关于springboot的过滤器,拦截器,aop ,全局异常处理的学习整理
项目目录
过滤器(filter)
package cn.juhe.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
import java.util.Date;
/**
* 过滤器的缺点是虽然可以拿到请求与响应,
* 但是没有办法知道是具体执行的是哪个控制器
* 和具体发方法
*/
@Component
@Slf4j
@Order(-1)
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("do filter start");
long time = new Date().getTime();
filterChain.doFilter(servletRequest,servletResponse);
log.info("cost:{}",new Date().getTime()-time);
log.info("do filter end");
}
@Override
public void destroy() {
log.info("filter destroy");
}
}
自定义注入filter
package cn.juhe.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
import java.util.Date;
/**
* 通过@Compent注解注册的filer默认会拦截所有的请求,
* 如果不加入此注解,需要自己注入到容器当中,并且指定
* 拦截的路径,不仅是自己定义的filter,如果有第三方的
* filter,也可以通过此方式注入到容器当中
*/
@Slf4j
public class SecondFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("second filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("second do filter start");
long time = new Date().getTime();
filterChain.doFilter(servletRequest,servletResponse);
log.info("cost:{}",new Date().getTime()-time);
log.info("second do filter end");
}
@Override
public void destroy() {
log.info("second filter destroy");
}
}
如果想使用自定义注入的filter,还需要加入以下代码
package cn.juhe.config;
import cn.juhe.filter.SecondFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
@Configuration
public class WebFilterConfig {
@Bean
public FilterRegistrationBean secondFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
SecondFilter secondFilter = new SecondFilter();
registrationBean.setFilter(secondFilter);
ArrayList<String> urls = new ArrayList<>();
urls.add("/*");
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
}
拦截器(inteceptor)
package cn.juhe.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.invoke.MethodHandle;
import java.util.Date;
/**
* 拦截器需要添加注解@compent,并且需要在webConfig中注册,并且webConfig需要继承webmvcconfigureadapter
* 拦截器的缺点是无法获取封装到控制器的具体的方法的参数值,比如 public String userInfo(User user){},用户
* 传入的是User对象,在拦截器里面是拿不到的,因为用户的参数是在调用具体的拦截器之后才封装成User对象的
*/
@Component
@Slf4j
public class TimeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle");
request.setAttribute("startTime", new Date().getTime());
return true;
}
/**
* 如果具体的方法抛出了异常,则不会执行postHandle
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle");
String name = null;
String name1 = null;
try {
name = ((HandlerMethod) handler).getBean().getClass().getName();
name1 = ((HandlerMethod) handler).getMethod().getName();
} catch (Exception e) {
//e.printStackTrace();
}
log.info("class name: {}", name);
log.info("method name: {}", name1);
long startTime = (Long) request.getAttribute("startTime");
log.info("postHandle cost: {}", new Date().getTime() - startTime);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion");
}
}
要想使用拦截器,还需要加入以下代码
package cn.juhe.config;
import cn.juhe.interceptor.TimeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebInterceptorConfig implements WebMvcConfigurer {
@Autowired
TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
}
面向切面(AOP)
package cn.juhe.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.stream.Stream;
@Aspect
@Component
//定义切片类
//定义切入点
//定义切入方法
@Slf4j
public class TimeAspect {
/**
* 执行什么方法起作用
* 什么时候起作用
*/
@Around("execution(* cn.juhe.controller.TestController.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
log.info("TimeAspect start ....");
//获取参数
Object[] args = proceedingJoinPoint.getArgs();
Stream.of(args).forEach(System.out::println);
Object proceed = proceedingJoinPoint.proceed();
log.info("TimeAspect return:{}",proceed);
log.info("TimeAspect end ....");
return proceed;
}
}
自定义异常
package cn.juhe.entity;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class User {
private int id;
private String name;
private int age;
}
package cn.juhe.exception;
import lombok.Data;
/**
* 自定义异常
*/
@Data
public class UserNotFoundException extends RuntimeException {
private int id;
public UserNotFoundException(int id) {
super("user not found");
this.id = id;
}
}
controller
package cn.juhe.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class TestController {
@GetMapping("/test")
public String test(@RequestParam("name") String name){
log.info("test .....");
return "hello " +name;
}
}
package cn.juhe.controller;
import cn.juhe.exception.UserNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class UserController {
@GetMapping("/user")
public String test(@RequestParam("id") int id) {
log.info("user .....");
if (id == 2) {
throw new UserNotFoundException(2);
}
return "hello " + id;
}
}