`
jinnianshilongnian
  • 浏览: 21504172 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418704
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008810
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639502
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259925
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597331
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250226
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858967
Group-logo
跟我学Nginx+Lua开...
浏览量:702014
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785226
社区版块
存档分类
最新评论

注解式控制器运行流程及处理器定义 第六章 注解式控制器详解——跟着开涛学SpringMVC

 
阅读更多

 

声明:本系列都是原创内容,觉得好就顶一个,让更多人知道!! 希望那些的人给出不好的理由,我会积极改正。写博客不容易,写原创更不容易!!


6.1
、注解式控制器简介

一、Spring2.5之前,我们都是通过实现Controller接口或其实现来定义我们的处理器类。已经@Deprecated。

 

二、Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMapping注解定义我们的处理器类。

并且提供了一组强大的注解:

 

需要通过处理器映射DefaultAnnotationHandlerMapping和处理器适配器

AnnotationMethodHandlerAdapter来开启支持@Controller 和

@RequestMapping注解的处理器。

 

@Controller:用于标识是处理器类;

@RequestMapping:请求到处理器功能方法的映射规则;

@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;

@ModelAttribute:请求参数到命令对象的绑定;

@SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出

模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中;

@InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;

 

三、Spring3.0引入RESTful架构风格支持(通过@PathVariable注解和一些其他特性支持),且又引入了

更多的注解支持:

@CookieValue:cookie数据到处理器功能处理方法的方法参数上的绑定;

@RequestHeader:请求头(header)数据到处理器功能处理方法的方法参数上的绑定;

@RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换);

@ResponseBody:处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换);

@ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和原因;

@ExceptionHandler:注解式声明异常处理器;

@PathVariable:请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定,

从而支持RESTful架构风格的URI;

 

四、Spring3.1使用新的HandlerMapping 和 HandlerAdapter来支持@Contoller和@RequestMapping

注解处理器。

新的@Contoller和@RequestMapping注解支持类:处理器映射RequestMappingHandlerMapping

处理器适配器RequestMappingHandlerAdapter组合来代替Spring2.5开始的处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter

提供更多的扩展点。

 

接下来,我们一起开始学习基于注解的控制器吧。

②、④、⑥一般是可变的,因此我们可以这些信息进行请求到处理器的功能处理方法的映射,

因此请求的映射分为如下几种:

 

URL路径映射:使用URL映射请求到处理器的功能处理方法;

请求方法映射限定:如限定功能处理方法只处理GET请求;

请求参数映射限定:如限定只处理包含“abc”请求参数的请求;

请求头映射限定:如限定只处理“Accept=application/json”的请求。

 

接下来看看具体如何映射吧。

 

6.2、入门

(1、控制器实现


java代码:
package cn.javass.chapter6.web.controller;
//省略import
@Controller         // 或 @RequestMapping               //①将一个POJO类声明为处理器
public class HelloWorldController {
    @RequestMapping(value = "/hello")                  //②请求URL到处理器功能处理方法的映射
    public ModelAndView helloWorld() {
		//1、收集参数
		//2、绑定参数到命令对象
		//3、调用业务对象
		//4、选择下一个页面
		ModelAndView mv = new ModelAndView();
		//添加模型数据 可以是任意的POJO对象
		mv.addObject("message", "Hello World!");
		//设置逻辑视图名,视图解析器会根据该名字解析到具体的视图页面
		mv.setViewName("hello");
		return mv;                                         //○3 模型数据和逻辑视图名
	}
}


 

可以通过在一个POJO类上放置@Controller或@RequestMapping,即可把一个POJO类变身为处理器;

@RequestMapping(value = "/hello") 请求URL(/hello) 到 处理器的功能处理方法的映射;

模型数据和逻辑视图名的返回。

 

现在的处理器无需实现/继承任何接口/类,只需要在相应的类/方法上放置相应的注解说明下即可,

非常方便。

 

2、Spring配置文件chapter6-servlet.xml

2.1、HandlerMapping和HandlerAdapter的配置

如果您使用的是Spring3.1之前版本,开启注解式处理器支持的配置为:

DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。

 

java代码:
<!—Spring3.1之前的注解 HandlerMapping -->
<bean 
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>

<!—Spring3.1之前的注解 HandlerAdapter -->
<bean 
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
    

 

如果您使用的Spring3.1开始的版本,建议使用RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

 

java代码:
<!--Spring3.1开始的注解 HandlerMapping -->
<bean 
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--Spring3.1开始的注解 HandlerAdapter -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

 

下一章我们介绍DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter

与RequestMappingHandlerMapping和RequestMappingHandlerAdapter 的区别。

 

2.2、视图解析器的配置

还是使用之前的org.springframework.web.servlet.view.InternalResourceViewResolver。

2.3、处理器的配置

 

 

java代码:
<!-- 处理器 -->
<bean class="cn.javass.chapter6.web.controller.HelloWorldController"/>

 

只需要将处理器实现类注册到spring配置文件即可,spring的DefaultAnnotationHandlerMapping或RequestMappingHandlerMapping

能根据注解@Controller或@RequestMapping自动发现。

 

2.4、视图页面(/WEB-INF/jsp/hello.jsp)

 

 

java代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
${message}
</body>
</html>

 

${message}表示显示由HelloWorldController处理器传过来的模型数据。

 

4、启动服务器测试

地址栏输入http://localhost:9080/springmvc-chapter6/hello,我们将看到页面显示“Hello World!”,

表示成功了。

 

整个过程和我们第二章中的Hello World 类似,只是处理器的实现不一样。接下来我们来看一下具体流程吧。

6.3、运行流程

 

 

和第二章唯一不同的两处是:

1、HandlerMapping实现:使用DefaultAnnotationHandlerMapping(spring3.1之前)或RequestMappingHandlerMapping(spring3.1)

替换之前的BeanNameUrlHandlerMapping

注解式处理器映射会扫描spring容器中的bean,发现bean实现类上拥有

@Controller或@RequestMapping注解的bean,并将它们作为处理器。

 

2、HandlerAdapter实现:使用AnnotationMethodHandlerAdapter(spring3.1之前)或RequestMappingHandlerAdapter(spring3.1)替换之前的SimpleControllerHandlerAdapter

注解式处理器适配器会通过反射调用相应的功能处理方法(方法上拥有@RequestMapping注解)。

 

好了到此我们知道Spring如何发现处理器、如何调用处理的功能处理方法了,接下来我们

详细学习下如何定义处理器、如何进行请求到功能处理方法的定义。

 

6.4、处理器定义

6.4.1、@Controller

 

java代码:
@Controller
public class HelloWorldController {
……
}

 

推荐使用这种方式声明处理器,它和我们的@Service、@Repository很好的对应了我们常见的三层开发架构的组件。

 

6.4.2、@RequestMapping

 

java代码:
@RequestMapping
public class HelloWorldController {
……
}

 

这种方式也是可以工作的,但如果在类上使用@ RequestMapping注解一般是用于

窄化功能处理方法的映射的,详见6.4.3。

 

 

package cn.javass.chapter6.web.controller;
@Controller
@RequestMapping(value="/user")                 //①处理器的通用映射前缀
public class HelloWorldController2 {
    @RequestMapping(value = "/hello2")        //②相对于①处的映射进行窄化
    public ModelAndView helloWorld() {
         //省略实现
    }
}

6.4.3、窄化请求映射

 

java代码:
package cn.javass.chapter6.web.controller;
@Controller
@RequestMapping(value="/user")                 //①处理器的通用映射前缀
public class HelloWorldController2 {
    @RequestMapping(value = "/hello2")        //②相对于①处的映射进行窄化
    public ModelAndView helloWorld() {
         //省略实现
    }
}

①类上的@RequestMapping(value="/user") 表示处理器的通用请求前缀;

②处理器功能处理方法上的是对①处映射的窄化。

 

因此http://localhost:9080/springmvc-chapter6/hello2 无法映射到HelloWorldController2的 helloWorld功能处理方法;而http://localhost:9080/springmvc-chapter6/user/hello2是可以的。

 

窄化请求映射可以认为是方法级别的@RequestMapping继承类级别的@RequestMapping。

 

窄化请求映射还有其他方式,如在类级别指定URL,而方法级别指定请求方法类型或参数等等,

后续会详细介绍。

 

到此,我们知道如何定义处理器了,接下来我们需要学习如何把请求映射到相应的功能处理方法

进行请求处理。

6.5、请求映射

处理器定义好了,那接下来我们应该定义功能处理方法,接收用户请求处理并选择视图进行渲染。

首先我们看一下图6-1:

 

 

http请求信息包含六部分信息:
①请求方法,如GET或POST,表示提交的方式;
URL,请求的地址信息;
③协议及版本
④请求头信息(包括Cookie信息);
⑤回车换行CRLF);
⑥请求内容区(即请求的内容或数据),如表单提交时的参数数据、URL请求参数(?abc=123 后边的)等。
想要了解HTTP/1.1协议,请访问http://tools.ietf.org/html/rfc2616
那此处我们可以看到有①、②、④、⑥一般是可变的,因此我们可以这些信息进行请求到
处理器的功能处理方法的映射,因此请求的映射分为如下几种:

URL路径映射:使用URL映射请求到处理器的功能处理方法;

请求方法映射限定:如限定功能处理方法只处理GET请求;

请求参数映射限定:如限定只处理包含“abc”请求参数的请求;

请求头映射限定:如限定只处理“Accept=application/json”的请求。

 

接下来看看具体如何映射吧。

 


私塾在线学习网
原创内容(http://sishuok.com

原创内容,转载请注明私塾在线【http://sishuok.com/forum/blogPost/list/0/6117.html

250
4
分享到:
评论
29 楼 杨俊德 2012-12-14  
有个问题请教,如果找不到视图文件,会抛  servletException ,这个异常是在return ModelandView 之后,我要捕获这个异常,提示其他的,有什么好解决方法吗?我现在是用拦截器afterCompletion 中处理的,不知道有别的更好的方法吗?
28 楼 杨俊德 2012-12-14  
感谢楼主的分享,目前刚开始使用springMVC 看了文章后受益很多!  
27 楼 jinnianshilongnian 2012-11-20  
9344187 写道
很优秀的文章。
楼主能不能详细讲一讲“RESTful架构风格”,这个架构在哪些地方可以应用呢?

这个估计得明年了  你可以看看一本叫《rest实战》
26 楼 9344187 2012-11-20  
很优秀的文章。
楼主能不能详细讲一讲“RESTful架构风格”,这个架构在哪些地方可以应用呢?
25 楼 337240552 2012-10-30  
踩的人有两种 源于中国人的劣根性 自己写不出来 看到别人写了 心理不爽 所以踩 第二种归于第一种 鼓励博主继续啊
24 楼 accphc 2012-10-17  
[{"conditionName":"brands","conditionTitle":"如家","conditionVal":null,"single":false},{"conditionName":"hotelStars","conditionTitle":null,"conditionVal":null,"single":false}]

public void test(@RequestBody ArrayList<ConditionVo> conList){}

-->List<ConditionVo>

如何转化

public class ConditionVo {
/** 条件名(类型) */
private String conditionName;
/** 条件标题 */
private String conditionTitle;
/** 条件值 */
private String conditionVal;
/** 是否单选 */
private boolean single;
       
        ......
23 楼 jinnianshilongnian 2012-09-29  
Inmethetiger 写道
每一篇都很详细!  必须定!

谢谢
22 楼 Inmethetiger 2012-09-29  
每一篇都很详细!  必须定!
21 楼 jinnianshilongnian 2012-09-24  
xiaoxichina 写道
我靠,还有人踩?谁在大象面前鼻子里插葱?
tao哥,我ding你!

谢谢
20 楼 xiaoxichina 2012-09-24  
我靠,还有人踩?谁在大象面前鼻子里插葱?
tao哥,我ding你!
19 楼 彩虹神 2012-09-23  
jinnianshilongnian 写道
彩虹神 写道
//Controller  
     public class AppController extends MultiActionController {
....
        public ModelAndView update(HttpServletRequest request, HttpServletResponse response, App app) {
log.debug("update appId" + app.getAppId());
if ("GET".equals(request.getMethod())) {
return new ModelAndView("admin/app/update").addObject("app", appService.get(app.getAppId()));
}
        appService.update(app);
        return new ModelAndView("redirect:/admin/app/index");
}
....

@Override
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(Date.class, new DateEditor());
}
}


对啊  你用chrome监控下数据

感谢tao哥,找到问题所在了,是自己粗心了,toupdate的时候appId从url带过去了,然后Update的时候表单中一个appId,url中一个appId. 多谢!
18 楼 jinnianshilongnian 2012-09-23  
彩虹神 写道
//Controller  
     public class AppController extends MultiActionController {
....
        public ModelAndView update(HttpServletRequest request, HttpServletResponse response, App app) {
log.debug("update appId" + app.getAppId());
if ("GET".equals(request.getMethod())) {
return new ModelAndView("admin/app/update").addObject("app", appService.get(app.getAppId()));
}
        appService.update(app);
        return new ModelAndView("redirect:/admin/app/index");
}
....

@Override
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(Date.class, new DateEditor());
}
}


对啊  你用chrome监控下数据
17 楼 彩虹神 2012-09-22  
//Controller  
     public class AppController extends MultiActionController {
....
        public ModelAndView update(HttpServletRequest request, HttpServletResponse response, App app) {
log.debug("update appId" + app.getAppId());
if ("GET".equals(request.getMethod())) {
return new ModelAndView("admin/app/update").addObject("app", appService.get(app.getAppId()));
}
        appService.update(app);
        return new ModelAndView("redirect:/admin/app/index");
}
....

@Override
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(Date.class, new DateEditor());
}
}
16 楼 彩虹神 2012-09-22  
<form:form method="POST" commandName="app">
    <table class="table_login" align="center" >
       <tbody>
          <tr class='row1'>
         <td align="center">appId</td>
         <td><form:input path="appId" size="60" style="width:320px;"/></td>
      </tr>
          ...省略其他字段
          <center>   
        <input type="submit" value="add" />
          </center>
</form:form>
15 楼 彩虹神 2012-09-22  
Errors binding onto object 'command'; nested exception is org.springframework.validation.BindException:
    org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'command' on field 'appId':
    rejected value [500,300]; codes [typeMismatch.command.appId,typeMismatch.appId,typeMismatch.int,typeMismatch];
    arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [command.appId,appId];
    arguments []; default message [appId]]; default message [Failed to convert property value of type 'java.lang.String[]' to
    required type 'int' for property 'appId'; nested exception is java.lang.NumberFormatException: For input string: "500,300"]    怎么会提交一个数组呢?不是应该只提交更新之后的那个300么...
14 楼 彩虹神 2012-09-22  
tao哥,问个遇到的问题,按照你的xml系列和annotation系列的博文写了两个CRUD的小例子,遇到了个问题,在按照xml的方式中的update模块在更新时,主键那个字段始终无法更新成功,比如toupdate的时候id为500,在update页面把他修改成300,那么提交的时候就会出现这个异常:
13 楼 jinnianshilongnian 2012-09-22  
gaiqiliang 写道
   很好的文章 期待后续的

12 楼 gaiqiliang 2012-09-22  
   很好的文章 期待后续的
11 楼 jinnianshilongnian 2012-09-21  
archy123 写道
jinnianshilongnian 写道
archy123 写道

这两种方式有什么不同呢?


类似的,只是第二种仅仅返回一个逻辑视图名字  后续会详解

期待后续文章,加油!!

谢谢 支持 
10 楼 archy123 2012-09-21  
jinnianshilongnian 写道
archy123 写道

这两种方式有什么不同呢?


类似的,只是第二种仅仅返回一个逻辑视图名字  后续会详解

期待后续文章,加油!!

相关推荐

    SpringMVC教程

    第六章 注解式控制器详解1(注解式控制器运行流程及处理器定义).pdf 第六章 注解式控制器详解2(SpringMVC3强大的请求映射规则详解).pdf 第六章 注解式控制器详解3(生产者、消费者请求限定).pdf 第六章 注解式控制器...

    SpringMvc开涛.rar

    PDF,源代码 开涛学SpringMVC 第一章源代码下载 第二章 Spring MVC入门 源代码下载 ...第五章 处理器拦截器详解——跟着开涛学SpringMVC 第六章 注解式控制器详解 第七章 注解式控制器的数据验证、类型转换及格式化

    springmvc常用注解标签详解

    @Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是 SpringMVC 的一个控制器类,因为这个时候 Spring...

    SpringMVC注解驱动的控制器详解

    SpringMVC注解驱动的控制器详解,具体效果与过程看博文 http://blog.csdn.net/evankaka/article/details/45562951

    源代码下载 第六章 注解式控制器详解

    标题中的“源代码下载 第六章 注解式控制器详解”表明了我们即将探讨的是关于Spring MVC框架中的注解式控制器的深入理解,并且提供了一套相关的源代码供学习和参考。这一章节通常会涵盖如何使用注解来实现Web应用...

    跟开涛学SpringMVC(5)处理器拦截器详解Java开

    本教程“跟开涛学SpringMVC(5)处理器拦截器详解”深入解析了这个核心概念,帮助Java开发者提升其应用的灵活性和可维护性。 处理器拦截器在Spring MVC中的主要职责包括: 1. **预处理**:在请求到达目标控制器...

    跟我学SpringMVC 教程

    第六章注解式控制器详解深入探讨了SpringMVC提供的注解式控制器。注解式控制器通过使用各种注解(如@Controller、@RequestMapping等)使得控制器的实现更为简洁和直观。本章不仅解析了注解式控制器的运行流程,还...

    SpringMvc教程 跟着我学SpringMVC

    注解式控制器使用注解来简化控制器的配置,这使得控制器的代码更加简洁。我们会学习使用@Controller注解来定义控制器,使用@RequestMapping来映射请求到处理器方法,以及如何处理请求参数和返回响应。 SpringMVC的...

    SpringMvc注解详解

    【SpringMvc注解详解】 SpringMvc 是 Spring 框架的一部分,主要负责处理 Web 请求。在 SpringMVC 中,注解扮演着至关重要的角色,它们简化了代码并减少了配置。以下是一些常用的 SpringMVC 注解及其详细解释: 1....

    SpringMVC注解开发的详解.doc

    SpringMVC注解开发是Java Web开发中一种高效的方式,它极大地简化了控制器的定义和请求处理。在SpringMVC框架中,`@Controller`注解用于标识一个类作为处理HTTP请求的控制器。这个注解使得类中的方法可以被SpringMVC...

    SpringMVC详解

    4. **注解式控制器** 从Spring 3.0开始,SpringMVC引入了注解式编程,使得开发者可以直接在方法上使用@RequestMapping等注解来定义请求映射,极大地简化了配置。此外,还可以使用@ModelAttribute、@RequestParam、@...

    SpringMVC+MyBatis+MySql注解示例

    它的核心功能包括模型-视图-控制器(MVC)模式的实现,使得开发者可以将业务逻辑、控制流程和视图分离,提高代码的可读性和可维护性。SpringMVC通过注解可以极大地简化配置,如`@Controller`、`@RequestMapping`等,...

    SpringMVC 常用注解类视频详解

    1. `@Controller`:这是定义一个类作为Spring MVC控制器的基本注解。当Spring容器扫描到这个注解时,它会将此类实例化,并处理其方法以响应HTTP请求。 2. `@RequestMapping`:用于映射HTTP请求到控制器方法。它可以...

    springMVC详解以及注解说明

    ### SpringMVC详解及注解说明 #### 一、引言 随着软件开发技术的不断发展,基于注解(Annotation)的配置方式越来越受到开发者们的青睐。Spring框架自2.5版本开始,便提供了完全基于注解配置Bean的能力,极大地简化...

    跟我学SpringMVC

    - **注解式控制器**:重点介绍了以下内容: - **运行流程**:控制器运行的基本流程。 - **处理器定义**:如何定义处理器。 - **请求映射**:包括URL路径映射、请求方法映射限定、强大的请求映射规则。 - **数据...

    跟开涛学SpringMVC(4.6)Controller接

    在本课程"跟开涛学SpringMVC(4.6)Controller接...在学习过程中,结合"跟开涛学SpringMVC(4.6)Controller接口控制器详解(6)Java开发Java经验技巧共10页.pdf"这份资料,你将能深入理解并掌握SpringMVC的核心概念。

    springmvc注解详解

    `@Controller` 注解是 Spring MVC 中的关键注解,用于标记一个类作为 MVC 应用中的控制器。控制器负责处理来自客户端的请求,并与业务逻辑层交互,最终将数据传递给视图层进行展示。 ### 2. `@RequestMapping` `@...

    SpringMVC九大常用注解

    ### SpringMVC九大常用注解详解 #### 一、@Controller **定义**: `@Controller` 注解是用来标记一个类作为控制器(Controller)组件,在Spring MVC框架中扮演着请求处理者的角色。 **作用**: 通过这个注解,可以将...

Global site tag (gtag.js) - Google Analytics