Spring 25新特性第二部分Spring MVC中的新特性.docx

上传人:b****5 文档编号:12148243 上传时间:2023-04-17 格式:DOCX 页数:23 大小:26.37KB
下载 相关 举报
Spring 25新特性第二部分Spring MVC中的新特性.docx_第1页
第1页 / 共23页
Spring 25新特性第二部分Spring MVC中的新特性.docx_第2页
第2页 / 共23页
Spring 25新特性第二部分Spring MVC中的新特性.docx_第3页
第3页 / 共23页
Spring 25新特性第二部分Spring MVC中的新特性.docx_第4页
第4页 / 共23页
Spring 25新特性第二部分Spring MVC中的新特性.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

Spring 25新特性第二部分Spring MVC中的新特性.docx

《Spring 25新特性第二部分Spring MVC中的新特性.docx》由会员分享,可在线阅读,更多相关《Spring 25新特性第二部分Spring MVC中的新特性.docx(23页珍藏版)》请在冰豆网上搜索。

Spring 25新特性第二部分Spring MVC中的新特性.docx

Spring25新特性第二部分SpringMVC中的新特性

Spring2.5新特性-第二部分-SpringMVC中的新特性

Spring框架从创建伊始就致力于为复杂问题提供强大的、非侵入性的解决方案。

Spring2.0当中为缩减XML配置文件数量引入定制命名空间功能,从此它便深深植根于核心Spring框架(aop、context、jee、jms、lang、tx和util命名空间)、SpringPortfolio项目(例如SpringSecurity)和非Spring项目中(例如CXF)。

Spring2.5推出了一整套注解,作为基于XML的配置的替换方案。

注解可用于Spring管理对象的自动发现、依赖注入、生命周期方法、Web层配置和单元/集成测试。

探索Spring2.5中引入的注解技术系列文章由三部分组成,本文是其中的第二篇,它主要讲述了Web层中的注解支持。

最后一篇文章将着重介绍可用于集成和测试的其它特性。

这个系列文章的第一部分论述了Java注解(annotation)是如何代替XML来配置Spring管理对象和依赖注入的。

我们再用一个例子回顾一下:

Java代码

1.@Controller  

2. public class ClinicController {  

3.  

4.    private final Clinic clinic;  

5.  

6.    @Autowired  

7.    public ClinicController(Clinic clinic) {  

8.       this.clinic = clinic;  

9.    }  

10.    ...  

@Controller

publicclassClinicController{

privatefinalClinicclinic;

@Autowired

publicClinicController(Clinicclinic){

this.clinic=clinic;

}

...

@Controller表明ClinicController是Web层组件,@Autowired请求一个被依赖注入的Clinic实例。

这个例子只需要少量的XML语句就能使容器识别两个注解,并限定组件的扫描范围:

Java代码

1.

component-scan base-package="org.springframework.samples.petclinic"/>  

component-scanbase-package="org.springframework.samples.petclinic"/>

这对Web层可谓是个福音,因为在这层Spring的XML配置文件已日益臃肿,甚至可能还不如层下的配置来得有用。

控制器掌握着许多属性,例如视图名称、表单对象名称和验证器类型,这些多是关乎配置的,甚少关于依赖注入的。

通过bean定义继承,或者避免配置变化不是很频繁的属性,也可以有效的管理类似的配置。

不过以我的经验,很多开发人员都不会这样做,结果就是XML文件总比实际需要的要庞大。

不过@Controller和@Autowired对Web层的配置会产生积极的作用。

在系列文章的第二部分我们将继续讨论这个问题,并浏览Spring2.5在Web层的注解技术。

这些注解被非正式的称为@MVC,它涉及到了SpringMVC和SpringPorletMVC,实际上本文讨论的大部分功能都可以应用在这两个框架上。

从Controller到@Controller

与第一部分讨论的注解相比,@MVC已不只是作为配置的一种替换方案这样简单了,考虑下面这个著名的SpringMVC控制器签名:

Java代码

1.public interface Controller {  

2.    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse   

3.response) throws Exception;  

4. }  

publicinterfaceController{

ModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponse

response)throwsException;

}

所有的SpringMVC控制器要么直接实现Controller接口,要么就得扩展类似AbstractController、SimpleFormController、MultiActionController或AbstractWizardFormController这样的基类实现。

正是Controller接口允许SpringMVC的DispatcherServlet把所有上述对象都看作是“处理器(handlers)”,并在一个名为SimpleControllerHandlerAdapter的适配器的帮助下调用它们。

@MVC从三个重要的方面改变了这个程序设计模型:

  1.不需要任何接口或者基类。

  2.允许有任意数量的请求处理方法。

  3.在方法签名上具有高度的灵活性。

考虑到以上三个要点,就可以说很公平的说@MVC不仅仅是个替换方案了,它将会是SpringMVC的控制器技术演变过程中下一个重要步骤。

DispatcherServlet在名为AnnotationMethodHandlerAdapter的适配器帮助下调用被注解的控制器。

正是这个适配器做了大量工作支持我们此后将会讨论的注解,同时也是它有效的取代了对于控制器基类的需求。

@RequestMapping简介

我们还是从一个类似于传统的SpringMVCController控制器开始:

Java代码

1.@Controller  

2. public class AccountsController {  

3.  

4.    private AccountRepository accountRepository;  

5.  

6.    @Autowired  

7.    public AccountsController(AccountRepository accountRepository) {  

8.       this.accountRepository = accountRepository;  

9.    }  

10.  

11.    @RequestMapping("/accounts/show")  

12.    public ModelAndView show(HttpServletRequest request,  

13.                             HttpServletResponse response) throws Exception {  

14.       String number = ServletRequestUtils.getStringParameter(request, "number");  

15.       ModelAndView mav = new ModelAndView("/WEB-INF/views/accounts/show.jsp");  

16.       mav.addObject("account", accountRepository.findAccount(number));  

17.       return mav;  

18.    }  

@Controller

publicclassAccountsController{

privateAccountRepositoryaccountRepository;

@Autowired

publicAccountsController(AccountRepositoryaccountRepository){

this.accountRepository=accountRepository;

}

@RequestMapping("/accounts/show")

publicModelAndViewshow(HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

Stringnumber=ServletRequestUtils.getStringParameter(request,"number");

ModelAndViewmav=newModelAndView("/WEB-INF/views/accounts/show.jsp");

mav.addObject("account",accountRepository.findAccount(number));

returnmav;

}

}

此处与以往的不同在于,这个控制器并没有扩展Controller接口,并且它用@RequestMapping注解指明show()是映射到URI路径“/accounts/show”的请求处理方法。

除此以外,其余代码都是一个典型的SpringMVC控制器应有的内容。

在将上述的方法完全转化到@MVC后,我们会再回过头来看@RequestMapping,但是在此之前还有一点需要提请注意,上面的请求映射URI也可匹配带有任意扩展名的URI路径,例如:

Java代码

1./accounts/show.htm  

2. /accounts/show.xls  

3. /accounts/show.pdf  

4. ...  

/accounts/show.htm

/accounts/show.xls

/accounts/show.pdf

...

灵活的请求处理方法签名

我们曾经承诺过要提供灵活的方法签名,现在来看一下成果。

输入的参数中移除了响应对象,增加了一个代表模型的Map;返回的不再是ModelAndView,而是一个字符串,指明呈现响应时要用的视图名字:

Java代码

1.@RequestMapping("/accounts/show")  

2. public String show(HttpServletRequest request, Map model)  

3. throws Exception {  

4.    String number = ServletRequestUtils.getStringParameter(request, "number");  

5.    model.put("account", accountRepository.findAccount(number));  

6.    return "/WEB-INF/views/accounts/show.jsp";  

7. }  

@RequestMapping("/accounts/show")

publicStringshow(HttpServletRequestrequest,Mapmodel)

throwsException{

Stringnumber=ServletRequestUtils.getStringParameter(request,"number");

model.put("account",accountRepository.findAccount(number));

return"/WEB-INF/views/accounts/show.jsp";

}

Map输入参数是一个“隐式的”模型,对于我们来说在调用方法前创建它很方便,其中添加的键—值对数据便于在视图中解析应用。

本例视图为show.jsp页面。

@MVC可以接受多种类型的输入参数,例如HttpServletRequest/HttpServletResponse、HttpSession、Locale、InputStream、OutputStream、File[]等等,它们的顺序不受任何限制;同样它也允许多种返回类型,例如ModelAndView、Map、String,或者什么都不返回。

你可以查看@RequestMapping的JavaDoc以了解它支持的所有输入和返回参数类型。

有种令人感兴趣的情形是当方法没有指定视图时(例如返回类型为void)会有什么事情发生,按照惯例DispatcherServlet要再使用请求URI的路径信息,不过要移去前面的斜杠和扩展名。

让我们把返回类型改为void:

Java代码

1.@RequestMapping("/accounts/show")  

2. public void show(HttpServletRequest request, Map model) throws Exception {  

3.    String number = ServletRequestUtils.getStringParameter(request, "number");  

4.    model.put("account", accountRepository.findAccount(number));  

5. }  

@RequestMapping("/accounts/show")

publicvoidshow(HttpServletRequestrequest,Mapmodel)throwsException{

Stringnumber=ServletRequestUtils.getStringParameter(request,"number");

model.put("account",accountRepository.findAccount(number));

}

对于给定的请求处理方法和“/accounts/show”的请求映射,我们可以期望DispatcherServlet能够获得“accounts/show”的默认视图名称,当它与如下适当的视图解析器结合共同作用时,会产生与前面指明返回视图名同样的结果:

Java代码

1.  

2.      

3.      

4.   

强烈推荐视图名称依赖惯例的方式,因为这样可以从控制器代码中消除硬编码的视图名称。

如果你想定制DispatcherServlet获取默认视图名的方式,就在servlet上下文环境中配置一个你自己的RequestToViewNameTranslator实现,并为其beanid赋名为“viewNameTranslator”。

用@RequestParam提取和解析参数

@MVC另外一个特性是其提取和解析请求参数的能力。

让我们继续重构上面的方法,并在其中添加@RequestParam注解:

Java代码

1.@RequestMapping("/accounts/show")  

2. public void show(@RequestParam("number") String number, Map model) {  

3.    model.put("account", accountRepository.findAccount(number));  

4. }  

@RequestMapping("/accounts/show")

publicvoidshow(@RequestParam("number")Stringnumber,Mapmodel){

model.put("account",accountRepository.findAccount(number));

}

这里@RequestParam注解可以用来提取名为“number”的String类型的参数,并将之作为输入参数传入。

@RequestParam支持类型转换,还有必需和可选参数。

类型转换目前支持所有的基本Java类型,你可通过定制的PropertyEditors来扩展它的范围。

下面是一些例子,其中包括了必需和可选参数:

Java代码

1.@RequestParam(value="number", required=false) String number  

2. @RequestParam("id") Long id  

3. @RequestParam("balance") double balance  

4. @RequestParam double amount  

@RequestParam(value="number",required=false)Stringnumber

@RequestParam("id")Longid

@RequestParam("balance")doublebalance

@RequestParamdoubleamount

注意,最后一个例子没有提供清晰的参数名。

当且仅当代码带调试符号编译时,结果会提取名为“amount”的参数,否则,将抛出IllegalStateException异常,因为当前的信息不足以从请求中提取参数。

由于这个原因,在编码时最好显式的指定参数名。

继续@RequestMapping的讨论

把@RequestMapping放在类级别上是合法的,这可令它与方法级别上的@RequestMapping注解协同工作,取得缩小选择范围的效果,下面是一些例子。

类级别:

Java代码

1.RequestMapping("/accounts/*")  

2.  

3.方法级别:

  

4.@RequestMapping(value="delete", method=RequestMethod.POST)  

5.@RequestMapping(value="index", method=RequestMethod.GET, params="type=checking")  

6.@RequestMapping  

RequestMapping("/accounts/*")

方法级别:

@RequestMapping(value="delete",method=RequestMethod.POST)

@RequestMapping(value="index",method=RequestMethod.GET,params="type=checking")

@RequestMapping

第一个方法级的请求映射和类级别的映射结合,当HTTP方法是POST时与路径“/accounts/delete”匹配;第二个添加了一个要求,就是名为“type”的请求参数和其值“checking”都需要在请求中出现;第三个根本就没有指定路径,这个方法匹配所有的HTTP方法,如果有必要的话可以用它的方法名。

下面改写我们的方法,使它可以依靠方法名进行匹配,程序如下:

Java代码

1.@Controller  

2. @RequestMapping("/accounts/*")  

3. public class AccountsController {  

4.  

5.    @RequestMapping(method=RequestMethod.GET)  

6.    public void show(@RequestParam("number") String number, Map model)  

7.   {  

8.       model.put("account", accountRepository.findAccount(number));  

9.    }  

10.    ...  

@Controller

@RequestMapping("/accounts/*")

publicclassAccountsController{

@RequestMapping(method=RequestMethod.GET)

publicvoidshow(@RequestParam("number")Stringnumber,Mapmodel)

{

model.put("account",accountRepository.findAccount(number));

}

...

方法匹配的请求是“/accounts/show”,依据的是类级别的@RequestMapping指定的匹配路径“/accounts/*”和方法名“show”。

消除类级别的请求映射

Web层注解频遭诟病是有事实依据的,那就是嵌入源代码的URI路径。

这个问题很好矫正,URI路径和控制器类之间的匹配关系用XML配置文件去管理,只在方法级的映射中使用@RequestMapping注解。

我们将配置一个ControllerClassNameHandlerMapping,它使用依赖控制器类名字的惯例,将URI映射到控制器:

Java代码

1.  

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 实习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1