1、切面(Aspect)
是什么
切面,指切入目标方法,扩展目标方法功能,却不修改目标方法代码,将扩展功能代码从目标方法代码中分离出来。可以针对方法级拦截,并获得方法的参数和返回值,但获取不到http请求,多配合注解使用。
应用场景
• 权限校验
• 字段加密解
怎么用
package com.dy.aspect;
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.Date; /** * this is a acpect * 切入点 * 在那些方法上起作用 * 在什么时候起作用 * * @author duoyuan * @create 2019-12-20 20:52 **/
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.duoyuan.controller.UserController.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("time aspect start");
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
System.out.println(arg.getClass().getName());
System.out.println("arg is " + arg);
}
long startTime = new Date().getTime();
Object obj = proceedingJoinPoint.proceed();
System.out.println("time aspect 耗时" + (new Date().getTime() - startTime));
System.out.println("time aspect end");
return obj;
}
}
2、过滤器(Filter)
是什么
过滤器就是一个实现了特殊接口的Java类,实现对请求资源的过滤的功能。和框架无关,所有过滤组件的最外层,颗粒度比较大。
应用场景
• 验证token合法性、有效性
怎么用
springboot中一般有两种配置方式:
(1)直接实现java.servlet.Filter接口
package com.dy.webFilter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
import java.util.Date;
@Component
public class TimerFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Time filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Time filter start");
long startTime = new Date().getTime();
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("time filter:"+(new Date().getTime()-startTime));
System.out.println("time filter finish");
}
@Override
public void destroy() {
System.out.println("Time filter destroy");
}
}
(2)在WebConfig中配置,这种配置方式是因为使用第三方的Filter没有@Compont注解。
package com.dy.config;
import com.nbkj.webFilter.TimerFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* Web配置
*
* @author duoyuan
* @Configuration 这个注解声明这个类是配置类
* @create 2019-12-20 18:00
**/
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean timeFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
TimerFilter timerFilter = new TimerFilter();
registrationBean.setFilter(timerFilter);
List<String> urls = new ArrayList<>();
urls.add("/*");
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
}
3、拦截器(Intereptor)
是什么
拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。是基于JAVA的反射机制。拦截器不是在web.xml,比如struts在struts.xml中配置。可以获取被拦截的controller的方法,获取不到参数。
应用场景
• 执行安全检查
• 格式化请求头和主体
• 审查或者记录日志
• 根据请求内容授权或者限制用户访问
• 根据请求频率限制用户访问
怎么用
package com.dy.interceptor;
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.persistence.Convert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
* this is spring interceptor
*
* @author duoyuan
* @create 2019-12-24 18:16
**/
@Component
public class TimeInterceptor implements HandlerInterceptor {
/**
* 控制器方法处理之前
*
* @param httpServletRequest
* @param httpServletResponse
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
System.out.println("preHandle");
System.out.println(((HandlerMethod) handler).getBean().getClass().getName());
System.out.println(((HandlerMethod) handler).getMethod().getName());
httpServletRequest.setAttribute("startTime", new Date().getTime());
return false;
}
/**
* 控制器方法处理之后
* 控制器方法调用不抛异常调用
*
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long startTime = (Long) httpServletRequest.getAttribute("startTime");
System.out.println("time interceptor 耗时" + (new Date().getTime() - startTime));
}
/**
* 控制器方法抛不抛异常都会被调用
*
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
Long startTime = (Long) httpServletRequest.getAttribute("startTime");
System.out.println("time interceptor 耗时" + (new Date().getTime() - startTime));
System.out.println("ex is" + e);
}
}
package com.dy.config;
import com.nbkj.interceptor.TimeInterceptor;
import com.nbkj.webFilter.TimerFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* Web配置
*
* @author duoyuan
* @Configuration 这个注解声明这个类是配置类
* @create 2019-12-20 18:00
**/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
}
4、ControllerAdvice
是什么
controller的一个增强,最常用的是和@ExceptionHandler一起用来做全局异常。
应用场景
• 配合@ExceptionHandler做全局异常处理
• 配合@InitBinder对特殊请求参数做转换
• 配合@ModelAttribute使用
怎么用
package com.dy.handler;
import com.wusong.order.common.Resp;
import com.wusong.order.common.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @description: 全局异常处理
* @author:duoyuan
* @create: 2019-12-16 下午1:45
**/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* @description: 业务异常统一处理
* @param e
* @return:
* @author:
* @Date: 2019-12-16 下午12:26
*/
@ExceptionHandler(value = ServiceException.class)
@ResponseBody
public Object serviceExceptionHandle(ServiceException e) {
log.error("异常{}", e);
Object obj = Resp.error(e);
return obj;
}
}
Spring的Aspect,Filter、Interceptor、ControllerAdvice区别
原文:https://www.cnblogs.com/duoyuan/p/12102421.html