【Java Web开发学习】Spring MVC添加自定义Servlet、Filter、Listener
转载:https://www.cnblogs.com/yangchongxing/p/9968483.html
自定义Servlet
package cn.ycx.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; public MyServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("myservlet"); response.getWriter().append("Served at: ").append(request.getContextPath()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
自定义Filter
package cn.ycx.filter; 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; public class MyFilter implements Filter { public MyFilter() { } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("myfilter"); chain.doFilter(request, response); } public void init(FilterConfig fConfig) throws ServletException { } }
静态资源处理Filter
package cn.ycx.filter; import java.io.FileInputStream; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class StaticFilter implements Filter { public StaticFilter() { } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("StaticFilter"); HttpServletRequest httpServletRequest = (HttpServletRequest) request; String path = httpServletRequest.getServletPath(); String realPath = httpServletRequest.getServletContext().getRealPath(path); System.out.println(realPath); ServletOutputStream out = response.getOutputStream(); FileInputStream in = new FileInputStream(realPath); byte[] buf = new byte[2048]; int len = -1; while((len = in.read(buf)) != -1) { out.write(buf, 0, len); } in.close(); out.flush(); out.close(); } public void init(FilterConfig fConfig) throws ServletException { } }
自定义Listener
package cn.ycx.listener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; public class MyServletRequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("requestDestroyed"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("requestInitialized"); } }
方式一、基于Java初始化器WebApplicationInitializer添加(支持Servlet3.0的容器)
package cn.ycx.initializer; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import cn.ycx.filter.MyFilter; import cn.ycx.filter.StaticFilter; import cn.ycx.listener.MyServletRequestAttributeListener; import cn.ycx.listener.MyServletRequestListener; import cn.ycx.servlet.MyServlet; public class MyInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { System.out.println(">>>>>>>>>>>> 自定义 onStartup ..."); // 自定义Servlet ServletRegistration.Dynamic myServlet = servletContext.addServlet("myservlet", MyServlet.class); myServlet.addMapping("/myservlet"); // 自定义Filter FilterRegistration.Dynamic staticFilter = servletContext.addFilter("staticfilter", StaticFilter.class); staticFilter.addMappingForUrlPatterns(null, false, "/static/*"); FilterRegistration.Dynamic myFilter = servletContext.addFilter("myfilter", MyFilter.class); myFilter.addMappingForUrlPatterns(null, false, "/*"); // 自定义Listener servletContext.addListener(MyServletRequestListener.class); servletContext.addListener(MyServletRequestAttributeListener.class.getName()); } }
addServlet 重载方法
public ServletRegistration.Dynamic addServlet(String servletName, String className); public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet); public ServletRegistration.Dynamic addServlet(String servletName,Class <? extends Servlet> servletClass);
addFilter 重载方法
public FilterRegistration.Dynamic addFilter(String filterName, String className); public FilterRegistration.Dynamic addFilter(String filterName, Filter filter); public FilterRegistration.Dynamic addFilter(String filterName,Class <? extends Filter> filterClass);
addListener 重载方法
public void addListener(String className); public <T extends EventListener> void addListener(T t); public void addListener(Class <? extends EventListener> listenerClass);
addMappingForUrlPatterns方法第二个参数isMatchAfter相同时,Filter的执行顺序由其在onStartup方法中的添加顺序决定,为false的优先级比为true高
/** * Adds a filter mapping with the given url patterns and dispatcher * types for the Filter represented by this FilterRegistration. * * <p>Filter mappings are matched in the order in which they were * added. * * <p>Depending on the value of the <tt>isMatchAfter</tt> parameter, the * given filter mapping will be considered after or before any * <i>declared</i> filter mappings of the ServletContext from which * this FilterRegistration was obtained. * * <p>If this method is called multiple times, each successive call * adds to the effects of the former. * * @param dispatcherTypes the dispatcher types of the filter mapping, * or null if the default <tt>DispatcherType.REQUEST</tt> is to be used * @param isMatchAfter true if the given filter mapping should be matched * after any declared filter mappings, and false if it is supposed to * be matched before any declared filter mappings of the ServletContext * from which this FilterRegistration was obtained * @param urlPatterns the url patterns of the filter mapping * * @throws IllegalArgumentException if <tt>urlPatterns</tt> is null or * empty * @throws IllegalStateException if the ServletContext from which this * FilterRegistration was obtained has already been initialized */ public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns);
为什么实现这个接口容器就能加载自定义类呢?
因为在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,并用它来配置Servlet容器。Spring提供了这个接口的实现类名为SpringServletContainerInitializer,这个类会查找实现WebApplicationInitializer接口的类,并将任务交给他们来完成。
SpringServletContainerInitializer类源码
@HandlesTypes(WebApplicationInitializer.class) public class SpringServletContainerInitializer implements ServletContainerInitializer { @Override public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException { List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>(); if (webAppInitializerClasses != null) { for (Class<?> waiClass : webAppInitializerClasses) { // Be defensive: Some servlet containers provide us with invalid classes, // no matter what @HandlesTypes says... if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) { try { initializers.add((WebApplicationInitializer) waiClass.newInstance()); } catch (Throwable ex) { throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex); } } } } if (initializers.isEmpty()) { servletContext.log("No Spring WebApplicationInitializer types detected on classpath"); return; } servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath"); AnnotationAwareOrderComparator.sort(initializers); for (WebApplicationInitializer initializer : initializers) { initializer.onStartup(servletContext);//我们自定义的WebApplicationInitializer类在这里被执行 } } }