Spring的理解:Filter与Intercepter

Filter是Servlet的规范,它的定义如下:

public interface Filter {

public void init(FilterConfig filterConfig)throwsServletException;

public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain)throwsIOException,ServletException;

public void destroy();

主要作用就是,对ServletRequest做预处理,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题

而Spring MVC是基于Servlet来响应用户请求对,所以,在Spring中可以可以用Filter来干预Http请求,解决诸如跨域、认证方面的要求。例子如下:

@Component

public classSimpleCORSFilterimplementsFilter {

public voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain)throwsIOException,

ServletException {

HttpServletResponse response = (HttpServletResponse) res;

response.setHeader("Access-Control-Allow-Origin","*");

response.setHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE");

response.setHeader("Access-Control-Max-Age","3600");

response.setHeader("Access-Control-Allow-Headers","Token,Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since");

chain.doFilter(req,res);

}

public voidinit(FilterConfig filterConfig) {}

public voiddestroy() {}

}

而拦截器,是基于Spring IOC的。可以在方法级别,对流程进行预处理、后处理、综合(前后同时)处理。我们需要做的就是:

1、创建自己的拦截器实现HandlerInterceptor接口

2.  加入到拦截器链条,继承WebMvcConfigurerAdapter类,重写addInterceptors方法

    将拦截器加入到拦截链条(需要添加拦截规则),如下:

public class CustomInterceptor implements HandlerInterceptor {

@Override

public void afterCompletion (HttpServletRequest request,  HttpServletResponse response,  Object object, Exception exception)throwsException {

//在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)

System.out.println("3. 整个请求结束之后被调用......CustomInterceptor1......");

}

@Override

publicvoidpostHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView view)

throwsException {

// 请求处理之后进行调用,但是在视图被渲染之前

System.out.println("2. 请求处理之后进行调用,但是在视图被渲染之前......CustomInterceptor1......");

}

@Override

publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object object)throwsException {

// 在请求处理之前进行调用

System.out.println("1. 在请求处理之前进行调用......CustomInterceptor1......");

// 只有返回true才会继续向下执行,返回false取消当前请求

returntrue;

}

@Configuration

publicclassWebAdapterextendsWebMvcConfigurerAdapter{

@Override

publicvoidaddInterceptors(InterceptorRegistry registry) {

//众多的拦截器组成了一个拦截器链

/**

* 主要方法说明:

* addPathPatterns 用于添加拦截规则

* excludePathPatterns 用户排除拦截

*/

registry.addInterceptor(newCustomInterceptor()).addPathPatterns("/*");

registry.addInterceptor(newCustomInterceptor2()).addPathPatterns("/*");

super.addInterceptors(registry);

}


或者直接写一个完整的自定义拦截器

@Aspect

@Component

public classControllerInterceptor {

private static finalLoggerlogger= LoggerFactory.getLogger(ControllerInterceptor.class);

@Value("${spring.profiles}")

privateStringenv;

/**

* 定义拦截规则:拦截com.xjj.web.controller包下面的所有类中,有@RequestMapping注解的方法。

*/

@Pointcut("execution(* com.xjj.web.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)")

public voidcontrollerMethodPointcut(){}

/**

* 拦截器具体实现

*@parampjp

*@returnJsonResult(被拦截方法的执行结果,或需要登录的错误提示。)

*/

@Around("controllerMethodPointcut()")//指定拦截器规则;也可以直接把“execution(* com.xjj.........)”写进这里

public Object Interceptor(ProceedingJoinPoint pjp){

long beginTime = System.currentTimeMillis();

Method Signature signature = (MethodSignature) pjp.getSignature();

Method method = signature.getMethod();//获取被拦截的方法

String methodName = method.getName();//获取被拦截的方法名

Set allParams =newLinkedHashSet<>();//保存所有请求参数,用于输出到日志中

logger.info("请求开始,方法:{}",methodName);

Object result =null;

Object[] args = pjp.getArgs();

for(Object arg : args){

//logger.debug("arg: {}", arg);

if(arginstanceofMap) {

//提取方法中的MAP参数,用于记录进日志中

@SuppressWarnings("unchecked")

Map map = (Map) arg;

allParams.add(map);

}else if(arginstanceofHttpServletRequest){

HttpServletRequest request = (HttpServletRequest) arg;

if(isLoginRequired(method)){

if(!isLogin(request)){

result =newJsonResult(ResultCode.NOT_LOGIN,"该操作需要登录!去登录吗?", null);

}

}

//获取query string 或 posted form data参数

Map paramMap = request.getParameterMap();

if(paramMap!=null&& paramMap.size()>0){

allParams.add(paramMap);

}

}else if(arginstanceofHttpServletResponse){

//do nothing...

}else{

//allParams.add(arg);

}

}

try{

if(result ==null){

// 一切正常的情况下,继续执行被拦截的方法

result = pjp.proceed();

}

}catch(Throwable e) {

logger.info("exception: ",e);

result =newJsonResult(ResultCode.EXCEPTION,"发生异常:"+e.getMessage());

}

if(resultinstanceofJsonResult){

longcostMs = System.currentTimeMillis() - beginTime;

logger.info("{}请求结束,耗时:{}ms",methodName,costMs);

}

returnresult;

}

/**

* 判断一个方法是否需要登录

*@parammethod

*@return

*/

private booleanisLoginRequired(Method method){

if(!env.equals("prod")){//只有生产环境才需要登录

return false;

}

booleanresult =true;

if(method.isAnnotationPresent(Permission.class)){

result = method.getAnnotation(Permission.class).loginReqired();

}

returnresult;

}

//判断是否已经登录

private booleanisLogin(HttpServletRequest request) {

return true;

/*String token = XWebUtils.getCookieByName(request, WebConstants.CookieName.AdminToken);

if("1".equals(redisOperator.get(RedisConstants.Prefix.ADMIN_TOKEN+token))){

return true;

}else {

return false;

}*/

}

}

你可能感兴趣的:(Spring的理解:Filter与Intercepter)