Spring MVC 03:RESTful与常用注解
什么是REST
REST全称是Representational State Transfer,中文意思是表述(通常译为表现层状态转移),一种Web应用接口的设计风格。
要解决什么样的问题
针对Http协议和Web应用环境,实现简单的API
特点
1.用URI来代替资源
schema://host[:port]/path[?query-string][#anchor]
2.用Method表示针对资源的动作
- Get:查询资源
- Post:新建资源
- PUT:更新资源
- DELETE:删除资源
RESTful架构应该遵循统一接口原则,统一接口包含了一组受限的预定义的操作,不论什么样的资源,都是通过使用相同的接口进行资源的访问。接口应该使用标准的HTTP方法如GET,PUT和POST,并遵循这些方法的语义。
简单来说就是,REST给你规定了URI的格式,并且给所有请求方法规定了一些具体的规范。查询资源就用Get方法,新建资源就用Post方法。
3.监控HTTP的返回值,作为调用结果
200:OK
400:Bad Request
4.无状态
状态信息存储在客户端,服务器端无状态,即在没有数据变化的情况下,相同的请求会获得相同的返回数据。和函数式编程类似:一个函数的返回只跟它的输入有关,这个函数没有它的内部状态。
注意:无状态的之所以被强调,就是因为它有两大好处:1.方便分布式/负载均衡。2.方便扩展,特别是在微服务上
校正请求参数名@RequestParam(掌握)
所谓校正请求参数名,是指若请求 URL 所携带的参数名称与处理方法中指定的参数名不相同时,则需在处理方法参数前,添加一个注解**@RequestParam(“请求参数名”)**,指定请求 URL 所携带参数的名称。该注解是对处理器方法参数进行修饰的。value 属性指定请求参数的名称。

项目:receiveParameters-params。在 receiveParameters-property 基础上修改。
@PathVariable
带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义。
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable(“xxx”) 绑定到操作方法的入参中。例如:
@RequestMapping("/user/{id}")
public String getUser(@PathVariable(name = "sid")String id,@PathVariable(name = "a")String a) {
System.out.println("getUser()");
System.out.println("id = " + id);
System.out.println("a = " + a);
return "HelloWorld";
}
关于如何发送PUT和DELETE请求
如果是一个html网页的form,它的合法选项只有“GET|POST”,除非用了AJAX库或者框架。
PUT请求
@RequestMapping(value = "/user/{sid}/{a}",method = RequestMethod.PUT)
public String getUser(@PathVariable(name = "sid")String id,@PathVariable(name = "a")String a) {
System.out.println("getUser()");
System.out.println("id = " + id);
System.out.println("a = " + a);
return "HelloWorld";
}
但是我们在POSTMAN发送了请求之后,会发现报错:
JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS
也就是说JSP天然就是和RESTful中的一些方法冲突,所以在RESTful中就不要用JSP作为返回的view,应该返回JSON。
所以当你要用RESTful返回数据时,应该在Controller类中添加一个注解@RestController,而不是原来的@Controller
如果是HTML页面的form发送请求,form无法发送PUT和DELETE,但是服务器端就是按照PUT实现的,需要Filter将POST改成PUT
配置Filter
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<servlet-name>dispatcherServlet</servlet-name>
</filter-mapping>
POSTMAN模拟只能发送POST请求的情况,需要在请求体中添加_method,会将POST转成PUT

利用@RequestHeader根据不同浏览器返回不同的View
// /param/test10
// User-Agent:获取请求头
@RequestMapping("/test10")
public String test10(@RequestHeader("User-Agent") String header) {
System.out.println("test10()");
System.out.println(header);
// 当请求头含有Chrome时
if (header.indexOf("Chrome") != -1){
System.out.println("Chrome");
return "HelloWorldForChrome";
}else if (header.indexOf("Firefox") != -1){
System.out.println("Firefox");
return "HelloWorldForFireFox";
}
return "HelloWorld";
}
利用@CookieValue获取Cookie
// /param/test11
@RequestMapping("/test11")
public String test11(@CookieValue("JSESSIONID") String cookie) {
System.out.println("test11()");
System.out.println(cookie);
return "HelloWorld";
}
@ModelAttribute设置请求参数的默认值
@ModelAttribute("p1")
public Pabc1 initPabc(){
System.out.println("inintPabc() is called");
Pabc1 pabc = new Pabc1();
pabc.setA("default");
pabc.setB("default");
pabc.setC("default");
return pabc;
}
@RequestMapping("/test5")
public String test5(@ModelAttribute("p1") Pabc1 pabc) {// 自动组装
System.out.println("test5()");
System.out.println(pabc);
return "HelloWorld";
}
利用@SessionAttributes在不同Servlet传递数据(跨request)
//SessionAttributes将p1同时也会放到sessionScope中去
@Controller
@RequestMapping("/param")
@SessionAttributes("p1")
public class Parameters {
@RequestMapping("/test12")
public String test12(Model model) {
System.out.println("test12()");
// 添加Session数据缺省会同步到request
model.addAttribute("p1","myValue");
return "HelloWorld";
}
@RequestMapping("/test13")
public String test13(ModelMap map) {
System.out.println("test13()");
// 从Session拿数据
System.out.println((String)map.get("p1"));
return "HelloWorld";
}
@RequestMapping("/test14")
public String test14(SessionStatus status) {
System.out.println("test14()");
// 清理掉Session数据
status.setComplete();
return "HelloWorld";
}
}