前段时间对项目进行改造,需要实现对请求参数进行解密,再传输到控制层。参考了网上的一些文章,基本都是通过过滤器和实现RequestBodyAdvice接口进行处理。结合自己的项目要求,实现RequestBodyAdvice接口只能对参数在请求体中(@RequestBody)才生效,而项目中需要对get和post请求都进行处理,所以最后决定使用过滤器来实现。这里记录下代码实现,方便以后遇到相似的功能就不需要再去网上搜了。
首先需要继承HttpServletRequestWrapper类来自定义一个Request类,因为post请求需要使用request.getInputStream()来读取请求体中的参数,而流中的数据读取一次后就不能再读取了,这样传输到控制层就没有参数了,所以需要自定义一个request进行包装,将读取的参数处理后重新放回request中。
public class MyHttpRequest extends HttpServletRequestWrapper {
/**
* 保存流数据
*/
private final byte[] body;
/**
* 保存参数
*/
private Map<String, String[]> params = new HashMap<>();
public MyHttpRequest(HttpServletRequest request) {
super(request);
body = getBodyString(request).getBytes(StandardCharsets.UTF_8);
this.params.putAll(request.getParameterMap());
}
public MyHttpRequest(HttpServletRequest request, byte[] body) {
super(request);
this.body = body;
this.params.putAll(request.getParameterMap());
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return bais.read();
}
};
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
public void setParameter(Map<String, String> map) {
params.clear();
map.forEach((key, value) -> params.put(key, new String[]{value}));
}
public String getBody() {
return new String(body);
}
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
然后自定义一个过滤器,实现Filter接口
@WebFilter(filterName = "customParamFilter", urlPatterns = {"/*"})
public class CustomParamFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
MyHttpRequest requestWrapper = new MyHttpRequest(request);
try {
// get请求
if (requestWrapper.getMethod().equals(HttpMethod.GET.name())) {
// 对参数进行处理,得到新的参数,将参数重新设置到request中
Map<String, String> params = handle(requestWrapper.getParameterMap());
requestWrapper.setParameter(params);
} else { // post请求,这里没有对x-www-form-urlencoded类型进行处理
String body = requestWrapper.getBody();
if (StringUtils.isNotEmpty(body)) {
JSONObject jsonObject = JSONObject.parseObject(body);
// 对参数进行处理
Map<String, String> params = handle(jsonObject);
// 由于body是设置成不可变的,所以需要重新创建一个request,将body设置进去
requestWrapper = new MyHttpRequest(requestWrapper, JSONObject.toJSONString(params).getBytes());
}
}
filterChain.doFilter(requestWrapper, servletResponse);
} catch (Exception ex) {
outErrorMessage(servletResponse, ExceptionConfig.BUSINESS_CODE, ExceptionConfig.BUSINESS_MSG);
}
}
public void outErrorMessage(ServletResponse servletResponse, Integer code, String msg) throws IOException {
//返回json错误
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("application/json; charset=utf-8");
PrintWriter out = servletResponse.getWriter();
JSONObject res = new JSONObject();
res.put("code", code);
res.put("msg", msg);
out.append(JSON.toJSONString(res));
}
}
类上加@WebFilter使过滤器生效即可。
————————————————
版权声明:本文为CSDN博主「指尖凉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hsz2568952354/article/details/119882809