OncePerRequestFilter和HttpServl

场景

  • 修改请求中的参数,某字段加密(接口需要解密后的数据),此处统一解密
  • 请求参数和响应结果,记录日志/存数据库
  • 在请求参数中添加 额外字段(标识某些系统等)

OncePerRequestFilter

GET方式

getParameterMap(),只能够获取到GET请求的参数

1
2
3
4
5
6
7
8
9
java复制代码//请求参数
parameterMap = httpRequest.getParameterMap();


//下为通用
//请求方式
String requestMethod = httpRequest.getMethod();
String remoteAddr = httpRequest.getRemoteAddr();
int remotePort = httpRequest.getRemotePort();

注意:异常 No modifications are allowed to a locked ParameterMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
java复制代码//类 org.apache.catalina.util.ParameterMap
@Override
public V put(K key, V value) {
checkLocked();
return delegatedMap.put(key, value);
}
private void checkLocked() {
if (locked) {
throw new IllegalStateException(sm.getString("parameterMap.locked"));
}
}

//类 org.apache.tomcat.util.res.StringManager
public String getString(String key) {
if (key == null){
String msg = "key may not have a null value";
throw new IllegalArgumentException(msg);
}

String str = null;

try {
// Avoid NPE if bundle is null and treat it like an MRE
if (bundle != null) {
str = bundle.getString(key);
}
} catch (MissingResourceException mre) {
//bad: shouldn't mask an exception the following way:
// str = "[cannot find message associated with key '" + key +
// "' due to " + mre + "]";
// because it hides the fact that the String was missing
// from the calling code.
//good: could just throw the exception (or wrap it in another)
// but that would probably cause much havoc on existing
// code.
//better: consistent with container pattern to
// simply return null. Calling code can then do
// a null check.
str = null;
}

return str;
}

/*错误码对应文件 tomcat下 org.apache.catalina.util.LocalStrings.properties
PropertyResourceBundle bundle会在服务启动加载到内存
*/
parameterMap.locked=No modifications are allowed to a locked ParameterMap

//类 java.util.PropertyResourceBundle
private final Map<String,Object> lookup;
public PropertyResourceBundle (Reader reader) throws IOException {
Properties properties = new Properties();
properties.load(reader);
lookup = new HashMap(properties);
}
public Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException();
}
return lookup.get(key);
}

POST方式

POST的请求参数是在请求体body中,而body参数是以流形式存在的。

1
2
3
4
5
6
7
8
9
Java复制代码ServletInputStream inputStream = httpRequest.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,StandardCharsets.UTF_8);
BufferedReader bfReader = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bfReader.readLine()) != null){
sb.append(line);
}
System.out.println(sb.toString());

注意:异常 request body missing

过滤器获得POST请求参数,但是controller层报错。

httpRequest.getInputStream() 只能使用一次,再次使用报错

1
2
3
4
5
6
7
8
9
arduino复制代码InputStream read方法内部有一个postion标志。
当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,InputStream.read方法会返回-1。

如果想再次读取,可调用inputstream.reset方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读。

是否能reset又是由markSupported决定的,为true能reset,为false就不能reset。
从源码可以看到,markSupported是为false的,而且一调用reset就是直接异常。

需要将读取到的InputStream 保存下来,使用HttpServletRequestWrapper进行处理

继承并重写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Java复制代码@Component
@Slf4j
public class ParamFilter extends OncePerRequestFilter {

@Value("${app.self.name}")
private String selfName;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {

RequestParameterWrapper requestWrapper=null;
String method=request.getMethod();
if("GET".equalsIgnoreCase(method)){
try {
requestWrapper = new RequestParameterWrapper(request, RequestMethod.GET);
Map<String, String[]> parameterMap = new HashMap<>(requestWrapper.getParameterMap());
log.info("get 参数={}", parameterMap.toString());
parameterMap.put("selfName", new String[]{selfName});
requestWrapper.setParameterMap(parameterMap);
}catch (Exception e){
e.printStackTrace();
}
}else if("POST".equals(method)){
try {
requestWrapper = new RequestParameterWrapper(request, RequestMethod.POST);
//获取post消息体
String body = requestWrapper.getBody();
JSONObject jsonObject = new JSONObject(body);
String dataAuthCode = (String) jsonObject.get("selfName");
if (StringUtils.isNotBlank(dataAuthCode)) {
chain.doFilter(request, response);
} else {
jsonObject.put("selfName", selfName);
requestWrapper.setBody(jsonObject);
}

}catch (Exception e){
e.printStackTrace();
}
}

if(requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
}

继承HttpServletRequestWrapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
java复制代码public class RequestParameterWrapper extends HttpServletRequestWrapper {

private String body;

private Map<String, String[]> parameterMap;

public RequestParameterWrapper(HttpServletRequest request, RequestMethod method) throws Exception{
super(request);

if(RequestMethod.POST.equals(method)){
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));) {
char[] charBuffer = new char[128];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} catch (Exception ex) {
throw ex;
}
body = stringBuilder.toString();
}else if(RequestMethod.GET.equals(method)){
parameterMap=request.getParameterMap();
}

}

public String getBody() {
return this.body;
}

/**
* post方式使用
* @param object
*/
public void setBody(JSONObject object) {
this.body=object.toString();
}



@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {

}

public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}


@Override
public Enumeration<String> getParameterNames() {
Vector<String> vector = new Vector<String>(parameterMap.keySet());
return vector.elements();
}

@Override
public String getParameter(String name) {
String[] results = parameterMap.get(name);
return results[0];
}

@Override
public Map<String, String[]> getParameterMap() {
return parameterMap;
}

@Override
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}

public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%