1. filter、interceptor、AOP 执行顺序
    1. filter 是容器(常放在servlet)自带的,interceptor 是 Spring MVC 自带的,后者是一个 Web 应用,是放在容器里面的,所以请求会先进入容器,再进入到应用,所以 filter 会比 interceptor 先执行
    2. 结论: fileter — interceptor — aop
  2. 基本构成
    1. filter 基于 servlet
    2. Interceptor aop 基于 spring 的
  3. https://blog.csdn.net/testcs_dn/article/details/80279578

1. 过滤器(Filter)

1.1 基础认知

  1. 首先过滤器是 JavaWeb 阶段的知识,但是现在的项目都是 SpringBoot 的,Web 阶段如何配置的暂时忽略
  2. 过滤器(Filter)是 J2EE Servlet 模块下的组件
  3. Filter 的作用是对 url 进行统一的拦截,常用于应用程序层面进行全局处理

    1.2 实现一个过滤器

  4. 任何过滤器都要实现 javax.servlet.Filter 接口

  5. 在 Filter 接口的 doFilter() 方法编写过滤器的功能代码
  6. 配置过滤器

    1. JavaWeb 版本:在 web.xml 中对过滤器进行配置,说明拦截的url范围
    2. SpringBoot 版本:注解、配置都可以

      1.3 JavaWeb版本

  7. 实现接口的代码就不写了,很简单,或者看看下面的版本

  8. 图一:如何在 web.xml 中对过滤器进行配置,说明拦截的 Url 范围
  9. 图二:注解如何配置
  10. 图三:配置化参数,可以提前设置一些设置,然后在初始化的时候取出来
  11. 图四:拦截支持正则匹配

image.png
image.png
image.png
image.png

1.4 SpringBoot版本

1.4.1 基础的Filter代码

  1. package com.kong.wiki.filter;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.stereotype.Component;
  5. import javax.servlet.*;
  6. import javax.servlet.http.HttpServletRequest;
  7. import java.io.IOException;
  8. /**
  9. * 接口计时
  10. *
  11. * @author YiHua
  12. * @date 2022/7/3
  13. */
  14. public class InterfaceTimeFilter implements Filter {
  15. private static final Logger log = LoggerFactory.getLogger(InterfaceTimeFilter.class);
  16. @Override
  17. public void init(FilterConfig filterConfig) throws ServletException {
  18. Filter.super.init(filterConfig);
  19. }
  20. @Override
  21. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  22. // 拿到请求,获取到想要的信息
  23. HttpServletRequest request = (HttpServletRequest) servletRequest;
  24. log.info("------------- 开始:接口开始被调用 -------------");
  25. log.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
  26. log.info("远程地址: {}", request.getRemoteAddr());
  27. long startTime = System.currentTimeMillis(); // 执行过滤器的链路,多个过滤器依次执行 ——> 执行业务代码,最后返回来,计算接口耗时
  28. filterChain.doFilter(servletRequest, servletResponse);
  29. log.info("------------- 结束:接口耗时:{} ms -------------", System.currentTimeMillis() - startTime);
  30. }
  31. @Override
  32. public void destroy() {
  33. Filter.super.destroy();
  34. }
  35. }

1.4.2 通过扫描注解完成Filter组件注册

  1. 在 Filter 实现类使用注解 @WebFilter,设置 filterName、urlPatterns、initParams 等参数
  2. 编写启动类:增加注解 @ServletComponentScan
  3. 如果有多个 Filter 可以用 @Order 注解指定执行顺序,序号越小,越早被执行,例如:@Order(1)

    1.4.3 通过配置类完成Filter组件注册

    ```java package com.yihua.mall.common.config;

import com.yihua.mall.common.filter.InterfaceTimeFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;

/**

  • Servlet级别的配置信息 *
  • @author YiHua
  • @date 2022/7/3 */ @Configuration public class ServletConfig { @Bean public FilterRegistrationBean getFilterRegistrationBean() {
    1. FilterRegistrationBean filter = new FilterRegistrationBean();
    2. filter.setFilter(new MyFilter());
    3. filter.addUrlPatterns(new String[] {"*.do","*.jsp"});
    4. filter.addUrlPatterns("/second");
    5. return bean;
    } } ```

    1.4.4 直接使用@Component注解完成注册

  1. 直接在实现的 xxxFilter 上新增 @Component 注解

    1.5 过滤器的生命周期

    image.png

    1.6 过滤器的特性

  2. 过滤器对象在应用程序启动时候被创建,且全局唯一,所以 destory() 在程序关闭才会执行

  3. 唯一的过滤器对象在并发环境中采用“多线程”提供服务

    1. 过滤器和 Servlet 一样采用单例多线程的并发模式
    2. 虽然全局只有一个对象,但是每一个请求过来了,过滤器都会为其创建一个线程提供服务

      2. 切面编程(AOP)

      3. 拦截器(Interceptor)

      3.1 基础认知

  4. 拦截器是 Spring MVC 提供的

  5. 用于对 Url 请求进行前置/后置的拦截处理
  6. 拦截器和过滤器的用途类似,但是实现方式不同
  7. 拦截器的底层是基于Spring AOP切面编程实现的,所以换句话说也就是基于反射实现的

    3.2 实现一个拦截器

  8. 继承和实现都可以

    1. 继承: HandlerInterceptorAdapter
    2. 实现: HandlerInterceptor
  9. 三个方法介绍
    1. preHandle:请求在调用 controller 之前
    2. postHandle:controller 执行之后,页面渲染之前(因为modelAndView)
    3. afterCompletion:页面渲染之后: 常用来关闭一些资源

      3.3 注册拦截器

      ```java package com.kong.wiki.core.configuration;

import com.kong.wiki.interceptor.InterfaceTimeInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.beans.factory.annotation.Autowired;

@Configuration public class SpringMVCConfiguration implements WebMvcConfigurer {

  1. /**
  2. * 拦截器配置的两种方式
  3. * 1. 直接配置Bean的方式,相当于在spring时代的配置xml文件
  4. * 2. 注入方式,但是拦截器需要加上@Component注解交给spring管理
  5. */
  6. // 注入这个拦截器
  7. @Autowired
  8. InterfaceTimeInterceptor interfaceTimeInterceptor;
  9. // 配置bean的方式
  10. @Bean
  11. public UserTokenInterceptor interfaceTimeInterceptor() {
  12. return new UserTokenInterceptor();
  13. }
  14. // 对拦截器进行一些配置,计算接口时间的直接默认权限路由
  15. public void addInterceptors(InterceptorRegistry registry) {
  16. // 这里添加的就是上面写的方法名称
  17. registry.addInterceptor(interfaceTimeInterceptor)
  18. // 那些接口需要经过这个拦截器
  19. .addPathPatterns("/**")
  20. // 排除某些接口:
  21. .excludePathPatterns("/login");
  22. }

}

  1. <a name="Cm1NU"></a>
  2. # 4. 监听器(Listener)
  3. 1. **监听器是 J2EE Servlet 模块下的组件**
  4. 1. **监听器的作用是对 Web 应用对象的行为进行监控**
  5. 1. **通过 Listener 监听自动触发指定的功能代码**
  6. 1. **内置对象监听接口,如下图所示**
  7. 1. **想要监听某个对象,只需要实现对应的监听器接口**
  8. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1656832624418-23cc8829-77ae-4218-89fe-d8827b92f428.png#clientId=ufbc61056-ae9a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=341&id=ue8f90a4b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=682&originWidth=1918&originalType=binary&ratio=1&rotation=0&showTitle=false&size=236502&status=done&style=none&taskId=uc5e2e87f-78a1-4e96-ba5c-1eec3374aee&title=&width=959)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1656832645132-a72ae62e-efaf-4ed5-b256-3d27661bb624.png#clientId=ufbc61056-ae9a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=340&id=u111cb63c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=680&originWidth=1918&originalType=binary&ratio=1&rotation=0&showTitle=false&size=236240&status=done&style=none&taskId=u986646a5-ddce-4487-9419-cc6f09e9c51&title=&width=959)
  9. <a name="YDjT1"></a>
  10. # 5. 参数校验
  11. <a name="WWzsO"></a>
  12. ## 5.1 路径参数校验
  13. 1. **在类上新增 **`**org.springframework.validation.annotation.Validated**`** 注解**
  14. 1. **在对应的参数前面加上常用、定制化的校验注解**
  15. 1. **常见的注解**
  16. 1. `**javax.validation.constraints.Max**`
  17. 1. `**javax.validation.constraints.Min**`
  18. 1. `**javax.validation.constraints.Positive**`
  19. 4. **注意:路径参数一般不做非空判断,需要的话可以设置**`**required = false**`
  20. <a name="aaZlY"></a>
  21. ## 5.2 请求对象参数校验
  22. 1. **使用 Spring 提供的**`**org.springframework.validation.annotation.Validated**`**注解**
  23. 1. **在类上新增该注解**
  24. 1. **在参数对象前面新增该注解**
  25. 2. **使用 Servlet 提供**`**javax.validation.Valid**`**注解**
  26. 1. **直接在参数对象前面新增该注解**
  27. <a name="VbrSz"></a>
  28. ## 5.3 嵌套对象的参数校验
  29. 1. **嵌套对象:指一个 model 是另外一个 model 的成员属性**
  30. 1. **方式一**
  31. 1. **类上、参数对象上新增 @Validated 注解**
  32. 1. **参数对象中的,嵌套 model 属性上新增 @Valid 注解**
  33. 3. **方式二**
  34. 1. **参数对象上新增 @Valid 注解 **
  35. 1. **参数对象中的,嵌套 model 属性上新增 @Valid 注解**
  36. <a name="tknWQ"></a>
  37. ## 5.4 常见的校验注解
  38. <a name="nSfZD"></a>
  39. ### 5.4.1 常见注解
  40. 1. **长度校验:**`**@Length(min = 2, max = 20)**`
  41. 1. **定义参数的范围:**`**@Range(min = 1, max = 10, message = "1~10欧 ")**`
  42. 1. **字段必须是正整数:**`**@Positive**`
  43. 1. **字段不能为空**
  44. 1. `**@NotEmpty**`**:用在集合类上面**
  45. 1. `**@NotBlank**`**:用在 String上面**
  46. 1. `**@NotNull**`**:用在基本类型上**
  47. <a name="J5RAs"></a>
  48. ### 5.4.2 自定义提示信息
  49. 1. **注解这边的操作**
  50. 1. `**@NotBlank(message = "{username.not-blank}")**`
  51. 1. `**@Positive(message = "{id.positive}")**`
  52. 2. **新增配置文件的操作**
  53. 1. `**ValidationMessages.properties**`
  54. 1. `**username.not-blank = 用户名不可为空**`
  55. 1. `**id.positive = id必须为正整数**`
  56. <a name="zYnDa"></a>
  57. ## 5.5 自定义校验注解
  58. 1. **定义需要的注解,例如:**`**@PasswordEqual**`
  59. 1. **使用注解关联业务类,例如:**`**@Constraint(validatedBy = PasswordValidator.class )**`
  60. 1. **业务类需要实现指定接口:**`**ConstraintValidator<T,K>**`
  61. 1. **实际的操作**
  62. 1. `**@TokenPassword**`
  63. 1. `**@Enum**`
  64. <a name="oHs8W"></a>
  65. # 6. Spring Data Jpa
  66. 1. **VO对象解决的一个问题:如果双向配置导航属性,会产生循环序列化,可能会内存溢出的**
  67. <a name="GuMPL"></a>
  68. # 使用配置的方式配置数据源
  69. 1. `**架构师 - 分布式事务 - 基于XA的两阶段提交 - 使用Atomikos的分布式事务**`
  70. 1. `**架构师 - Rabbit MQ章节 - 基础组件的封装部分**`
  71. 1. **类似于如下的代码**
  72. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1654437265527-e3fd11aa-a271-42ed-9ef7-d1ae57b9fb1b.png#clientId=u65615064-4bc9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=375&id=uc1cb55a2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=2178&originalType=binary&ratio=1&rotation=0&showTitle=false&size=218897&status=done&style=none&taskId=u6b176948-cba3-447f-894f-6fbb4d1d3f6&title=&width=1089)
  73. <a name="LEYmu"></a>
  74. # 事务问题
  75. ```sql
  76. @Transactional(rollbackFor = Exception.class)
  77. public Integer createOrder() throws Exception {
  78. }
  79. 默认是RunTimeException才会回滚异常,上面的指定什么异常都回滚