Spring Servlet 拦截器 过滤器

Spring MVC Handler拦截器用例

Spring MVC HandlerInterceptor Example


在这里我将使用 WebMvcConfigurerAdapter 编写一个 HandlerInterceptor 的用例.

Spring HandlerInterceptor 与 Servlet 过滤器类似, Servlet 过滤器更强大些, 不过它只能在 web.xml 中配置( 正如对 DispatcherServlet 的配置一样, 译者注 ), 而 HandlerInterceptor 可通过 Spring 应用上下文 xml 文件和 Java 代码配置, HandlerInterceptor 可以用来避免重复的处理程序代码, 比如用作认证检测, 区域检查等不同用途.

在 Java 中, 我们可以重写 WebMvcConfigurerAdapter#addInterceptors( InterceptorRegistry ) 方法, 该回调方法在参数中提供了一个 InterceptorRegistry 对象,

使用 InterceptorRegistry#addInterceptor( HandlerInterceptor ) 方法可以向 Spring 注入 HandlerInterceptor 接口, 该接口有适配器 HandlerInterceptorAdapter.

InterceptorRegistry#addInterceptor( HandlerInterceptor ) 方法返回一个 InterceptorRegistration,允许您进一步配置已注册的拦截器,例如添加应该应用的URL模式。

On this page we will provide Spring MVC HandlerInterceptor example with WebMvcConfigurerAdapter. Spring HandlerInterceptor works similar to the Servlet Filter. Servlet filters are more powerful than Spring HandlerInterceptor. Servlet Filters are configured in web.xml and Spring HandlerInterceptor is configured in Spring application context xml file or Java configuration. Spring HandlerInterceptor can be used to avoid repetitive handler code. We can use HandlerInterceptor for different purposes like authorization checks, locale checks etc. In java configuration, WebMvcConfigurerAdapter has a method as addInterceptors in which InterceptorRegistry is passed as an argument. Using InterceptorRegistry.addInterceptor(), we add our interceptors and using InterceptorRegistry.addInterceptor().addPathPatterns(), we provide path pattern specific to given interceptor. If an interceptor has not been provided with any path pattern, it is called for each request. Spring provides HandlerInterceptorAdapter adapter class for implementing only required handler methods of HandlerInterceptor. HandlerInterceptor has three methods.

HandlerInterceptor 接口有三个方法:

preHandle(): It is executed before actual handler is executed. 在实际处理之前执行, 返回值是布尔类型, false 取消处理
postHandle(): It is executed after handler is executed. 在实际处理之后执行
afterCompletion(): It is executed after the complete request is finished.  在完成请求后执行
也就是说, 你可能这样重写 WebMvcConfigurerAdapter :
import ...

@EnableMvc
@ComponetScan(basePackageClasses = { Index.class })
public final class MyWebAppInitializer extends WebConfigAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor( new HandlerInterceptorAdapter() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                return true; // 继续处理
            }
        }).addPathPatterns("/*", "/*.jpg");
        //
    }
    ...
}

如果不调用 addPathPatterns( String... ) , 则会匹配所有 RequestMapping


Spring 过滤器用例

javax.servlet
Interface Filter
All Known Implementing Classes:
GenericFilter, HttpFilter

default void	destroy()
//Called by the web container to indicate to a filter that it is being taken out of service.

void	doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
//The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

default void	init(FilterConfig filterConfig)
//Called by the web container to indicate to a filter that it is being placed into service.

实现效果:

package club.init;

import java.io.IOException;
import java.util.Enumeration;

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class StaticResourceFilter implements Filter {
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
		intercept((HttpServletRequest)request, (HttpServletResponse)response, chain);
	}

	public void intercept(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
		// 添加服务器名
		try {
			response.addHeader("Server", "Fast Tomcat");
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 获取 refer
		Enumeration<String> headers = request.getHeaderNames();
		String refer = null;
		String content = "GET " + request.getRequestURI() + "\n";
		while (headers.hasMoreElements()) {
			String header = headers.nextElement();
			content += String.format("%s : %s\n", header, request.getHeader(header));
			if ("referer".equals(header)) {
				refer = request.getHeader(header);
				break;
			}
		}
		Log.d(content);
		
		if (request.getRequestURI().matches(".*\\..+")) {
			// 静态资源
			if (refer == null || !refer.matches("https?://abc.com/.*")) {
				response.setStatus(404);
				response.addHeader("Error", "You can't use this resource without abc.com");
				return;
			}
			response.addHeader("Content-Disposition", 
					String.format("attachment; filename*=UTF-8''%s", request.getRequestURI().replaceAll(".*/", "")));
		}
		try {
			chain.doFilter(request, response);
		} catch (IOException | ServletException e) {
			e.printStackTrace();
		}
	}

}

最好使用 HttpFilter 这个类

这里有一个使用过滤器的项目: https://github.com/develon2015/Spring-filter


posted @ 2019-09-10 23:30  develon  阅读(885)  评论(0编辑  收藏  举报