Filter,顾名思义,过滤器,是由servlet容器为每个传入的http请求和每个http响应执行的Java类。 这样,就可以在HTTP传入请求到达资源之前对其进行管理,例如JSP页面,servlet或简单的静态页面; 以相同的方式可以在资源执行后管理HTTP出站响应。
此行为允许实现在许多不同上下文中重用的常用功能。
如上图所示,过滤器在Web容器中运行,因此其定义也将包含在web.xml文件中。
<filter> <filter-name>CORSFilter</filter-name> <filter-class>com.listfeeds.components.CORSFilter</filter-class> <init-param> <param-name>fake-param</param-name> <param-value>fake-param-value</param-value> </init-param> </filter> <filter-mapping> <filter-name>CORSFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 复制代码
在过滤器定义中,由com.listfeeds.filters.CORSFilter类实现的过滤器具有满足表达式的所有端点:/ *(在本例中为all)
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; public class CORSFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); chain.doFilter(req, res); } public void init(FilterConfig filterConfig) {} public void destroy() {} } 复制代码
Filter包括三个主要方法:
Spring拦截器类似于Servlet过滤器,但它们在Spring Context中起作用,因此管理HTTP请求和响应的功能非常强大,但它们可以实现更加软化的行为,因为它可以访问所有Spring上下文。
Spring拦截器在SpringMVC上下文中执行,因此它们已在spring-servlet.xml文件中定义:
<mvc:interceptors> <bean class="com.listfeeds.interceptors.LogContextInterceptor" /> <bean class="com.listfeeds.interceptors.TimedInterceptor" /> </mvc:interceptors> 复制代码
com.listfeeds.interceptors.LogContextInterceptor拦截器类,用于向Log4j Thread上下文添加参数。
import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.log4j.MDC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class LogContextInterceptor extends HandlerInterceptorAdapter { private static final Logger log = LoggerFactory.getLogger(LogContextInterceptor.class); public static final String LOG_IDENTIFYING_TOKEN = "logIdentifyingToken"; @Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerMethod methodHandler = (HandlerMethod) handler; log.debug("END EXECUTION method {} request: {}", methodHandler.getMethod().getName(), request.getRequestURI()); Boolean settato = (Boolean) request.getAttribute(LOG_IDENTIFYING_TOKEN); if(settato != null && settato) { MDC.remove(LOG_IDENTIFYING_TOKEN); } } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { try { if( MDC.get(LOG_IDENTIFYING_TOKEN) == null ) { /* Retrieve parameters useful for logging */ @SuppressWarnings("unchecked") Map<String,String> pathVariables = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); String applicationId = null; if ( pathVariables != null ) applicationId = pathVariables.get("applicationId"); if ( StringUtils.isEmpty(applicationId) ) applicationId = request.getParameter("applicationId"); String loggingToken = String.format("ApplicationId: %s", applicationId); MDC.put(LOG_IDENTIFYING_TOKEN, loggingToken); request.setAttribute(LOG_IDENTIFYING_TOKEN, Boolean.TRUE); } } catch ( IllegalArgumentException e) { log.warn("Prehandle",e); return true; } finally { HandlerMethod methodHandler = (HandlerMethod) handler; //logger.debug("START EXECUTION " + methodHandler.getMethod().getName()); log.debug("START EXECUTION method {} request: {}", methodHandler.getMethod().getName(), request.getRequestURI()); } return true; } } 复制代码
interceptor 包含如下几个主要方法: