17、Spring MVC 之 COC support

对于很多项目,坚持既定的约定,并设置合理的默认值是他们(项目)所需要的东西。并且Spring WEB MVC已经明确的支持约定优于配置(or Convention over configuration)。这意味着如果你建立一组命名约定等,你可以充分的减少大多数配置。其中必要的设置包含handler mappings,view resolvers, ModelAndView实例等等。对于快速原型这是一个被视为很好的,提供一定程度的(总是好)一致性代码库。你应该选择把它推行到生产环境中。

约定优于配置支持定位MVC三个基本的地方: models, view 和controllers.

1、The Controller ControllerClassNameHandlerMapping

ControllerClassNameHandlerMapping类是HandlerMapping的一个实现.它使用约定去决定requeset URLS与处理这些请求的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会找到所有不同的定义在它的应用context中的handler(or Controller)beans并且剥离Controller中定义的handler mappings。从而,ViewShoppingCartController映射/viewshoppingcart*到请求URL。

让我们看一下一些其它的例子,所以,主要的想法立即变得熟悉。(注意所有URLs中的小名字母,与Controller类名的骆峰式形成对照)。

  • WelcomeController maps to the /welcome* request URL
  • HomeController maps to the /home* request URL
  • IndexController maps to the /index* request URL
  • RegisterController maps to the /register* request URL

在情况下MultiActionController这个handler类,他映射生成更复杂。在下面的例子中,这个Controller名称假定认为是MultiActionController的实现。

  • AdminController maps to the /admin/* request URL
  • CatalogController maps to the /catalog/* request URL

如果你按照约定的命名你的Controller实现为xxxController,ControllerClassNameHandlerMapping会按昭上面保存你的定义并且维持一个的SimpleUrlHandlerMapping(or suchlike).

ControllerClassNameHandlerMapping继承于基类AbstractHandlerMapping,因此你可以定义HandlerInterceptor实例并且你想定义的其它HandlerMapping实现。

2、The Model ModelMap (ModelAndView)

ModelMap类本质上是一个增强的Map,它是一个常见的命名约定,用来添加对应View用来展示的对象。思考一下下面的Controller实现;注意:被添加到ModelAndView的对象并没有指定关联的名称。

public class DisplayShoppingCartController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {

        List cartItems = // get a List of CartItem objects
        User user = // get the User doing the shopping

        ModelAndView mav = new ModelAndView("displayShoppingCart"); <-- the logical view name

        mav.addObject(cartItems); <-- look ma, no name, just the object
        mav.addObject(user); <-- and again ma!

        return mav;
    }
}

ModelAndView类使用一个自定义的Map实现类 – ModelMap。它一个对象被添加到它的时候,它可以自动的为一个对象生成一个key值。决定这个被添加对象的名称的策略,我们以一个标准的User对象来说明。它会使用这个对象类的短类名.下面的例子就是放`进ModelMap实例的标准对象的名称。

  • Anx.y.User 实例被添加会生成user名称.
  • An x.y.Registration 实例被添加会生成registration名称.
  • An x.y.Foo实例被添加会生成foo名称.
  • A java.util.HashMap 实例被添加会生成hashMap名称.你可能想要明确这种情况下的名称,因为hashMap显得并不直观。
  • A null对象被添加会导致抛出IllegalArgumentException异常。如果你想添加的object(or objects)为null,你需要明确的指明它的名称。

What, no automatic pluralization?
Spring Web MVC的约定优于配置并不自动支持泛型。也就是说
也就是说,你不能够添加PersonList对象到ModelAndView中并且生成名称为people.

这个决定会引起后面很多争论,”Principle of Least Surprise”最后赢了。


当添加一个Set或者List对象的时候,它们生成名称的策略可以看一看collection.首先获取集合中第一个对象的类的短名称,然后再这个名称的后面添加"List".对于数组也是一样的。下面的几个例子将会清楚的展现集合名称生成的语法:

  • An x.y.User[] 如果有一个或者多个x.y.User元素将生成添加userList名称.
  • An x.y.Foo[] 如果有一个或者多个 x.y.User元素将生成添加fooList 名称.
  • A java.util.ArrayList如果有一个或者多个 x.y.User 元素将生成添加userList名称.
  • A java.util.HashSet 如果有一个或者多个 x.y.Foo 元素将生成添加fooList 名称.
  • An empty java.util.ArrayList 不会添加元素 (事额头上, the addObject(..) 将不会被调用).
3、The View - RequestToViewNameTranslator

当没有明确提出相应的逻辑view名称,RequestToViewNameTranslator会确定一个逻辑上的View名称。它仅有一个实现,就是DefaultRequestToViewNameTranslator

DefaultRequestToViewNameTranslator会映射requeset URL到一个逻辑的页面名称,正如下面的这个例子:

public class RegistrationController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
        // process the request...
        ModelAndView mav = new ModelAndView();
        // add data as necessary to the model...
        return mav;
        // notice that no View or logical view name has been set
    }

}
<?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会负责对request的URL生成一个逻辑的页面名称.RegistrationController这种情况下,ControllerClassNameHandlerMapping结合使用的是哪一个,DefaultRequestToViewNameTranslator会生成一个registration逻辑名称用来关联http://localhost/registration.html这个request URL。这个逻辑页面名称然后通过InternalResourceViewResolver这个bean来解析成/WEB-INF/jsp/registration.jsp


注意 :
你不需要明确的定义一个DefaultRequestToViewNameTranslatorbean。如果你喜欢DefaultRequestToViewNameTranslator的默认设置,如果你没有明确配置的话,你可以依赖Spring Web MVC中的DispatcerServlet来实例化这个类的实例。


当然,如果你需要改变默认的设置,你可以明确的配置你自己的DefaultRequestToViewNameTranslator bean。可以查看DefaultRequestToViewNameTranslator的javadocs了解关于它可以配置的各种properties的详情。

因为水平有限,翻译不足之处还望见谅。
原文地址:spring-framework-reference-4.2.6.RELEASE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值