SpringMVC的高级技术
本章的主要内容包括:
SpringMVC配置的替代方案
处理文件上传
在控制器中处理异常
使用flash属性
1 SpringMVC配置的替换方案
在之前的内容中,通过扩展AbstractAnnotationConfigDispatcherServletInitializer快速搭建了SpringMVC环境。在这个便利的基础类中,假设我们需要基本的DispatcherServlet和ContextLoaderListener环境,并且Spring配置是使用Java的,而不是XML。
尽管对很多Spring应用来说,这是一种安全的假设,但是这并不一定能满足我们的要求。除了DispatcherServlet以外,我们可能还需要额外的Servlet和Filter;我们可能还需要对DispatcherServlet本身做一些额外的配置;或者我们需要将应用部署到Servlet3.0之前的容器中,那么还需要将DispatcherServlet配置到web.xml中。
1.1 自定义DispatcherServlet配置
在AbstractAnnotationConfigDispatcherServletInitializer将DispatcherServlet注册到Servlet容器之后,就会调用customizeRegistration(),并将Servlet注册后得到的Registration.Dynamic传递进来。通过重载customizeRegistration()方法,我们可以对DispatcherServlet进行额外的配置。
借助customizeRegistration()方法中的ServletRegistration.Dynamic,我们能够完成多项任务,包括通过调用setLoadOnStartup()设置load-on-startup优先级,通过调用setInitParameter()设置初始化参数,通过调用setMultipartConfig()配置Servlet3.0对multipart的支持。
1.2 添加其他的Servlet和Filter
按照AbstractAnnotationConfigDispatcherServletInitializer的定义,它会创建DispatcherServlet和ContextLoaderListener。但是,如果需要注册其他的Servlet、Filter或Listener的话,那该怎么办?
基于Java的初始化器(initializer)的一个好处就是我们可以定义任意数量的初始化类器类。因此如果我们想往Web容器中注册其他组件的话,只需要创建一个新的初始化容器就可以了。最简单的方式就是实现Spring的WebApplicationInitializer接口。
自定义Servlet代码如下:
package com.godman.spittr.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPut(req, resp);
}
}
自定义initializer代码如下:
package com.godman.spittr.config;
import com.godman.spittr.servlet.MyServlet;
import org.springframework.web.WebApplicationInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class MyServletInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
ServletRegistration.Dynamic myServlet = servletContext.addServlet(“myServlet”, MyServlet.class);
myServlet.addMapping(“/custom/**”);
}
}
类似地,可以创建新的WebApplicationInitializer实现来注册Listener和Filter。
自定义Filter代码如下:
package com.godman.spittr.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("MyFilter innit successfully!");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
logger.info("MyFilter destroyed");
}
}
自定义initializer代码如下:
package com.godman.spittr.config;
import com.godman.spittr.filter.MyFilter;
import org.springframework.web.WebApplicationInitializer;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
public class MyFilterInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//注册filter
FilterRegistration.Dynamic filter = servletContext.addFilter(“myFilter”, MyFilter.class);
//添加filter的映射路径
filter.addMappingForUrlPatterns(null, false, “/custom/*”);
}
}
如果要将应用部署到支持Servlet3.0的容器中,那么WebApplicationInitializer只提供了一种通用的方式,实现在Java中注册Servlet、Filter或Listener。不过,如果只是注册Filter,并且该Filter只会映射到DispatcherServlet上的话,那么在AbstractAnnotationConfigDispatcherServletInitializer上还有一种快捷方式。所需要做的仅仅是重载Filters()方法。
@Override
protected Filter[] getServletFilters() {
return new Filter[] {new MyFilter()};
}
在这里没有必要声明它的映射路径,getServletFilters()方法返回的所有Filter都会映射到DispatcherServlet上。
假如需要将应用部署到不支持Servlet3.0的容器中(或者只是希望使用web.xml文件),那么完全可以通过web.xml配置SpringMVC。
1.3 在web.xml中声明DispatcherServlet
在典型的SpringMVC应用中,我们会需要DispatcherServlet和ContextLoaderListener。AbstractAnnotationConfigDispatcherServletInitializer会自动注册它们,但是在web.xml文件中就需要手动配置了。
网友评论