一、参考
1.1 chain.doFilter(request,response)
过滤器中的chain.doFilter(request,response)
1.2 Filter过滤器及其作用介绍
1.3 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 参考
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
- 无论是否发生异常,都会执行。
来源:CSDN
作者:初心魏
链接:https://blog.csdn.net/qq_42306803/article/details/103441307