Spring中过滤器 拦截器 aop使用顺序

1.前文提到log4j2日志记录如何使用,目前log4j2的主要作用是记录 请求入参,出参,控制层 ,方法,使用时间等信息.而接口入参是放在spring拦截器中,出参及消耗时间是放在aop的后置通知中.趁着这个机会刚好把当前框架中过滤器,拦截器,aop之间的使用顺序关系梳洗一下.

2.首先来看一下项目中日志记录的内容,主要有发挥作用的有InitInterceptor 拦截其中的preHandle方法(请求进入控制层之前记录时间 控制层 方法 参数 url地址 ),LogAspect中after方法(aop面向切面的后置通知记录返回参数类型参数),InitInterceptor 拦截器中的postHandle方法(在controller方法调用完毕后记录消耗时间及请求完成记录信息),具体相关代码在下面

11:24:16.634 [http-apr-8080-exec-4] INFO  com.bxd.core.interceptor.InitInterceptor - -----------------------2019-01-30 11:24:16-------------------------------------
11:28:21.202 [http-apr-8080-exec-3] INFO  com.bxd.core.interceptor.InitInterceptor - -----------------------2019-01-30 11:28:21-------------------------------------
Controller: com.bxd.app.controller.sysmgr.SysOrganController$$EnhancerBySpringCGLIB$$2392dc1b
Method    : page
Params    : {"orgName":[""],"orgNo":[""],"size":["20"],"start":["0"],"page":["1"],"_dc":["1548818901173"]}
URI       : /pv_webT/sysmgr/organ/page

11:28:21.235 [http-apr-8080-exec-3] INFO  com.bxd.app.aop.LogAspect - com.bxd.core.support.QueryResult@16e6f486
11:28:21.236 [http-apr-8080-exec-3] INFO  com.bxd.app.aop.LogAspect - -------------------日志记录结束---------------------
11:28:21.239 [http-apr-8080-exec-3] INFO  com.bxd.core.interceptor.InitInterceptor - 耗时  : 37ms
-------------------------------------------------------------------------------
11:28:21.240 [http-apr-8080-exec-3] INFO  com.bxd.core.interceptor.InitInterceptor - ********************请求已完成******************
11:28:21.240 [http-apr-8080-exec-3] INFO  com.bxd.core.interceptor.InitInterceptor - ********************系统更新完成******************

InitInterceptor 类

public class LogAspect {
	
	
	private static Logger LOG = LoggerFactory.getLogger(LogAspect.class);
	
	/**
	 * 在请求进入控制器之前进行拦截,存储请求信息
	 * @param joinPoint
	 * @throws JsonProcessingException 
	 */
	public void before(JoinPoint joinPoint) throws JsonProcessingException {
		
		String classType = joinPoint.getTarget().getClass().getName();  
		
        if(!"com.bxd.app.controller.APIController".equals(classType)){
        	return;
        }

        LOG.info("-------------------开始进行统一日志记录---------------------");
				
	}

	/**
	 * 在controller方法执行完之后进行拦截,存储方法返回的结果信息
	 * @param joinPoint
	 * @param returnValue
	 * @throws JsonProcessingException 
	 */
	public void after(JoinPoint joinPoint,Object returnValue) throws JsonProcessingException {
		String classType = joinPoint.getTarget().getClass().getName();  

		if(StringUtil.hasText("LogController", classType)){
        	return;
        }
        if(StringUtil.isNotEmpty(returnValue)){
        	 LOG.info(returnValue.toString());
        }      
        LOG.info("-------------------日志记录结束---------------------");
	}

	/**
	 * 把map类型参数转为key,value型参数
	 * @param map
	 * @return
	 */
	protected Map<String, Object> getParams(Map<String, String[]> map) {
		Map<String, Object> params = new HashMap<>();
		for (Entry<String, String[]> e : map.entrySet()) {
			params.put(e.getKey(), e.getValue());
		}
		return params;
	}

LogAspect类

private static final Logger logger = LoggerFactory.getLogger(InitInterceptor.class);
	
	@Autowired
	JacksonObjectMapper objectMapper;
	/**
	 * 在执行controller方法之前进行请求参数处理
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		if (handler instanceof HandlerMethod) {
			HandlerMethod h = (HandlerMethod) handler;
			Date dateTime = Calendar.getInstance().getTime();
			request.setAttribute("startTime", dateTime.getTime());
			if(h.getMethod().getName().contains("refresh")){
				logger.info("********************系统缓存更新成功******************************");
				return true;
			};
			Map<String, Object> params = getParams(request);		
			StringBuilder sb = new StringBuilder(2000);
			SimpleDateFormat sfFormat = new SimpleDateFormat("yyyy-MM-dd H:m:s");
			
			sb.append("-----------------------").append(sfFormat.format(dateTime))
					.append("-------------------------------------\n");
			
			sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n");
			sb.append("Method    : ").append(h.getMethod().getName()).append("\n");
			sb.append("Params    : ").append(JsonUtil.toJson(params)).append("\n");
			sb.append("URI       : ").append(request.getRequestURI()).append("\n");
			
			logger.info(sb.toString());
		}

		return true;
	}

	/**
	 * 调用controller方法之后执行日志记录
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		if (handler instanceof HandlerMethod) {
			long startTime = (Long) request.getAttribute("startTime");;								
			Date dateTime = Calendar.getInstance().getTime();
			long endTime = dateTime.getTime();
			long executeTime = endTime - startTime;
			StringBuilder sb = new StringBuilder(1000);
			sb.append("耗时  : ").append(executeTime).append("ms").append("\n");
			sb.append("-------------------------------------------------------------------------------");
			logger.info(sb.toString());
		}

	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
		logger.info("********************请求已完成******************");
		if (handler instanceof HandlerMethod){
			//HandlerMethod method = (HandlerMethod) handler;
			
			logger.info("********************系统更新完成******************");
		}
		
		
	}
	
	 /**
		 * 把map类型参数转为key,value型参数
		 * @param map
		 * @return
		 */
		protected Map<String, Object> getParams(HttpServletRequest request) {
			Map<String, String[]> map = request.getParameterMap();
			Map<String, Object> params = new HashMap<>();
			for (Entry<String, String[]> e : map.entrySet()) {
				params.put(e.getKey(), e.getValue());
			}
			return params;
		}

LogAspect需要配置的spring-aop.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!--将日志类注入到bean中--> 
	<bean id="logAsp" class="com.bxd.app.aop.LogAspect"></bean>  
  
	<aop:config>  
		<!--配置在controller包下所有的类在调用之前都会被拦截--> 
		<aop:pointcut id="logpoint" expression="execution(* com.bxd.app.controller..*(..))"/>
		<aop:aspect ref="logAsp" order="2">			
			<!-- 配置通知,相当于@Before、@After、@AfterReturn、@Around、@AfterThrowing -->
			<aop:before pointcut-ref="logpoint" method="before"/>
			<aop:after-returning pointcut-ref="logpoint" method="after" returning="returnValue"/>
		</aop:aspect> 
	</aop:config>
	
	<!-- 启动对@AspectJ注解的支持  -->
	<!--aop:config proxy-target-class="true"></aop:config-->
	
	<!--aop:aspectj-autoproxy proxy-target-class="true"/-->
</beans>

3.从上面我们就可以理清楚拦截器 aop使用顺序是这样的
拦截顺序:filter—>Interceptor—->@Aspect -->Interceptor),具体点可以看下面这张图在这里插入图片描述https://blog.csdn.net/rainbow702/article/details/52185827原文作者地址
在这里插入图片描述https://blog.csdn.net/weixin_39168678/article/details/80987539原文作者地址

4.最后讲一下日志记录中看不到过滤器的作用,过滤器与框架无关主要是配置在web容器中.主要有3个郭过滤器,执行顺序是InitFilter在web容器中并没有做出配置,所以暂不研究.

web.xml配置
<filter> <filter-name>XssFilter</filter-name> <filter-class>com.bxd.core.filter.XssFilter</filter-class> </filter>

XssFilter->XssHttpServletRequestWrapper,通过名字我们就可以知道主要是为了防止xss跨域及跨站攻击的.在这里插入图片描述
XssFilter.class

public class XssFilter implements Filter  {

	 FilterConfig filterConfig = null;

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    public void destroy() {
        this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {        
    	chain.doFilter(new XssHttpServletRequestWrapper(
                (HttpServletRequest) request), response);
    }

}

XssHttpServletRequestWrapper.class

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
	public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {

        super(servletRequest);

    }

    public String[] getParameterValues(String parameter) {

        String[] values = super.getParameterValues(parameter);

        if (values == null) {

            return null;

        }

        int count = values.length;

        String[] encodedValues = new String[count];

        for (int i = 0; i < count; i++) {

            encodedValues[i] = cleanXSS(values[i]);

        }

        return encodedValues;

    }

    public String getParameter(String parameter) {

        String value = super.getParameter(parameter);

        if (value == null) {

            return null;

        }

        return cleanXSS(value);

    }

    public String getHeader(String name) {

        String value = super.getHeader(name);

        if (value == null)

            return null;

        return cleanXSS(value);

    }

    private String cleanXSS(String value) {

        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");

        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");

        value = value.replaceAll("'", "& #39;");

        value = value.replaceAll("eval\\((.*)\\)", "");

        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");

        value = value.replaceAll("script", "");

        return value;

    }
}

最后:项目中对于权限的控制 只是在前端做了控制,后端 只是针对用户是否登录做了校验,并没有对权限问题作出解决.最近想着能否利用拦截器 也就是preHandler 中对权限进行控制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring拦截器过滤器AOPSpring框架常用的三种技术,用于实现对请求的处理和控制。它们的作用和使用方式有一些不同,我会分别对它们进行简单解释。 1. 过滤器(Filter): 过滤器是Java Servlet规范提供的一种技术,用于在请求到达Servlet之前或响应返回给客户端之前拦截和处理请求。过滤器可以在Web应用的整个生命周期起作用,对所有请求都生效。常见的应用场景包括:编码转换、身份认证、日志记录等。 2. 拦截器(Interceptor): 拦截器Spring框架提供的一种技术,用于在请求到达Handler(Controller方法)之前或响应返回给客户端之前对请求进行拦截和处理。拦截器只在Spring MVC起作用,用于实现对请求的预处理和后处理。常见的应用场景包括:身份认证、权限控制、日志记录等。 3. AOP(面向切面编程): AOP是一种编程思想,也是Spring框架提供的一种技术。通过AOP,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑解耦出来,以模块化的方式进行管理。在SpringAOP通常通过动态代理实现,可以在方法执行前、后或抛出异常时进行一些额外的处理。AOP常用于事务管理、日志记录、性能监控等方面。 总结: - 过滤器主要用于在Servlet规范对请求进行拦截和处理。 - 拦截器主要用于在Spring MVC对请求进行拦截和处理。 - AOP主要用于将与业务逻辑无关的横切关注点进行解耦和管理。 希望以上解释能对你有所帮助!如果有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值