spring-mvc.xml杂说(待续)

注解说:

<context:component-scan>
在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller @Service等这些注解的类,则把这些类注册为bean
注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context:component-scan>还提供了两个子标签
1.        <context:include-filter>
2.       <context:exclude-filter>
对@Component:解释:
通过@Component将切面定义为Spring管理Bean。
@Component:定义Spring管理Bean,对@Component进行分类注解,如下三个:
@Repository:
@Component扩展,被@Repository注解的POJO类表示DAO层实现,从而见到该注解就想到DAO层实现,使用方式和@Component相同;
@Service:
@Component扩展,被@Service注解的POJO类表示Service层实现,从而见到该注解就想到Service层实现,使用方式和@Component相同;
@Controller:
@Component扩展,被@Controller注解的类表示Web层实现,从而见到该注解就想到Web层实现,使用方式和@Component相同;


列如:<context:component-scan base-package="com.fh">,启动服务只会扫描com.fh路径下的类文件
<context:component-scan base-package="com.fh">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>
在说明这两个子标签前,先说一下<context:component-scan>有一个use-default-filters属性,改属性默认为true,这就意味着会扫描指定包下的全部的标有@Component的类,并注册成bean.也就是@Component的子注解@Service,@Reposity等。所以如果仅仅是在配置文件中这么写
<context:component-scan base-package="tv.huan.weisp.web"/>
 Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。
 
 可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?此时子标签<context:incluce-filter>就起到了勇武之地。如下所示
<context:component-scan base-package="tv.huan.weisp.web .controller">  
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  
这样就会只扫描base-package指定下的有@Controller下的java类,并注册成bean
但是因为use-dafault-filter在上面并没有指定,默认就为true,所以当把上面的配置改成如下所示的时候,就会产生与你期望相悖的结果(注意base-package包值得变化)
<context:component-scan base-package="tv.huan.weisp.web">  
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  
此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类
此时指定的include-filter没有起到作用,只要把use-default-filter设置成false就可以了。这样就可以避免在base-packeage配置多个包名这种不是很优雅的方法来解决这个问题了。
另外在我参与的项目中可以发现在base-package指定的包中有的子包是不含有注解了,所以不用扫描,此时可以指定<context:exclude-filter>来进行过滤,说明此包不需要被扫描。综合以上说明
Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描

@ControllerAdvice注解的使用:从名字上可以看出大体意思是控制器增强,使用<context:component-scan>扫描时也能扫描到

/**
 * 1、通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置。
 * 2、注解了@Controller的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
 * 3、@ControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上。
 * 4、@ExceptionHandler:用于全局处理控制器里的异常。
 * 5、@InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中。
 * 6、@ModelAttribute:本来作用是绑定键值对到Model中,此处让全局的@RequestMapping都能获得在此处设置的键值对
/
列如:
@ControllerAdvice//
public class CommonController {
@ModelAttribute
public void addGlobalAttributes(Model model) {
        //催收关系下拉框列表
        model.addAttribute("callshipmap", JSON.toJSON(Const.CALLSHIPMAP));
        //催收结果下拉框列表(新增)
        model.addAttribute("callresulttypen", JSON.toJSON(Const.CALLRESULTMAPN));
        //催收结果下拉框列表(查询)
        model.addAttribute("callresulttypef", JSON.toJSON(Const.CALLRESULTMAPF));
        //联系人关系下拉列表
        model.addAttribute("linkManShipMap", JSON.toJSON(Const.linkManShip));
}
}
<c:forEach  var="callRecord" varStatus="var"  items="${callresulttypen}"></c:forEach>//中的可以直接从该类中拿到对应的集合


<mvc:default-servlet-handler />和<mvc:resources />说

web.xml中的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>
通过上面url-pattern的配置,所有URL请求都将被Spring MVC的DispatcherServlet截获。


方法1.采用<mvc:default-servlet-handler />//
访问静态资源

在springMVC-servlet.xml中配置<mvc:default-servlet-handler/>后,会在SpringMVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。

一般Web应用服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:

<mvc:default-servlet-handler default-servlet-name="所使用的Web服务器默认使用的Servlet名称" />

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

首先,<mvc:resources/>允许静态资源放在任何地方,如WEB-INF目录下、类路径下等,你甚至可以将JavaScript等静态文件打到JAR包中。通过location属性指定静态资源的位置,由于location属性是Resources类型,因此可以使用诸如"classpath:"等的资源前缀指定资源位置。传统Web容器的静态资源只能放在Web容器的根路径下,<mvc:resources/>完全打破了这个限制。

其次,<mvc:resources/>依据当前著名的PageSpeed、YSlow等浏览器优化原则对静态资源提供优化。你可以通过cacheSeconds属性指定静态资源在浏览器端的缓存时间,一般可将该时间设置为一年,以充分利用浏览器端的缓存。在输出静态资源时,会根据配置设置好响应报文头的Expires 和 Cache-Control值。

在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,则直接返回303相应状态码,提示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端,以充分节省带宽,提高程序性能。

在springMVC-servlet中添加如下配置:<mvc:resources location="/,classpath:/META-INF/publicResources/" mapping="/resources/**"/>

以上配置将Web根路径"/"及类路径下/META-INF/publicResources/的目录映射为/resources路径。假设Web根路径下拥有images、js这两个资源目录,在images下面有bg.gif图片,在js下面有test.js文件,则可以通过 /resources/images/bg.gif 和 /resources/js/test.js 访问这二个静态资源。

假设WebRoot还拥有images/bg1.gif 及 js/test1.js,则也可以在网页中通过 /resources/images/bg1.gif 及 /resources/js/test1.js 进行引用。

列如:<mvc:resources mapping="/static/**" location="/,/static/" />  对应项目中的:collection\src\main\webapp\static\1.9.1\jquery.min.js


<mvc:annotation-driven>说

<mvc:annotation-driven/>相当于注册了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了@Controller注解的使用前提配置。
<context:annotation-config/>是对包进行扫描,实现注释驱动Bean定义,同时将bean自动注入容器中使用。即解决了@Controller标识的类的bean的注入和使用,列如:想使用@Autowired,@ Resource等注解,那么就必须事先在 Spring 容器中声明,但是使用<context:component-scan/> 之后,<context:annotation-config/>就可以省略,后者包括了前者


一开始我在写配置的时候,只写了<context:component-scan/>,并没有使用<mvc:annotation-driven/>,servlet拦截*.do,.do请求可以被正确捕捉和处理。代码如下
mvc-servlet.xml
<context:component-scan base-package="com"></context:component-scan>  
web.xml如下
<servlet>  
    <servlet-name>mvc</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <load-on-startup>1</load-on-startup>  
</servlet>  
<servlet-mapping>  
    <servlet-name>mvc</servlet-name>  
    <url-pattern>*.do</url-pattern>  //(2)中解释:
</servlet-mapping>  


如果没有<mvc:annotation-driven/>注解启动,那么所有的Controller可能就没有解析,所有当有请求时候都没有匹配的处理请求类,就都去<mvc:default-servlet-handler/>即defaultservlet处理了。添加上<mvc:annotation-driven/>后,相应的do请求被Controller处理,而静态资源因为没有相应的Controller就会被defaultservlet处理。总之没有相应的Controller就会被default servlet处理就ok了


(2)一个servlet可以使用多个url-pattern规则,每个<url-pattern>标签代表1个匹配规则;url-pattern映射匹配过程是有优先顺序的;而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了。
1、精确匹配,servlet-mapping1:<url-pattern>/user/users.html</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配/
2、路径匹配,先最长路径匹配,再最短路径匹配servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
3、扩展名匹配,servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>*.action</url-pattern>。当一个请求http://localhost:8080/appDemo/user/addUser.action来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配/
4、缺省匹配,以上都找不到servlet,就用默认的servlet,配置为<url-pattern>/</url-pattern>


同时设定<mvc:message-converters> 标签,设定字符集和json处理类,例如:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- json处理 -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值