Spring MVC 03:RESTful与常用注解


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 属性指定请求参数的名称。

image-20220712144223669

项目: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

1

利用@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";
    }
}

参考资料

RESTful 架构详解

基于@PathVariable注解的用法说明


文章作者: 银色回廊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 银色回廊 !
评论
  目录