1、要写过滤器类,写注册过滤器的配置类,要重写HttpServletRequestWapper类,因为读取一次入参后,入参流为空
1、过滤器类(实现Filter接口)
package com.liu.web.Filter;
import com.alibaba.dubbo.common.utils.IOUtils;
import com.alibaba.fastjson.JSON;
import com.liu.web.utils.JsonUtils;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
//urlPatterns设置为/*对所有的路径进行拦截
@WebFilter(filterName = "UrlFilter" ,urlPatterns = "/filterTest/*")
public class UrlFilter implements Filter {
Logger logger = LoggerFactory.getLogger(UrlFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("--------初始化过滤器----------");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("------------执行过滤器--------------");
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
//getRequestURI:/test/test.jsp
//getRequestURL:http://localhost:8080/test/test.jsp
String uri = httpServletRequest.getRequestURI();
String cotentType = request.getContentType();
String method = httpServletRequest.getMethod();
logger.info("------method"+method);
logger.info("-------contentType"+cotentType);
// 类型为application/json用流接收参数
String decReqString ;
Map<String,String> paramMap = new HashMap();
if("application/json".equals(cotentType)) {
InputStreamReader reader = new InputStreamReader(request.getInputStream());
String reqStr = IOUtils.read(reader);
logger.info("--------加密的入参信息:" + reqStr);
//对加密的字符串进行解密
Map<String, Object> map = (Map) JsonUtils.convertJson2Object(reqStr, Map.class);
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if ("name".equals(key)) {
String value = (String) entry.getValue();
String decString = URLDecoder.decode(value, "utf-8");
paramMap.put(key, decString);
}
}
decReqString = JSON.toJSONString(paramMap);
logger.info("------解密后的入参信息:" + decReqString);
}else {
//其他请求类型方式获取参数
Enumeration<?> enumeration = httpServletRequest.getParameterNames();
if (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = httpServletRequest.getParameter(name);
String decString = URLDecoder.decode(value, "utf-8");
paramMap.put(name, decString);
}
decReqString = JSON.toJSONString(paramMap);
logger.info("------解密后的入参信息:" + decReqString);
}
if(!uri.contains("success")){
//可以直接放行调controller
chain.doFilter(request,response);
//不包含这个路径,到请求失败的页面,不可以使用重定向 httpServletRequest.getRequestDispatcher("/filterTest/failed").forward(request,response);
//重定向是两次请求
// httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/filterTest/failed");
logger.info("------转向的路径:"+httpServletRequest.getContextPath()+"/filterTest/failed");
}else{
//直接放行,进入输入的地址Controller
//xyHttpServletRequestWrapper为重写的类,必须写重写类,否则getInputStream只读取一次,,Controller入参为空
// decString为解密后的入参字符串
XyHttpServletRequestWrapper xyHttpServletRequestWrapper2 = new XyHttpServletRequestWrapper(httpServletRequest,decReqString);
chain.doFilter(xyHttpServletRequestWrapper2,response);
}
}
@Override
public void destroy() {
logger.info("--------摧毁过滤器----------");
}
}
2、继承HttpServletRequestWrapper,重写getInputStream方法,防止读取一次入参流之后为空
package com.liu.web.Filter;
import org.apache.catalina.servlet4preview.http.HttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
public class XyHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static final Logger logger = LoggerFactory.getLogger(XyHttpServletRequestWrapper.class);
private String responseBody;
private HttpServletRequest request;
public XyHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request=request;
}
public XyHttpServletRequestWrapper(HttpServletRequest request, String body) {
super(request);
this.request=request;
responseBody=body;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream(){
private ByteArrayInputStream in = new ByteArrayInputStream(responseBody.getBytes(request.getCharacterEncoding()));
@Override
public int read() {
return in.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
}
public String getResponseBody() {
return responseBody;
}
}
3、注册过滤器的配置类,可以在此类设置多个过滤器的顺序
package com.liu.web.Filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterRegister {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//添加自定义的过滤器1
filterRegistrationBean.setFilter(new UrlFilter());
设置为/*对所有的路径进行拦截
filterRegistrationBean.addUrlPatterns("/filterTest/*");
//多个拦截器时,设置拦截的顺序
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
// @Bean
// public FilterRegistrationBean filterRegistrationBean2(){
// FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
// //添加自定义的过滤器2
// filterRegistrationBean.setFilter(new UrlFilter());
// 设置为/*对所有的路径进行拦截
// filterRegistrationBean.addUrlPatterns("/filterTest/*");
// //多个拦截器时,设置拦截的顺序
// filterRegistrationBean.setOrder(2);
// return filterRegistrationBean;
// }
}
4、测试类
- 注意:通过过滤器的地址,需要加@RequestBody实体类和@RequestParam来接受入参
- 如果是加密后的入参,controller接受的还是加密后的入参
package com.liu.web.Filter;
import com.alibaba.dubbo.common.utils.IOUtils;
import com.liu.beans.OutputObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
@RestController
@RequestMapping("/filterTest")
public class FilterController {
Logger logger = LoggerFactory.getLogger(FilterController.class);
//通过过滤器的地址,类型为application/json用@RequestBody实体类获取,其他类型用@RequestParam接收参数
@RequestMapping("/success")
public void success(@RequestParam String userNm, @RequestParam MultipartFile file ){
try{
// logger.info("------filename="+filename);
logger.info("------------file length="+ org.apache.commons.io.IOUtils.toString(file.getInputStream()).length());
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.setContentType("image/jpeg;");
OutputStream out = response.getOutputStream();
out.write(org.apache.commons.io.IOUtils.toByteArray(file.getInputStream()));
out.flush();
}catch (Exception e){
}
//加密后的参数,通过过滤器后还是加密的
OutputObject out = new OutputObject();
logger.info("------------name="+userNm);
out.setReturnCode("0000");
out.setReturnMess("操作成功!!!!");
// return out;
}
@RequestMapping("/failed")
public OutputObject failed(){
OutputObject out = new OutputObject();
out.setReturnCode("9999");
out.setReturnMess("请求失败!!");
return out;
}
}