注解式控制器详解

一、注解式控制器简介

1.Spring2.5引入注解式控制器支持,通过@Controller和@RequsetMapping注解定义我们的处理器类。并且提供了一组强大的注解:

需要通过处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter来开启支持@Controller和@RequestMapping注解的解释器。

  • @Controller:用于标识是处理器类
  • @RequestMapping:请求到处理器功能方法的映射规则
  • @RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定
  • @ModelAttribute:请求参数到命令对象的绑定
  • @SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中
  • @InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对象类型

2.Spring3.0引入RESTful架构风格支持(通过@PathVariable注解和一些其他特性支持),且又引入了更多的注释支持:

  • @CookieValue:cookie数据到处理器功能处理方法的方法参数上的绑定
  • @RequestHeader:请求头(header)数据到处理器功能处理方法的方法参数上的绑定
  • @RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换)
  • @ResponseBody:处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换)
  • @ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和原因
  • @ExceptionHandler:注解式声明异常处理器
  • @PathVariable:请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI

3.Spring3.1使用新的HandlerMapping和HandlerAdapter来支持@Controller和@RequestMapping注解处理器。

新的@Controller和@RequestMapping注解支持类:处理器映射RequestMappingHandlerMapping和处理器适配器RequestMappingHandlerAdapter组合来代替之前的类。

  • URI路径映射:使用URI映射请求到处理器的功能处理方法
  • 请求方法映射限定:如限定功能处理方法只处理GET请求
  • 请求参数映射限定:如限定只处理包含“adc”请求参数的请求
  • 请求头映射限定:如限定只处理“Accept=application/json”的请求

二、具体的使用

1.控制器实现

package cn.javass.chapter6.web.contorller;

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

可以通过在一个POJO类上放置@Controller或@RequestMapping,即可把一个POJO类变身为处理器。@RequestMapping(value="/hello")表示请求URI(/hello)到处理器的功能处理方法的映射。返回模型数据和逻辑视图名。

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

(1)HandlerMapping和HandlerAdapter的配置

<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

<!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

(2)视图解析器的配置

<!-- viewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>

(3)处理器的配置

<!-- 处理器 -->
<bean class="cn.javass.chapter6.web.controller.HelloWorldCounter"/>

只需要将处理器实现类注册到Spring配置文件即可,Spring的DefaultAnnotationHandlerMapping或RequestMappingHandlerMapping能根据注解@Controller或@RequestMapping自动发现

(4)视图页面(/WEB/INF/jsp/hello.jsp)

<%@ 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处理器传过来的模型数据。

(5)启动服务器测试

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

三、运行流程

四、处理器定义

1、@Controller

@Controller
public class HelloWorldController{
......
}

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

2.@RequestMapping

@RequestMapping
public class HelloWorldController{
...
}

这种方式也是可以的,但如果在类上使用@RequestMapping注解一般是用于窄化功能处理方法的映射的。

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是可以的。

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

五、请求映射

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

http请求信息包含六部分:

  • ①请求方法:如GET或POST,表示提交的方式
  • ②URL:请求的地址信息
  • ③协议及版本
  • ④请求头信息(包括cookie信息)
  • ⑤回车换行(CRLF)
  • ⑥请求内容区(即请求的内容或数据),如表单提交时的参数数据,URL请求参数(?abc=123?后边的)等等。

那此时我们可以看到有①、②、④、⑥一般是可变的,因此我们可以映射这些请求到处理器的功能处理方法,因此请求的映射分为如下几种:

  • URL路径映射:使用URL映射请求到处理器的功能处理方法
  • 请求方法映射限定:如限定功能处理方法只处理GET请求
  • 请求参数映射限定:如限定只处理包含“adc”请求参数的请求
  • 请求头映射限定:如限定只处理“Accept=application/json”的请求

1.URL路径映射 

(1)普通的URL路径映射

@RequestMapping(value={"/test1","/user/create"}),多个URL路径可以映射到同一个处理器的功能处理方法。

(2)URL模板模式映射

@RequestMapping(value="/users/{userId}"),{xxx}占位符,请求的URL可以是“/users/12345”或“/users/abcd”。

通过@PathVariable可以提取URL模板模式中的{xxx}中的xxx变量。

@RequestMapping(value=“/users/{userId}/topics/{topics}”):这样也是可以的,请求的URL可以是“/users/123/topics/123”.

(3)Ant分格的URL路径映射

@RequestMapping(value="/users/**"):可以匹配“users/abc/adc”,但“/users/123”将会被URL模板模式映射中的“/users/{userId}”模式优先映射到。

@RequestMapping(value="/product?"):可匹配“/product1”或“/producta”,但不匹配“/product”或“/productaa”;

@RequestMapping(value="/product*"):可匹配“/productabc”或“/product”,但不匹配“/productabc/abc”;

@RequestMapping(value="/product/*"):可匹配“/product/abc”,但不匹配“/productabc”;

@RequestMapping(value="/products/**/{productId}"):可匹配“/products/abc/abc/123”或“/products/123”,也就是Ant风格和URI模板变量风格可混用;

2.请求方法映射限定

一般我们熟悉的表单一般分为两步:第一步展示,第二步提交。

(1)请求方法映射限定

我们熟知的,展示表单一般为GET请求方法,提交表单一般为POST请求方法。但第一部分讲的URL路径映射方式对任意请求方法是全盘接受的,因此我们需要某种方式来告知相应的功能处理方法只处理如GET请求方法的请求或POST请求方法的请求。

接下来我们使用@RequestMapping来实现SimpleFormController的功能吧。

package cn.javass.chapter6.web.controller.method;
@Controller
@RequestMapping("/customers/**")   //①处理器的通用映射前缀
public class RequestMethodController{
    @RequestMapping(value="/create",method=RequestMethod.GET)   //②类级别的@RequestMapping窄化
    public String showForm(){
        System.out.println("===============GET");
        return "customer/create";
    }
    @RequestMapping(value="/create",method=RequestMethod.POST)   //③类级别的@RequestMapping窄化
    public String submit(){
        System.out.println("================POST");
        return "redirect:/success";
    }
}

①处理器的通用映射前缀(父路径):表示该处理器只处理匹配"/customers/**"的请求。

②对类级别的@RequestMapping进行窄化,表示showForm可处理匹配"customer/**/create"且请求方法为“GET”的请求。

③对类级别的@RequestMapping进行窄化,表示submit可处理匹配"/customer/**/create"且请求方法为“POST”的请求。

(2)组合使用时“或”的关系

@RequestMapping(value="/methodOr",method={RequestMethod.POST ,RequestMethod.GET):即请求方法可以是GET或POST。

3.请求参数数据映射限定

(1)请求数据中有指定参数名

package cn.javass.chapter6.web.controller.parameter;
@Controller
@RequestMapping("/parameter1")        //①处理器的通用映射前缀
public class RequestParameterController1{
    //②进行类级别的@RequestMapping窄化
    @RequestMapping(params="create",method=RequestMethod.GET)
    public String shwoForm(){
        System.out.println("=============showForm"):
        return "parameter/create";
    }

    //③进行类级别的@RequestMapping窄化
    @RequestMapping(params="create",method=RequestMethod.POST)
    public String submit(){
        System.out.println("=============submit");
        return "redirect:/success";
    }
}

②@RequestMapping(params="create",method=RequestMethod.GET):表示请求中有“create”的参数名且请求方法为“GET”即可匹配,如可匹配的请求URL"http://xxx/parameter1?create"。

③@RequestMapping(params="create",method=RequestMethod.POST):表示请求中有“create”的参数名且请求方法为"POST"即可匹配。

此处的create请求参数名表示你请求的动作,即你想要的功能的一个标识。常见的CRUD我们可以使用如下请求参数来表达:

create请求参数名  GET请求方法) 新增页面展示、(create请求参数名  POST请求方法)新增提交;

update请求参数名  GET请求方法) 新增页面展示、(update请求参数名  POST请求方法)新增提交;

delete请求参数名  GET请求方法) 新增页面展示、(delete请求参数名  POST请求方法)新增提交;

query请求参数名  GET请求方法) 新增页面展示、(query请求参数名  POST请求方法) 新增提交;

list请求参数名  GET请求方法) 列表页面展示;

view请求参数名  GET请求方法) 查看单条记录页面展示。

(2)请求数据中没有指定参数名

//请求参数中不包含create参数名
@RequestMapping(params="!create",method=RequestMethod.GET);  //进行类级别的@RequestMapping窄化

@RequestMapping(params="!create",method=RequestMethod.GET):表示请求中没有“create”参数名且请求方法为“GET”即可匹配。如可匹配的请求URL“http://xxx/parameter1?abc”。

(3)请求数据中指定参数名=值

package cn.javass.chapter6.web.controller.parameter;  
//省略import  
@Controller  
@RequestMapping("/parameter2")                      //①处理器的通用映射前缀  
public class RequestParameterController2 {  
    //②进行类级别的@RequestMapping窄化  
    @RequestMapping(params="submitFlag=create", method=RequestMethod.GET)    
    public String showForm() {  
        System.out.println("===============showForm");  
        return "parameter/create";          
    }  
    //③进行类级别的@RequestMapping窄化  
    @RequestMapping(params="submitFlag=create", method=RequestMethod.POST)     
    public String submit() {  
        System.out.println("===============submit");  
        return "redirect:/success";          
    }  
}  

 @RequestMapping(params="submitFlag=create", method=RequestMethod.GET):表示请求中有“submitFlag=create”请求参数且请求方法为“GET”即可匹配,如请求URL为http://×××/parameter2?submitFlag=create

@RequestMapping(params="submitFlag=create", method=RequestMethod.POST):表示请求中有“submitFlag=create”请求参数且请求方法为“POST”即可匹配。

此处的submitFlag=create请求参数表示你请求的动作,即你想要的功能的一个标识,常见的CRUD(删改查)我们可以使用如下请求参数名来表达:

submitFlag=create请求参数名  GET请求方法) 新增页面展示、(submitFlag=create请求参数名  POST请求方法) 新增提交;

submitFlag=update请求参数名  GET请求方法) 新增页面展示、(submitFlag=update请求参数名  POST请求方法) 新增提交;

submitFlag=delete请求参数名  GET请求方法) 新增页面展示、(submitFlag=delete请求参数名  POST请求方法) 新增提交;

submitFlag=query请求参数名  GET请求方法) 新增页面展示、(submitFlag=query请求参数名  POST请求方法) 新增提交;

submitFlag=list请求参数名  GET请求方法) 列表页面展示;

submitFlag=view请求参数名  GET请求方法) 查看单条记录页面展示。

(4)请求数据中指定参数名!=值

//请求参数submitFlag不等于create
@RequestMapping(params="submitFalg!=create",method=RequestMethod.GET)

 @RequestMapping(params="submitFlag!=create", method=RequestMethod.GET):表示请求中的参数“submitFlag!=create”且请求方法为“GET”即可匹配,如可匹配的请求URL“http://×××/parameter1?submitFlag=abc”。

(5)组合使用是“且”的关系

@RequestMapping(params={"test1", "test2=create"})  //②进行类级别的@RequestMapping窄化  

 @RequestMapping(params={"test1", "test2=create"}):表示请求中的有“test1”参数名 且 有“test2=create”参数即可匹配,如可匹配的请求URL“http://×××/parameter3?test1&test2=create。

4.请求头数据映射限定

(1)请求头数据中有指定参数名

@RequestMapping(value="/header/test1",headers="Accept"):表示请求的URL必须为“/header/test1”,且请求头中必须有Accept参数才能匹配。

@RequestMapping(value="/header/test1",headers="abc"):表示请求的URL必须为"/header/test1",且请求头中必须有abc参数才能匹配。

(2)请求头中没有指定参数名

@RequestMapping(value="/header/test2",headers="!abc"):表示请求的URL必须为"/header/test2",且请求头中必须没有abc参数才能匹配。

(3)请求头数据中指定参数名=值

@RequestMapping(value="/header/test3",headers="Context-Tyep=application/json"):表示请求的URL必须为"/header/test3"且请求头中必须有"Content-Type=application/json"参数即可匹配。

当你请求的URL为"/header/test3"但如果请求头中没有或不是"Content-Type=application/json"参数,将返回“HTTP Status 415”状态码。

(4)请求头数据中指定参数名!=值

@RequestMapping(value="/header/test7", headers = "Accept!=text/vnd.wap.wml"):表示请求的URL必须为“/header/test7” 且 请求头中必须有“Accept”参数但值不等于“text/vnd.wap.wml”即可匹配。

(5)组合使用是“且”的关系

@RequestMapping(value="/header/test8", headers = {"Accept!=text/vnd.wap.wml","abc=123"}):表示请求的URL必须为“/header/test8” 且 请求头中必须有“Accept”参数但值不等于“text/vnd.wap.wml”且 请求中必须有参数“abc=123”即可匹配。

转载自:https://jinnianshilongnian.iteye.com/blog/1752171

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值