1. Введение
ServletRequestэто мыJava Webчасто связываютсяServlet Api. Иногда нам приходится часто выполнять над ним некоторые операции. Вот некоторые часто трудные операции.
2. Извлеките данные из тела
Для интерфейсных и внутренних взаимодействий мы будемbodyпередать данные. Как мы получаем отbodyизвлечь данные. Обычно мы проходимIOработать:
/**
* obtain request body
*
* @param request the ServletRequest
* @return body string it maybe is null
*/
public static String obtainBody(ServletRequest request) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
br = request.getReader();
String str;
while ((str = br.readLine()) != null) {
sb.append(str);
}
br.close();
} catch (IOException e) {
log.error(" requestBody read error");
} finally {
if (null != br) {
try {
br.close();
} catch (IOException e) {
log.error(" close io error");
}
}
}
return sb.toString();
}
Выглядит грязно, с различной обработкой исключений,IOПереключение операции, очень неэлегантно. если вы использовалиJava 8Вы можете упростить эту операцию следующим образом:
String body = request.getReader().lines().collect(Collectors.joining());
BufferedReaderобеспечивает доступ кJava 8 Streamпроточный методlines(), мы можем легко получитьServletRequestсерединаbody
3. Потоки в ServletRequest одноразовые
Не думайте, что выше читаетсяbodyОперация безупречна, здесь есть дыра.Если вы будете следовать вышеизложенномуServletRequestсерединаbodyчитать только один раз. Все данные, которые мы передаем, передаются через потоки.ServletRequestв котором мы фактически переходим:
ServletInputStream inputStream = request.getInputStream()
чтобы получить входной поток, затем передайтеreadряд методов для чтения.JavaсерединаInputStream readВнутри метода естьpostion, ** Его функция состоит в том, чтобы отметить позицию, прочитанную текущим потоком.Каждый раз при чтении позиция будет перемещаться один раз.Если она прочитана до конца,readметод вернет-1, флаг был прочитан, если вы хотите прочитать его снова, вы можете позвонитьresetметод,positionперейдет к последнему звонкуmarkпозиция,markПо умолчанию0, так что вы можете начать сначала.
могуresetусловно, зависит отmarkSupported(),markSupported()Можно ли выполнить возврат методаmark/reset.
давайте оглянемся назадServletInputStream, реализация которого не отменяетresetметод не поддерживаетсяmark/reset. такServletRequestсерединаIO流можно прочитать только один раз.
4. Повторяемый поток чтения в ServletRequest
Если мы используем несколькоServlet FilterСовершайте связанные вызовы и работайте несколько разServletRequestЧто делать с потоком в ? мы можем пройтиServlet Apiкоторый предоставилjavax.servlet.http.HttpServletRequestWrapperупаковать его. по наследствуHttpServletRequestWrapper :
public class ReaderRequest extends HttpServletRequestWrapper {
private String body;
public ReaderRequest(HttpServletRequest request) throws IOException {
super(request);
body = request.getReader().lines().collect(Collectors.joining());
}
@Override
public BufferedReader getReader() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
InputStreamReader inputStreamReader = new InputStreamReader(byteArrayInputStream);
return new BufferedReader(inputStreamReader);
}
}
Следующее находится вServlet FilterСтандартный пример в:
public class TestFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 包装
ReaderRequest cachingRequestWrapper=new ReaderRequest((HttpServletRequest) servletRequest);
// 直接从包装读取
String collect = cachingRequestWrapper.getReader().lines().collect(Collectors.joining());
// 传递包装
filterChain.doFilter(cachingRequestWrapper, servletResponse);
}
}
5. Как установитьParameter() в ServletRequest
Когда данные передаются с переднего плана, фон проходитHttpServletRequestсерединаgetParameter(String name)способ получения данных. Если фон хочет поместить в него данные, его можно использовать только в следующем запросе или другом запросе.setAttribute(String name, Object o)вставить, а затем изgetAttribute(String name)получить, потерпеть неудачуgetParameter(String name)Получать. я здесьПрактичные галантереи Spring Security: поэкспериментируйте с пользовательским входом в системутолько что столкнулся с этой проблемой
Сначала позвольте мне сказатьgetParameter(String name)Действителен после отправки данных от клиента на сервер, при этом это внутреннее дело сервера, только при вызове сервераsetAttribute(String name, Object o)после этого и редиректа нет(redirect), до поступления к клиентуgetAttribute(String name)чтобы быть эффективными.
Если мы хотим использовать setParameter() в процессе передачи сервера, мы можем передатьgetParameter(String name)ПорученоgetAttribute(String name)выполнить. Соответствующая реализация все еще проходитjavax.servlet.http.HttpServletRequestWrapperреализовать.
package cn.felord.spring.security.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @author Felordcn
* @since 2019/10/17 22:09
*/
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
public ParameterRequestWrapper(HttpServletRequest request ) {
super(request);
}
@Override
public String getParameter(String name) {
return (String) super.getAttribute(name);
}
}
Вы также можете учиться на идеях для достижения других необходимых вам функций.
6. Резюме
Сегодня мыServletRequestОбъяснены некоторые часто используемые операции. Это также некоторые проблемы, с которыми мы часто сталкиваемся в реальной разработке. Конечно, вы также можете использовать некоторые сторонние пакеты для решения этих проблем.
关注公众号:Felordcn获取更多资讯
Личный блог: https://felord.cn