过滤器和拦截器

情到浓时终转凉″ 提交于 2019-12-11 07:36:45

一、参考

1.1 chain.doFilter(request,response)
过滤器中的chain.doFilter(request,response)

1.2 Filter过滤器及其作用介绍

Filter过滤器及其作用介绍

1.3 spring boot 过滤器、拦截器的区别与使用

spring boot 过滤器、拦截器的区别与使用

1.4 getParameter和getAttribute区别(超详细分析)

getParameter和getAttribute区别(超详细分析)

1.5 过滤器执行顺序

过滤器执行顺序

二、过滤器

2.1 简单例子

package com.example.demo.Filter;

import org.apache.coyote.Response;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.xml.crypto.dsig.spec.XPathType;
import java.io.IOException;
import java.io.PrintWriter;

@Component
@WebFilter(filterName = "myFilter",urlPatterns = "http://localhost:8080/Hello")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println(filterConfig.getFilterName());
        String initParameter = filterConfig.getInitParameter("name");
        ServletContext servletContext = filterConfig.getServletContext();
        System.out.println(servletContext.getContextPath());
        System.out.println("初始化了");
    }

    @Override
    public void destroy() {
        System.out.println("销毁了");
    }

    @Override
    public void doFilter(ServletRequest request , ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String sname = request.getParameter("sname");
        System.out.println(sname);
        String s = sname + "这是一个被改变的名字";
        request.setAttribute("name",s);
        System.out.println("过滤器处理");
        System.out.println("请求" + request.getProtocol());
        System.out.println("请求" + request.getServerName());
        System.out.println("请求" + request.getServerPort());
        System.out.println("请求" + request.getCharacterEncoding());
        chain.doFilter(request,response);
        System.out.println("返回" + response.getLocale());
        System.out.println("返回的编码格式" + response.getCharacterEncoding());
    }
}

2.2 controller

@RestController
public class HelloController {
    @RequestMapping(value = "/Hello",method = RequestMethod.GET)
    public String sayHello(@RequestParam("sname") String name, HttpServletRequest request, Model model){
        System.out.println("Controller " + request.getAttribute("name"));
        return "hello " + name;
    }
}

2.3 结果

jack
过滤器处理
请求HTTP/1.1
请求localhost
请求8080
请求UTF-8
Controller jack这是一个被改变的名字
返回zh_CN
返回的编码格式UTF-8

2.4 过滤器执行顺序

第一个过滤器开始处理
第二个过滤器开始处理
第三个过滤器开始处理
controller开始执行
controller开始返回
第三个过滤器返回
第二个过滤器返回
第一个过滤器返回

2.5 定义过滤器执行顺序

  • @Order注解
    order里面的值越小,过滤器越优先执行
@Component
@Order(3)
@WebFilter(urlPatterns = "http://localhost:8080/Hello")
public class MyFilter implements Filter {
.....
}

三、注意的点

3.1 response.setCharacterEncoding

response.setCharacterEncoding("UTF-8"); 在Servlet2.3中是不行的,至少要2.4版本才可以,如果低于2.4版本,可以用如下办法:

response.setContentType("text/html;charset=UTF-8");

3.2 request.setCharacterEncoding()

  • 只对post方式有效

四、Spring mvc中的拦截器

4.1 spring mvc中的拦截器HandlerInterceptor

  • 实现实现HandlerInterceptor接口
  • 继承HandlerInterceptorAdapter类

4.2 执行过程

  • 根据请求找到对应的HandlerExecutionChain,它包含了处理请求的handler和HandlerInterceptor拦截器,然后在调用handler之前,调用handlerinterceptor的prehandler方法,若有一个拦截器返回false,则会调用triggerAfterCompletion方法,并且立即返回不再往下执行;若所有的拦截器全部返回true并且没有出现异常,则调用handler返回ModelAndView对象;再然后分别调用每个拦截器的postHandle方法;最后,即使是之前的步骤抛出了异常,也会执行triggerAfterCompletion方法。

4.3 执行顺序

  • 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new Interceptor1()).addPathPatterns("/Hello");
        registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");
        registry.addInterceptor(new Interceptor3()).addPathPatterns("/**");
        registry.addInterceptor(new Interceptor4()).addPathPatterns("/**");
    }
}
拦截器1请求前处理
拦截器2请求前处理
拦截器3请求前处理
拦截器4请求前处理
controller开始执行
controller开始返回
拦截器4请求后处理
拦截器3请求后处理
拦截器2请求后处理
拦截器1请求后处理
拦截器4释放资源的操作
拦截器3释放资源的操作
拦截器2释放资源的操作
拦截器1释放资源的操作

4.4 拦截器的常用方法

  • preHandle()
    在请求被执行前执行,可以做一些登录验证等等
  • postHandle()
    请求处理完后进行,可以做一些打印日志,输出异常等一些工作
  • afterCompletion()
    请求处理完后执行可以做一些关闭资源,释放连接等一些工作。

该方法将Controller层的异常封装了,可以直接得到Controller层的异常信息。8

4.5 拦截器出现异常

  • 拦截器3出现异常(preHandler()方法执行时出现异常)
拦截器1请求前处理
拦截器2请求前处理
拦截器3请求前处理
拦截器2释放资源的操作
拦截器1释放资源的操作
  • 拦截器3出现异常(postHandler()方法执行时出现异常)
拦截器1请求前处理
拦截器2请求前处理
拦截器3请求前处理
拦截器4请求前处理
controller开始执行
controller开始返回
拦截器4请求后处理
拦截器4释放资源的操作
拦截器3释放资源的操作
拦截器2释放资源的操作
拦截器1释放资源的操作
  • 拦截器3出现异常(afterCompletion()方法执行时出现异常)
拦截器1请求前处理
拦截器2请求前处理
拦截器3请求前处理
拦截器4请求前处理
controller开始执行
controller开始返回
拦截器4请求后处理
拦截器3请求后处理
拦截器2请求后处理
拦截器1请求后处理
拦截器4释放资源的操作
{Exception......}
拦截器2释放资源的操作
拦截器1释放资源的操作

  • Controller层出现异常
拦截器1请求前处理
拦截器2请求前处理
拦截器3请求前处理
拦截器4请求前处理
拦截器4释放资源的操作
拦截器3释放资源的操作
拦截器2释放资源的操作
拦截器1释放资源的操作
{Exception...}
拦截器2请求前处理
拦截器3请求前处理
拦截器4请求前处理
拦截器4请求后处理
拦截器3请求后处理
拦截器2请求后处理
拦截器4释放资源的操作
拦截器3释放资源的操作
拦截器2释放资源的操作

4.6 参考

SpringBoot起飞系列-拦截器和统一错误处理(七)
springboot-拦截器
Spring中的拦截器

五、Spring中的拦截器

5.1 实现方式

  • 一种是实现MethodInterceptor接口
  • 另一种利用AspectJ的注解或配置。

5.2 参考

Spring AOP SpringBoot集成

5.3 处理顺序

  • Controller层没有异常发生并且执行around中的proceed()方法。
around前处理
before前处理
不知道拦截器能起作用不
around后处理
after后处理
返回前处理
  • Controller层发生异常未捕获并且执行around中的proceed()方法。
around前处理
before前处理
after后处理
抛出异常处理
  • around模块发生异常
around前处理
after后处理
抛出异常处理
  • before模块发生异常
around前处理
after后处理
抛出异常处理
  • after模块抛出异常
around前处理
before前处理
抛出异常处理

5.4 示例代码

package com.example.demo.AspectTj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ForkJoinTask;

@Component
@Aspect
public class AspectTjIntercept {
    Logger logger = LoggerFactory.getLogger(AspectTjIntercept.class);
    @Pointcut("execution(* com.example.demo.AspectTj.AspectController.*(..))")
    public void test(){

    }
    @Before("test()")
    public void setBefore(JoinPoint joinPoint){
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        /*HttpServletRequest request = servletRequestAttributes.getRequest();
        System.out.println(request.getContextPath());
        System.out.println(request.getRemoteAddr());
        System.out.println(request.getRequestURL());
        System.out.println(joinPoint.getSignature().getDeclaringTypeName());
        System.out.println(joinPoint.getArgs().toString());*/
        System.out.println("before前处理");
    }
    @After("test()")
    public void steAfter(){
        System.out.println("after后处理");
    }
    @Around("test()")
    public void setAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("around前处理");
        point.proceed();
        System.out.println("around后处理");
    }
    @AfterReturning("test()")
    public void afterReturn(){
        System.out.println("返回前处理");
    }
    @AfterThrowing("test()")
    public void haha(){
        System.out.println("抛出异常处理");
    }
}

5.5 @Around

 @Around("test()")
    public void setAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("around前处理");
        System.out.println(point.getSignature().getDeclaringTypeName());
        System.out.println(point.getSignature().getDeclaringType());
        System.out.println(point.getSignature().getName());
        System.out.println(point.getSignature().getModifiers());
        point.proceed();
        System.out.println("around后处理");
    }

5.6 @After

  • 无论是否发生异常,都会执行。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!