springboot fitler interceptor Aspect ControllerAdvice 一网打尽

关于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;
    }
}

猜你喜欢

转载自blog.csdn.net/silk_java/article/details/103633062