一,拦截器:
主要两个文件,一个是创建拦截器:ProjectInterceptor.java,
另一个是注册该拦截器:SpringMvcSupport
创建拦截器:
@Controller public class ProjectInterceptor implements HandlerInterceptor{ //继承该HandlerInterceptor接口,按alt+Ins重写方法 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截之前"); return false; //true表示放行,false表示拦截并终止 } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("拦截之后"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("拦截完成"); } }
注册拦截器:
@Controller public class SpringMvcSuppor implements WebMvcConfigurer { @Resource private ProjectInterceptor pp; //导入拦截器 public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(pp).addPathPatterns("/**").excludePathPatterns("/user/**") //这个表示拦截所有请求路径,但/user开头的路径不进行拦截 registry.addInterceptor(pp).addPathPatterns("/**","/aa/**").excludePathPatterns("/cc", "/book/**") //这个就表示拦截两个路径,排除两个路径 //通过这个只是想说明可以同时传递多个参数用来拦截或排除路径 ; } }
总结:拦截器是对指定路径进行拦截处理,处理成功后就直接放行
二,全局异常处理器
主要分为:自定义异常,抛出异常,捕获异常
自定义异常:
public class RunTimeE extends RuntimeException{ //这个类名是随便起的,继承RuntimeException的作用是能够保证编译过程可以正常通过,而不会因为异常导致编译失败 String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public RunTimeE(String msg) { this.msg = msg; } }
抛出异常:
@RequestMapping("/aa") @RestController public class AAController { @RequestMapping("/bb") public String ee(){ try { int i=1/0; } catch (Exception e) { throw new RunTimeE("我失败了"); } return "成功"; } }
捕获异常:
@RestControllerAdvice public class ProjectExceptionHandler { @ExceptionHandler(RunTimeE.class) public String aa(RunTimeE e){ return e.getMsg(); } }
当访问“/aa/bb" , 打印的结果是”我失败了"
三,过滤器
过滤器主要用于处理请求之前或响应之后修改它们,我们可以使用Filter接口实现一个过滤器
过滤器的注册有两种方法
第一种(这是常用的一种方法,它能指定优先级)
直接创建一个过滤器到IOC容器中,在IOC容器中能够自动识别对应的过滤器并让它发挥作用
import javax.servlet.Filter; //该接口来自这个包 @Component @Order(-1) //当有多个Filter时,数值越小,优先级就越高 public class MyFilter implements Filter { //继承了Filter接口就表示该Bean对象是一个过滤器对象 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("请求之前"); chain.doFilter(request,response); //将请求进行放行,你也可以将这个看成是将目标函数复制到这里来了, //其实这个就相当于代指所要运行的目标函数 request.getParameter("name") //获取请求体中的get请求参数 System.out.println("响应之后"); } } //一个接口 @RequestMapping("/aa") public String aa(){ System.out.println("运行中"); return "成功"; } 当发送接口:localhost:8080/aa?name=zhan 打印结果为: 请求之前 运行中 zhan 响应之后
第二种:通过 @WebFilter 注解来标记一个 Filter过滤器,但是要在启动类中注册该过滤器
(这是比较老的一种方式,一般不常用)
首先标注过滤器:
@WebFilter(urlPatterns = "/*") public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("-----doFilter-----"); chain.doFilter(request, response); } }
-
-
-
-
然后在启动类中注册该过滤器
@SpringBootApplication @ServletComponentScan public class FilterdemoApplication { public static void main(String[] args) { SpringApplication.run(FilterdemoApplication.class, args); } }//@ServletComponentScan 注解虽然名字带了 Servlet, //但是实际上它不仅仅可以扫描项目中的 Servlet 容器,也可以扫描 Filter 和 Listener //只要被扫描到,它就能自动发挥作用
总结:过滤器可以对任何请求进行预处理,是无法终止请求的
过滤器的实际应用方法:
import javax.servlet.Filter; //该接口来自这个包
@Component
@Order(-1) //当有多个Filter时,数值越小,优先级就越高
public class MyFilter implements Filter { //继承了Filter接口就表示该Bean对象是一个过滤器对象
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("请求之前");
String name=request.getParameter("name") //获取请求体中的get请求参数
if(name.equals("zhan"){
chain.doFilter(request,response); //将请求进行放行,你也可以将这个看成是将目标函数复制到这里来了,
}else{
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("你好"); //这个就是直接使用响应体的数据流打印结果
}
System.out.println("响应之后");
}
}
//一个接口
@RequestMapping("/aa")
public String aa(){
System.out.println("运行中");
return "成功";
}
当发送接口:localhost:8080/aa?name=zhan
打印结果为:
请求之前
运行中
响应之后
响应结果是: 成功
当发送接口: localhost:8080/sldk/sel
打印结果是:
请求之前
响应之后
响应结果是: 你好
从这两个接口运行可以看出,如果没有传递get参数: name
那么目标函数就不会被调用,可以直接通过响应体响应出你指定的数据
在响应数据给别人之后,过滤器中的函数还是接着往下运行,直到运行完毕