SpringMVC(16) - 约定优于配置支持

参考:https://docs.spring.io/spring/docs/4.3.20.RELEASE/spring-framework-reference/htmlsingle/#mvc-coc

 

对于很多项目来说,坚持已建立的约定并且具有合理的默认值正是他们(项目)所需要的,而Spring Web MVC现在明确支持约定优于配置。这意味着如果你建立了一组命名约定等,你可以大大减少设置处理器映射、视图解析器、ModelAndView实例等所需的配置量。这对于快速原型设计是一个很大的好处,如果选择将其推向生产阶段,还可以在代码库中提供一定程度的(始终是良好的)一致性。

Convention-over-configuration(约定优于配置)的支持解决了MVC的三个核心领域:模型,视图和控制器。

 

1. 控制器ControllerClassNameHandlerMapping
ControllerClassNameHandlerMapping类是一个HandlerMapping实现,它使用约定来确定请求URL与要处理这些请求的Controller实例之间的映射。

考虑以下简单的Controller实现。特别注意类名称。

public class ViewShoppingCartController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
        // the implementation is not hugely important for this example...
    }

}

以下是相应Spring Web MVC配置文件的片段:

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

<bean id="viewShoppingCart" class="x.y.z.ViewShoppingCartController">
    <!-- inject dependencies as required... -->
</bean>

ControllerClassNameHandlerMapping查找在其应用程序上下文中定义的所有各种处理器(或Controller)bean,并从名称中删除Controller以定义其处理器映射。因此,ViewShoppingCartController映射到 /viewshoppingcart* 请求URL。

示例: (注意URL中的所有小写,与驼峰式的Controller类名相反。)

  • WelcomeController:映射到/welcome*请求URL
  • HomeController:映射到/home*请求URL
  • IndexController:映射到/index*请求URL
  • RegisterController:映射到/register*请求URL

对于MultiActionController处理器类,生成的映射稍微复杂一些。以下示例中的Controller名称假定为MultiActionController实现:

  • AdminController:映射到/admin/*请求URL
  • CatalogController:映射到/catalog/*请求URL

如果遵循将Controller实现命名为xxxController的约定,ControllerClassNameHandlerMapping将节省定义和维护潜在的looooong SimpleUrlHandlerMapping(或类似)的繁琐。

ControllerClassNameHandlerMapping类扩展了AbstractHandlerMapping基类,因此可以像许多其他HandlerMapping实现一样定义HandlerInterceptor实例和其他所有实例。

 

2. 模型 ModelMap(ModelAndView)
ModelMap类本质上是一个Map,可以使添加要在View中(或在View上)显示的对象遵循通用的命名约定。考虑以下Controller实现;请注意,在未指定任何关联名称的情况下将对象添加到ModelAndView。

public class DisplayShoppingCartController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {

        List cartItems = // 获取CartItem对象列表
        User user = // 获取当前购物的用户

        ModelAndView mav = new ModelAndView("displayShoppingCart"); <-- 逻辑视图名称

        mav.addObject(cartItems); <-- 没有名称,只有对象
        mav.addObject(user); <-- 同上

        return mav;
    }
}

ModelAndView类使用ModelMap类,该类是一个自定义Map实现,在对象添加到对象时自动生成对象的key。确定添加对象的名称的策略是,在诸如User之类的纯量对象的情况下,使用对象类的短类名。以下示例是为放入ModelMap实例的纯量对象生成的名称。

  • x.y.User实例:生成名称为 user 的key
  • x.y.Registration实例:生成名称为 registration 的key
  • x.y.Foo实例:生成名称为 foo 的key
  • java.util.HashMap实例:生成名称为 hashMap 的key。在这种情况下,可能希望明确名称,因为hashMap不够直观。
  • null:将导致抛出IllegalArgumentException。如果要添加的对象(或多个对象)可能为null,那么还需要明确该名称。

注:

什么,没有自动复数?

Spring Web MVC的约定配置支持不支持自动为数组、集合生成key。也就是说,不能将Person对象列表添加到ModelAndView并将生成的名称设置为 people。

这个决定是在经过一番辩论之后作出的,最终的"Principle of Least Surprise"获胜。

添加Set或List后生成名称的策略是查看集合,获取集合中第一个对象的短类名,并使用List附加到名称。这同样适用于数组,尽管使用数组时不必查看数组内容。示例:

  • x.y.User[]数组:0或多个元素,生成名称为 userList 的key
  • x.y.Foo[]数组:0或多个元素,生成名称为 fooList 的key
  • java.util.ArrayList:一个或多个x.y.User元素,生成名称为 userList 的key
  • java.util.HashSet:一个或多个x.y.Foo元素,生成名称为 fooList 的key
  • java.util.ArrayList:空集合,addObject(...) 调用是无操作的,即根本不会被添加

 

3. 默认视图名称
当没有显式提供此类逻辑视图名称时,RequestToViewNameTranslator接口确定逻辑视图名称。它只有一个实现,DefaultRequestToViewNameTranslator类。

DefaultRequestToViewNameTranslator将请求URL映射到逻辑视图名称,如下例所示:

public class RegistrationController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
        // 处理请求...
        ModelAndView mav = new ModelAndView();
        // 必要时添加数据至model...
        return mav;
        // 提示,没有View或设置逻辑视图名称
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- this bean with the well known name generates view names for us -->
    <bean id="viewNameTranslator"
            class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>

    <bean class="x.y.RegistrationController">
        <!-- inject dependencies as necessary -->
    </bean>

    <!-- maps request URLs to Controller names -->
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

请注意,在handleRequest(...)方法的实现中,如何在返回的ModelAndView上设置View或逻辑视图名称。 DefaultRequestToViewNameTranslator的任务是从请求的URL生成逻辑视图名称。在上述RegistrationController(与ControllerClassNameHandlerMapping一起使用)的情况下,http://localhost/registration.html的请求URL导致由DefaultRequestToViewNameTranslator生成的注册的逻辑视图名称。然后,InternalResourceViewResolver bean将此逻辑视图名称解析为/WEB-INF/jsp/registration.jsp视图。

提示:
不需要显式定义DefaultRequestToViewNameTranslator bean。如果喜欢DefaultRequestToViewNameTranslator的默认设置,则可以依赖Spring Web MVC DispatcherServlet来实例化此类的实例(如果未明确配置该实例)。

当然,如果需要更改默认设置,则需要显式配置自己的DefaultRequestToViewNameTranslator bean。有关可配置的各种属性的详细信息,参考DefaultRequestToViewNameTranslator javadoc文档。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值