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获取更多资讯