
1. preface
ServletRequest
We did it. Java Web
who have frequent contacts Servlet Api
。Sometimes we have to do some operations on it often. Here are some frequently difficult operations.
2. Extract data from the body
Front-end interaction, we will body
Transfer data in. How do we start body
Extract data from. Normally we would pass IO
Operation:
/**
* 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();
}
It looks messy, with various exception handling,IO
Switch operation is not elegant. if you use Java 8 You can simplify this operation like this:
String body = request.getReader().lines().collect(Collectors.joining());
BufferedReader
Provides access Java 8 Stream flow method lines()
, we can obtain it very easily through the above methods ServletRequest
of body
3. Streams in ServletRequest are one-time
Don't think that the reading above body
The operation was flawless and there was a pit here.If you follow the above operation ServletRequest
of body
Read only once。The data we transmit is transmitted through streaming.ServletRequest
In fact, we all pass:
ServletInputStream inputStream = request.getInputStream()
to get the input stream, and then pass the read
Series methods to read.Java
of InputStream
read
There is a method insidepostion
, ** Its function is to mark the location where the current stream is read. Each time it is read, the location will move once. If it reaches the end,read
method returns -1
, the flag has been read. If you want to read again, you can call reset
Methods,position
it moves to the last call mark
location,mark
default is 0
, so you can read it from the beginning.
can reset
is conditional, and it depends on markSupported()
,markSupported()
Method returns whether it can be performed mark/reset
。
Let's look back ServletInputStream
, its implementation is not rewritten reset
Method does not support mark/reset
。soServletRequest
of IO stream
Read only once.
4. Stream in ServletRequest can be read repeatedly
If we use multiple Servlet Filter
Make chain calls and operate multiple times ServletRequest
What should flow in the middle do? we can Servlet Api
provided javax.servlet.http.HttpServletRequestWrapper
to package it. through inheritance 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);
}
}
The following is in a Servlet Filter
Standard examples in:
public class TestFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//Packaging
ReaderRequest cachingRequestWrapper=new ReaderRequest((HttpServletRequest) servletRequest);
//Read directly from packaging
String collect = cachingRequestWrapper.getReader().lines().collect(Collectors.joining());
//Delivery packaging
filterChain.doFilter(cachingRequestWrapper, servletResponse);
}
}
5. How to set Parameter () on ServletRequest
When data is passed in from the front end, it is passed in the background HttpServletRequest
of getParameter(String name)
Methods to obtain data. If the background wants to put data in and use it for the next request or other request, you can only use it throughsetAttribute(String name, Object o)
Put it in and then start from getAttribute(String name)
Get, cannot pass getParameter(String name)
Get. I'm Spring Security Practical Dry Goods: Playing with Custom Login I encountered this problem
First of all,getParameter(String name)
It is only effective after the data is transferred from the client to the server, but it is an internal matter of the server and can only be invoked on the server. setAttribute(String name, Object o)
After that, and without redirection (redirect
), before going to the client getAttribute(String name)
Only then will it be effective.
If you want to use setParameter() during the server transfer process, we can use the getParameter(String name)
entrusted to getAttribute(String name)
to execute. Relevant realization still passes javax.servlet.http.HttpServletRequestWrapper
to achieve it.
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);
}
}
You can also learn from ideas to achieve other functions you need.
6. summary
Today we are interested ServletRequest
Some commonly used operations are explained. They are also some of the problems we often encounter in actual development. Of course, you can also use some third-party packages to solve these problems.
Comments0