【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类在这里被执行
}
} }