Restful风格知识点

@RestController注解

在类上添加@RestController可以默认类中的所有方法都带有@ResponseBody注解,可以省去一个个添加的麻烦。

@RestController
@RequestMapping("/restful")
//@CrossOrigin(origins = {"http://localhost:8080","http://www.imooc.com"})
//@CrossOrigin(origins = "*",maxAge = 3600)
public class RestfulController {
    @GetMapping("/request")
    //@ResponseBody
    public String doGetRequest(){
        return "{\"message\":\"返回查询结果\"}";
    }

    // POST /article/1
    // POST /restful/request/100
    @PostMapping("/request/{rid}")
    //@ResponseBody
    public String doPostRequest(@PathVariable("rid") Integer requestId, Person person){
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"数据新建成功\",\"id\":" + requestId + "}";
    }

    @PutMapping("/request")
    //@ResponseBody
    public String doPutRequest(Person person){
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"数据更新成功\"}";
    }

    @DeleteMapping("/request")
    //@ResponseBody
    public String doDeleteRequest(){
        return "{\"message\":\"数据删除成功\"}";
    }

    @GetMapping("/person")
    public Person findByPersonId(Integer id){
        Person p = new Person();
        if(id==1){
            p.setName("lily");
            p.setAge(23);
        }else if(id==2){
            p.setName("smith");
            p.setAge(22);
        }
        return p;
    }

    @GetMapping("/persons")
    public List<Person> findPersons(){
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("lily");
        p1.setAge(23);
        p1.setBirthday(new Date());

        Person p2 = new Person();
        p2.setName("smith");
        p2.setAge(22);
        p2.setBirthday(new Date());
        list.add(p1);
        list.add(p2);
        return list;
    }

}

路径变量

@PathVariable注解可以让控制方法接收前端传来的请求中的路径变量。例如下面这个例子,无论前端传来1还是100这个id都能被控制方法中的requestId这个变量通过@PathVariable注解来接收从而在控制方法中使用。

	// POST /restful/request/1
    // POST /restful/request/100
    @PostMapping("/request/{rid}")
    //@ResponseBody
    public String doPostRequest(@PathVariable("rid") Integer requestId, Person person){
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"数据新建成功\",\"id\":" + requestId + "}";
    }

简单请求与非简单请求

简单请求是指标准结构的HTTP请求对应GET/POST请求
非简单请求是复杂要求的HTTP请求指PUT/DELETE、扩展标准请求
两者最大区别是非简单请求发送前需要发送预检请求
SpringMVC默认只支持get、post请求,要处理非简单请求需要在web.xml中配置过滤器。

<filter>
        <filter-name>formContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>formContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

JSON序列化

首先在项目中添加依赖。

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>

然后在控制方法中返回实体对象即可,如果有多个实体需要返回,则可以使用List。

@GetMapping("/person")
    public Person findByPersonId(Integer id){
        Person p = new Person();
        if(id==1){
            p.setName("lily");
            p.setAge(23);
        }else if(id==2){
            p.setName("smith");
            p.setAge(22);
        }
        return p;
    }

    @GetMapping("/persons")
    public List<Person> findPersons(){
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("lily");
        p1.setAge(23);
        p1.setBirthday(new Date());

        Person p2 = new Person();
        p2.setName("smith");
        p2.setAge(22);
        p2.setBirthday(new Date());
        list.add(p1);
        list.add(p2);
        return list;
    }

如果实体类中包含了日期变量,则需要使用特殊的注解进行格式转变。

public class Person {
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8")
    private Date birthday;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

浏览器的跨域访问

同源策略:
同源策略阻止从一个域加载的脚本去获取另一个域上的资源
只要协议、域名、端口有任何一个不同,都被当作是不同的域
浏览器Console看到Access-Control-Allow-Origin就代表跨域了
例子:
Restful风格笔记-LMLPHP
允许跨域的标签:

<img>- 显示远程图片
<script>- 加载远程JS
<link> - 加载远程CSS

请求头中的Sec-Fetch-Mode:cors说明这是一个跨域访问的请求。
响应头中的Vary: Origin,Access-Control-Request-Method, Access-Control-Request-Headers通知浏览器这是一个允许跨域访问的url。

在控制类之前添加注解解决跨域访问问题。
使用@CrossOrigin注解添加允许访问的url。
maxAge参数设置缓存预检请求结果的时间。

@CrossOrigin(origins = {"http://localhost:8080","http://www.imooc.com"},maxAge = 3600)

在配置文件中添加配置解决跨域访问问题。
在applicationContext.xml中添加mvc:cors设置允许访问的url。

<mvc:cors>
        <mvc:mapping path="/restful/**"
                     allowed-origins="http://localhost:8080,http://www.imooc.com"
                     max-age="3600"/>
    </mvc:cors>

path代表允许访问哪个路径下的资源。
注:注解和配置一起使用时,以注解配置为准。

06-22 14:49