过滤器&拦截器

image.png
过滤器Filter
过滤器的实现基于回调函数
实现方式一:
1)创建类实现Filter接口;2)注入springboot容器(代码注入 / 通过注解@WebFilter注入)

  1. package com.duing.filter;
  2. import javax.servlet.*;
  3. import javax.servlet.annotation.WebFilter;
  4. import java.io.IOException;
  5. /**
  6. * 原先实现过滤器,需要在web.xml中进行配置,
  7. */
  8. public class CustomFilter implements Filter {
  9. @Override
  10. public void init(FilterConfig filterConfig) throws ServletException {
  11. System.out.println("CustomFilter init");
  12. }
  13. @Override
  14. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  15. System.out.println("CustomFilter doFilter");
  16. filterChain.doFilter(servletRequest, servletResponse);
  17. }
  18. @Override
  19. public void destroy() {
  20. System.out.println("CustomFilter destroy");
  21. }
  22. }
  1. package com.duing.config;
  2. import com.duing.filter.CustomFilter;
  3. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. //代替了web.xml文件
  7. @Configuration
  8. public class FilterConfig {
  9. @Bean
  10. public FilterRegistrationBean<CustomFilter> filterRegistrationBean(){
  11. FilterRegistrationBean<CustomFilter> filterRegistrationBean=
  12. new FilterRegistrationBean<>();
  13. filterRegistrationBean.setFilter(new CustomFilter());
  14. filterRegistrationBean.addUrlPatterns("/*");//过滤规则
  15. //filterRegistrationBean.setOrder(0);//决定注册的优先级
  16. return filterRegistrationBean;
  17. }
  18. }

实现方式二:
1)创建类实现Filter接口;@WebFilter(filterName=”customFilter”,urlPatterns={“/*”})
2)入口类增加注解@ServletComponentScan

  1. package com.duing.filter;
  2. import javax.servlet.*;
  3. import javax.servlet.annotation.WebFilter;
  4. import java.io.IOException;
  5. @WebFilter(filterName = "customFilter2",urlPatterns = {"/*"})
  6. public class CustomFilter2 implements Filter {
  7. @Override
  8. public void init(FilterConfig filterConfig) throws ServletException {
  9. System.out.println("CustomFilter2 init");
  10. }
  11. @Override
  12. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  13. System.out.println("CustomFilter2 doFilter");
  14. filterChain.doFilter(servletRequest, servletResponse);
  15. }
  16. @Override
  17. public void destroy() {
  18. System.out.println("CustomFilter2 destroy");
  19. }
  20. }
  1. package com.duing;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.boot.web.servlet.ServletComponentScan;
  5. @SpringBootApplication
  6. @ServletComponentScan
  7. public class ServletApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ServletApplication.class, args);
  10. }
  11. }

image.png
image.png
拦截器Interceptor
拦截器(代理模式)的实现基于反射

实现方式:
1)创建拦截器类实现HandlerInterceptor接口 2)创建配置类实现WebMvcConfigurer接口
image.png

  1. package com.duing.config;
  2. import com.duing.interceptor.CustomInterceptor;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. @Configuration
  8. public class InterceptorConfig implements WebMvcConfigurer {
  9. @Autowired
  10. private CustomInterceptor customInterceptor;
  11. /**
  12. * 注册自定义的拦截器,并且定义拦截规则
  13. * @param registry
  14. */
  15. @Override
  16. public void addInterceptors(InterceptorRegistry registry) {
  17. registry.addInterceptor(customInterceptor).addPathPatterns("/**");
  18. }
  19. }
  1. package com.duing.interceptor;
  2. import org.springframework.stereotype.Service;
  3. import org.springframework.web.servlet.HandlerInterceptor;
  4. import org.springframework.web.servlet.ModelAndView;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. @Service//交给spring管理,看做是一个服务
  8. public class CustomInterceptor implements HandlerInterceptor {
  9. @Override
  10. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  11. System.out.println("CustomInterceptor------preHandle");
  12. return true;
  13. }
  14. @Override
  15. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  16. System.out.println("CustomInterceptor------postHandle");
  17. }
  18. @Override
  19. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  20. System.out.println("CustomInterceptor------afterCompletion");
  21. }
  22. }


  1. package com.duing.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class ServletController {
  6. @RequestMapping("/servlet")
  7. public String servlet(){
  8. System.out.println("ServletController---");
  9. return "hello";
  10. }
  11. }

image.png

image.png

错误&异常处理机制

错误和异常
Error ExceptionError经常是程序无法处理的 (用户引入的错误 系统的错误)Exception 程序员引发的,能够在程序中处理, try catch / throws

优秀的处理机制
问题:怎么处理? 如何做到优秀?

二、处理方式
统共分为三种:数据验证错误、错误页指派、全局异常处理

1)数据验证错误

image.png
注解 @NotNull @NotEmpty @NotBlank 三者的区别
@NotNull不为空 广泛用于基础类的判断(int、double)
@NotEmpty 内容不为空 广泛用于集合等的判断(map、set)
@NotBlank不为空串 广泛用于String类型的判断

  1. package com.duing.bean;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import javax.validation.constraints.NotBlank;
  5. @Data
  6. @AllArgsConstructor
  7. public class Guest {
  8. @NotBlank(message = "快乐小慧自定义的名字不能为空")
  9. private String name;
  10. @NotBlank
  11. private String role;
  12. }
  1. package com.duing;
  2. import com.duing.bean.Guest;
  3. import javax.validation.ConstraintViolation;
  4. import javax.validation.Validation;
  5. import javax.validation.Validator;
  6. import java.util.Set;
  7. public class GuestValidTest {
  8. public static void main(String[] args) {
  9. //通过validation创建一个validator实例
  10. //普通模式
  11. Validator validator= Validation.buildDefaultValidatorFactory().getValidator();
  12. //创建一个不符合要求的bean(不得为空串)
  13. Guest guest=new Guest("","");
  14. //开始验证 接受验证结果
  15. Set<ConstraintViolation<Guest>> violationSet= validator.validate(guest);
  16. for (ConstraintViolation<Guest> violation:violationSet){
  17. System.out.println(violation.getPropertyPath()+","+violation.getMessage());
  18. }
  19. }
  20. }

这是校验框架的模式之一,“普通模式”(遍历所有属性,不符合校验规则的都返回)
执行结果:
image.png
“快速失败模式”(遍历所有属性,有一个不符合校验规则即返回)
Guest.java不变

  1. package com.duing;
  2. import com.duing.bean.Guest;
  3. import javax.validation.ConstraintViolation;
  4. import javax.validation.Validation;
  5. import javax.validation.Validator;
  6. import java.util.Set;
  7. public class GuestValidTest {
  8. public static void main(String[] args) {
  9. //通过validation创建一个validator实例
  10. //快速失败模式
  11. Validator validatorFastFail=Validation.byDefaultProvider().configure()
  12. .addProperty("hibernate.validator.fail_fast","true")//打开快速失败模式
  13. .buildValidatorFactory().getValidator();
  14. //创建一个不符合要求的bean(不得为空串)
  15. Guest guest=new Guest("","");
  16. //开始验证 接受验证结果
  17. Set<ConstraintViolation<Guest>> violationFastFailSet = validatorFastFail.validate(guest);
  18. for(ConstraintViolation violation : violationFastFailSet){
  19. System.out.println(violation.getPropertyPath() + "," + violation.getMessage());
  20. }
  21. }
  22. }

image.png

SpringBoot 中可以集成Validation对数据进行校验
这里我们使用postman测试

默认的处理方式

  1. package com.duing.controller;
  2. import com.duing.bean.Guest;
  3. import org.springframework.web.bind.annotation.PostMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. import javax.validation.Valid;
  6. @RestController
  7. public class GuestController {
  8. /**
  9. *
  10. * @Valid 直接放在bean前方
  11. * 用来校验它是否符合注解规则
  12. * 校验失败时直接返回400和失败原因
  13. * 处理方式是普通模式
  14. *
  15. * @param guest
  16. * @return
  17. */
  18. @PostMapping("/guest")
  19. public String add(@Valid Guest guest){
  20. return "Success";
  21. }
  22. }

image.png
image.png
自定义的处理方式通过BindingResult实现(BindingResult要紧跟在@Valid注解后面)

  1. @PostMapping("/guest")
  2. public String add(@Valid Guest guest, BindingResult result){
  3. //校验结果有错误
  4. if(result.getErrorCount()>0){
  5. List<FieldError> fieldErrors= result.getFieldErrors();
  6. StringBuilder builder=new StringBuilder();
  7. for (FieldError error:fieldErrors){
  8. builder.append(error.getField());
  9. builder.append("\t");
  10. builder.append(error.getDefaultMessage());
  11. builder.append("\n");
  12. }
  13. return builder.toString();
  14. }
  15. return "Success";
  16. }

image.png
SpringBoot支持通过配置文件设置校验信息,文件名为ValidationMessages.properties
image.png
通过{key}来获取对应的value

  1. package com.duing.bean;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import javax.validation.constraints.NotBlank;
  5. @Data
  6. @AllArgsConstructor
  7. public class Guest {
  8. //通过{key}来获取对应的value
  9. @NotBlank(message = "{guest.name.notblank}")
  10. private String name;
  11. @NotBlank
  12. private String role;
  13. }