在构建springmvc+mybatis项目时,更常用的方式是采用web.xml来配置,而且一般情况下会在web.xml中使用ContextLoaderListener加载applicationContext-*.xml,在DispatcherServlet中配置${servlet-name}-servlet.xml。
但是实际上除了采用xml方式,在springmvc+mybatis项目中也可以采用纯代码+注解方式来替换web.xml、applicationContext-*.xml、${servlet-name}-servlet.xml。
下边我们先展示下采用web.xml配置方式,后边讲解如何使用代码+注解方式来替换的方案(所有代码请参考:https://github.com/478632418/springmv_without_web_xml/tree/master/test-pro-02)。
SpringMVC+Mybatis采用web.xml整合
/WEB-INF/web.xml配置
在/WEB-INF/web.xml中一般需要配置两个部分主要内容:ContextLoaderListener、DispatcherServlet。
一般web.xml配置信息如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <!-- 加载spring容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 文件上传与下载过滤器:form表单中存在文件时,该过滤器可以处理http请求中的文件,被该过滤器过滤后会用post方法提交,form表单需设为enctype="multipart/form-data"--> <!-- 注意:必须放在HiddenHttpMethodFilter过滤器之前 --> <filter> <filter-name>multipartFilter</filter-name> <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> <init-param> <param-name>multipartResolverBeanName</param-name> <!--spring中配置的id为multipartResolver的解析器--> <param-value>multipartResolver</param-value> </init-param> </filter> <filter-mapping> <filter-name>multipartFilter</filter-name> <!--<servlet-name>springmvc</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 注意:HiddenHttpMethodFilter必须作用于dispatcher前 请求method支持 put 和 delete 必须添加该过滤器 作用:可以过滤所有请求,并可以分为四种 使用该过滤器需要在前端页面加隐藏表单域 <input type="hidden" name="_method" value="请求方式(put/delete)"> post会寻找_method中的请求式是不是put 或者 delete,如果不是 则默认post请求 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <!--servlet为springMvc的servlet名 --> <servlet-name>springmvc</servlet-name> <!--可以通过配置覆盖默认'_method'值 --> <init-param> <param-name>methodParam</param-name> <param-value>_method</param-value> </init-param> <!--<url-pattern>/*</url-pattern>--> </filter-mapping> <!--结束后端数据输出到前端乱码问题--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- springmvc前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> </web-app>
备注:
1)上边关于spring的ApplicationContext配置有两处:ContextLoaderListener、DispatcherServlet,一般理解为:ContextLoaderListener为spring的parent ApplicationContext,DispatcherServlet为spring的child ApplicationContext。
2)ContextLoaderListener与DispatcherServlet所创建的上下文ApplicationContext的区别:
- ContextLoaderListener中创建ApplicationContext主要用于整个Web应用程序需要共享的一些组件,比如DAO,数据库的ConnectionFactory、multipartResolver等。而由DispatcherServlet创建的ApplicationContext主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。
- 对于作用范围而言,在DispatcherServlet中可以引用由ContextLoaderListener所创建的ApplicationContext,而反过来不行。
- 为什么multipartResolver需要配置在ContextLoaderListener的applicationContext.xml?具体可以查看MultipartFilter中的代码:
View Code
public class MultipartFilter extends OncePerRequestFilter { /** * The default name for the multipart resolver bean. */ public static final String DEFAULT_MULTIPART_RESOLVER_BEAN_NAME = "filterMultipartResolver"; private final MultipartResolver defaultMultipartResolver = new StandardServletMultipartResolver(); private String multipartResolverBeanName = DEFAULT_MULTIPART_RESOLVER_BEAN_NAME; /** * Set the bean name of the MultipartResolver to fetch from Spring's * root application context. Default is "filterMultipartResolver". */ public void setMultipartResolverBeanName(String multipartResolverBeanName) { this.multipartResolverBeanName = multipartResolverBeanName; } /** * Return the bean name of the MultipartResolver to fetch from Spring's * root application context. */ protected String getMultipartResolverBeanName() { return this.multipartResolverBeanName; } /** * Check for a multipart request via this filter's MultipartResolver, * and wrap the original request with a MultipartHttpServletRequest if appropriate. * <p>All later elements in the filter chain, most importantly servlets, benefit * from proper parameter extraction in the multipart case, and are able to cast to * MultipartHttpServletRequest if they need to. */ @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { MultipartResolver multipartResolver = lookupMultipartResolver(request); HttpServletRequest processedRequest = request; if (multipartResolver.isMultipart(processedRequest)) { if (logger.isTraceEnabled()) { logger.trace("Resolving multipart request"); } processedRequest = multipartResolver.resolveMultipart(processedRequest); } else { // A regular request... if (logger.isTraceEnabled()) { logger.trace("Not a multipart request"); } } try { filterChain.doFilter(processedRequest, response); } finally { if (processedRequest instanceof MultipartHttpServletRequest) { multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest); } } } /** * Look up the MultipartResolver that this filter should use, * taking the current HTTP request as argument. * <p>The default implementation delegates to the {@code lookupMultipartResolver} * without arguments. * @return the MultipartResolver to use * @see #lookupMultipartResolver() */ protected MultipartResolver lookupMultipartResolver(HttpServletRequest request) { return lookupMultipartResolver(); } /** * Look for a MultipartResolver bean in the root web application context. * Supports a "multipartResolverBeanName" filter init param; the default * bean name is "filterMultipartResolver". * <p>This can be overridden to use a custom MultipartResolver instance, * for example if not using a Spring web application context. * @return the MultipartResolver instance */ protected MultipartResolver lookupMultipartResolver() { WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); String beanName = getMultipartResolverBeanName(); if (wac != null && wac.containsBean(beanName)) { if (logger.isDebugEnabled()) { logger.debug("Using MultipartResolver '" + beanName + "' for MultipartFilter"); } return wac.getBean(beanName, MultipartResolver.class); } else { return this.defaultMultipartResolver; } } }