Spring项目实践(四)--- Spring MVC配置文件详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l00149133/article/details/78982336

前三讲我们依次讲了pom.xml,web.xml和spring配置文件,这次我们来讲一下springmvc的配置。

首先明确一下springmvc是spring的一个模块。

springmvc的配置文件,也不是固定命名的,而是同spring配置文件一样,在web.xml中指定的:

    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
下面我们还是老规矩,一步步的来分析spring mvc配置文件

一.root标签
跟spring配置一样,root标签是beans,毕竟springmvc是spring的一个模块

二.自动扫描

这部分我们在spring也讲过。在springmvc里,自动扫描主要是配置controller:

<context:component-scan base-package="com.xxx.controller"/>

三.解析器Resolver

解析器有很多种,比较重要的是ViewResolver

ViewResolver也有很多种,其中比较重要和常用的是InternalResourceViewResolver(内部资源视图解析器)

先上代码再说明:

	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="order" value="1" />
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
如果没有视图解析器,我们在controller里面的代码是这样的:

@Controller
public class LoginActionController {
	@RequestMapping("/index")
	public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
            return "/WEB-INF/jsp/index.jsp";
	}

而使用了视图解析器,我们的代码是这样的:

@Controller
public class LoginActionController {
	@RequestMapping("/index")
	public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
            return "index";
	}
区别在最后一句,我们不需要给出目标视图的全路径了。

InternalResourceViewResolver的主要作用也在于此,给出内部资源的路径和前后缀。

当然还有其他的视图解析器,比如XmlViewResolver,UrlBasedViewResolver等,不再铺开解释。

也还有别的解析器,比如处理文件上传的解析器CommonsMultipartResolver,统一处理异常的解析器SimpleMappingExceptionResolver。

这里多说两句SimpleMappingExceptionResolver,代码如下:

	<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="warnLogCategory" value="warn" />
		<property name="defaultStatusCode" value="500"/>
		<property name="defaultErrorView" value="/error/500"/>
		
		<property name="exceptionMappings">
			<props>
				<prop key="java.lang.Exception">/error/500</prop>
			</props>
		</property>
		
		<property name="statusCodes">
			<props>
				<prop key="/error/404">404</prop>
				<prop key="/error/404">400</prop>
				<prop key="/error/500">500</prop>
			</props>
		</property>
	</bean>


四.对静态资源的处理

在web.xml里面,我们配置了springmvc的DispatcherServlet:

    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
注意看servlet-mapping部分,这部分的url-pattern是"/",这表明, DispatcherServlet会帮我们截获所有的url请求,并将请求发送给对应的controller。

对,是所有的请求!也包括静态文件,比如.js文件,图片文件,css文件的请求。

显然这是有问题的,因为没有controller会去处理静态文件,这会导致静态文件查找不到。

这也是为什么我们在一些早期的文章或者书籍中,看到的servlet-mapping是下面这样的:

 <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
    </servlet-mapping>
然后在controller里面,我们会这么写:

@Controller
public class LoginActionController {
	@RequestMapping("/index.do")
	public String toIndex(HttpServletRequest request, ModelMap map, HttpSession session) {
            return "index";
	}
注意这里的RequestMapping的value是index.do

通过这种方式,等于是我们只让DispatcherServlet去处理了.do后缀的请求,controller也只会处理.do后缀的请求。

对应的,我们的url是这样的:www.test.com/index.do

很显然这样看着很奇怪,而且不符合REST风格。

所以spring团队给出了2种解决方案:

方案一:

你可以在springmvc的配置文件里面加上这么一句:

<mvc:default-servlet-handler />
这表示,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。

方案二:

<mvc:resources />
<mvc:default-servlet-handler />将静态资源的处理经由Spring MVC框架交回Web应用服务器处理。而<mvc:resources />更进一步,由Spring MVC框架自己处理静态资源,并添加一些有用的附加值功能:

首先你可以把你的静态文件放到项目的任何地方,比如/WEB-INF下面,classpath下面。而传统的方案,我们只能把静态文件放到web应用的根目录下面。然后通过location属性告诉spring我们的静态资源放在哪里

PS:补充一个知识,什么叫做web应用部署的根目录:http://blog.csdn.net/l00149133/article/details/78984083

其次依据当前著名的Page Speed、YSlow等浏览器优化原则对静态资源提供优化。你可以通过cacheSeconds属性指定静态资源在浏览器端的缓存时间,一般可将该时间设置为一年,以充分利用浏览器端的缓存。在输出静态资源时,会根据配置设置好响应报文头的Expires 和 Cache-Control值。在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,则直接返回303相应状态码,提示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端,以充分节省带宽,提高程序性能。

另外,通过mapping属性我们还可以指定静态资源的访问路径。

举例说明:

<mvc:resources location="/,/WEB-INF/js,classpath:/resource" mapping="resource/**"/>

这里,我们把web部署的根目录"/",以及WEB-INF下的js目录,还有build路径下的resource目录都设置成了静态资源目录,并且映射成resource路径。

假设我们:

在根目录下有个image文件夹,里面有个icon.png文件

WEB-INF下的js目录下有个test.js文件

build路径下的resource目录里有个css/test.css文件

我们可以分别通过:

www.test.com/resource/iamge/icon.png
www.test.com/resource/js/test.js

www.test.com/resource/css/test.css

来访问。

五.<mvc:annotation-driven />

这个有点像是我们之前讲的注解装配<context:annotation-config>,两者都是用来隐式的注册注解所需的bean。

比如你想要用@Autowired注解,如果没有<context:annotation-config>,那你需要手动去声明AutowiredAnnotationBeanPostProcessor的Bean:

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/> 
<context:annotation-config>的作用,就是隐式的帮你声明了这些注解的bean。包括AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及 RequiredAnnotationBeanPostProcessor 这 4 个BeanPostProcessor。

这样你就可以使用诸如@Required, @Autowired, @PostConstruct这些注解。

但是!<context:annotation-config>并没有帮我们声明controller所用的注解,比如@RequestMapping, @Controller。所以我们需要<mvc:annotation-driven />。

实际上<mvc:annotation-driven />注册了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了@Controller注解的使用前提配置。

六.mvc:message-converters消息转换器

这实际上是mvc:annotation-driven的一个子标签,可以看到它主要处理的是response返回的值,比如默认编码,比如支持Fastjson,当然你可以可以加入对其他返回类型的支持,比如gson,protobuf等等

    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <!-- @ResponseBody乱码问题,将StringHttpMessageConverter的默认编码设为UTF-8 -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <!-- 配置Fastjson支持 -->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="charset" value="UTF-8"/>
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json</value>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
                <property name="features">
                    <list>
                        <value>WriteMapNullValue</value>
                        <value>QuoteFieldNames</value>
                        <value>WriteDateUseDateFormat</value>
                        <value>WriteEnumUsingToString</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

七.springmvc拦截器mvc:interceptors

mvc:interceptors用来拦截url请求。

正常的流程,应该是DispatcherServlet先获取所有的URL请求,然后依据规则分发给可以处理这些请求的controller。

而是用mvc:interceptors后,流程变成了:DispatcherServlet先获取所有的URL请求,对于符合拦截器要求格式的URL,先分发给拦截器处理,最后再分发给可以处理这些请求的controller。

举例说明:

	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/static/**" />
			<bean class="com.xxx.interceptor.LoginRequiredInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>
这个拦截器表示,它会拦截所有的URL请求,除了static路径下的请求,并交给LoginRequiredInterceptor来处理


猜你喜欢

转载自blog.csdn.net/l00149133/article/details/78982336
今日推荐