Spring MVC 与 RESTful 的集成

一、概念

1、什么是 RESTful ?

RESTful 是当前比较流行的一种互联网软件架构模型,通过统一的规范完成不同终端的数据访问和交互,REST 全称是 Representational State Transfer(资源表现层状态转换)。
RESTful 的优点:结构清晰、标准统一、扩展性好。

  • Resources
    资源指的是网络中的某个具体文件,类型不限,可以是文本、图片、视频、音频、数据流等,是网络中真实存在的一个实体。如何获取它?可以通过统一资源标识符 URI 找到这个实体,每个资源都有一个特定的 URI,通过 URI 就可以找到一个具体的资源。

  • Representation
    资源表现层,资源的具体表现形式,例如一段文字,可以使用 TXT、HTML、XML、JSON 等不同的形式来描述它。

  • State Transfer
    状态转化是指客户端和服务端之间的数据交互,因为 HTTP 请求不能传输数据的状态,所有的状态都保存在服务端,如果客户端希望访问服务端的数据,就需要使其发生状态改变,同时这种状态转化是建立在表现层的,完成转换就表示资源的表现形式发生了改变。

2、RESTful 的特点

RESTful 的概念比较抽象,特点有两个:
1、URL 传参更加简洁

  • 传统形式的 URL:http://localhost:8080/;findById?id=1
  • RESTful URL:http://localhost:8080/findById/1

2、完成不同终端之间的资源共享,RESTful 提供了一套规范,不同终端之间只需要遵守该规范,就可以实现数据交互。

3、RESTful 的表现形式

RESTful 具体来讲就是四种表现形式,HTTP 协议中四种请求类型(GET、POST、PUT、DELETE)分别表示四种常规操作;CRUD

  • GET 用来获取资源
  • POST 用来创建资源
  • PUT 用来修改资源
  • DELETE 用来删除资源

两个终端要完成数据交互,基于 RESTful 的方式,增删改查操作分别需要使用不同的 HTTP 请求类型来访问。

传统的 Web 开发中,form支持 GET 和 POST,不支持 DELETE 和 PUT。可通过添加 HiddenHttpMethodFilter 过滤器,将 POST 请求转为 PUT 或 DELETE。

二、HiddenHttpMethodFilter 的实现原理

HiddenHttpMethodFilter 检测请求参数中是否包含 _method 参数,如果包含则取出它的值,并且判断请求类型之后完成请求类型的转换,然后继续传递。
在这里插入图片描述

实现步骤

1、在 form 表单中添加隐藏域标签,name 属性的值为_method,value 属性的值 DELETE/PUT。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/rest/update" method="post">
    <input hidden name="_method" value="PUT">
    <input type="submit" value="PUT请求提交">
</form>
<form action="/rest/delete" method="post">
    <input hidden name="_method" value="DELETE">
    <input type="submit" value="DELETE请求提交">
</form>
</body>
</html>
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/rest")
public class RestfulController {

    @PutMapping("/update")
    @ResponseBody
    public String update(){
        return "已接收到 PUT 请求";
    }@DeleteMapping("/delete")
    @ResponseBody
    public String delete(){
        return "已接收到 DELETE 请求";
    }
}

三、案例

1、需求分析

  • 添加课程,成功则返回全部课程信息。
  • 查询课程,通过 id 查询对应课程信息。
  • 修改课程,成功则返回修改之后的全部课程信息。
  • 删除课程,成功则返回删除之后的全部课程信息。

2、代码实现

(1)Course 实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Course {
    private Integer id;
    private String name;
    private Double price;
}

(2)CourseRepository

import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Repository
public class CourseRepository {

    private Map<Integer, Course> courseMap;

    public CourseRepository(){
        courseMap = new HashMap<>();
        courseMap.put(1, new Course(1, "Java 基础", Double.parseDouble("500")));
        courseMap.put(2, new Course(2, "Java 高级", Double.parseDouble("600")));
        courseMap.put(3, new Course(3, "企业级框架", Double.parseDouble("700")));
    }

    public Collection<Course> findAll(){
        return courseMap.values();  // values() 方法返回 HashMap 中所有 value 值所组成的 collection view(集合视图)。
    }

    public Course findById(Integer id){
        return courseMap.get(id);
    }

    public void saveOrUpdate(Course course){
        courseMap.put(course.getId(), course);
    }

    public void deleteById(Integer id){
        courseMap.remove(id);
    }
}

(3)Controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Collection;

@Controller
@RequestMapping("/course")
public class CourseController {

    @Autowired
    private CourseRepository courseRepository;


    @GetMapping("/findAll")
    public ModelAndView findAll(){
        Collection<Course> all = courseRepository.findAll();
        ModelAndView mav = new ModelAndView();
        mav.addObject("list", all);
        mav.setViewName("index");
        return mav;
    }

    @GetMapping("/findById/{id}")
    public ModelAndView findById(@PathVariable("id") Integer id){
        Course course = courseRepository.findById(id);
        ModelAndView mav = new ModelAndView();
        mav.addObject("course", course);
        mav.setViewName("course");
        return mav;
    }

    @PostMapping("/save")
    public String save(Course course){
        courseRepository.saveOrUpdate(course);
        return "redirect:/course/findAll";
    }

    @PutMapping("/update")
    public String update(Course course){
        courseRepository.saveOrUpdate(course);
        return "redirect:/course/findAll";
    }

    @DeleteMapping("/deleteById/{id}")
    public String deleteById(@PathVariable("id") Integer id){
        courseRepository.deleteById(id);
        return "redirect:/course/findAll";
    }
}

(4)jsp
index.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<html>
<body>
<table>
    <tr>
        <th>编号</th>
        <th>名称</th>
        <th>价格</th>
        <th>操作</th>
    </tr>
    <c:forEach items="${list}" var="course">
        <tr>
            <td>${course.id}</td>
            <td>${course.name}</td>
            <td>${course.price}</td>
            <td width="40px">
                <form method="post" action="/course/deleteById/${course.id}">
                    <input hidden name="_method" value="DELETE">
                    <input type="submit" value="删除">
                </form>
                <a href="/course/findById/${course.id}">修改</a>
            </td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

course.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<html>
<body>
<form method="post" action="/course/update">
    <input hidden name="_method" value="PUT">
<table>
    <tr>
        <td>编号:</td>
        <td><input name="id" readonly value="${course.id}"></td>
    </tr>
    <tr>
        <td>课程名称:</td>
        <td><input name="name" value="${course.name}"></td>
    </tr>
    <tr>
        <td>课程价格:</td>
        <td><input name="price" value="${course.price}"></td>
    </tr>
    <tr>
        <td>
            <input type="submit" value="提交">
        </td>
    </tr>
</table>
</form>
</body>
</html>

save.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/course/save" method="post">
    <table>
        <tr>
            <td>课程编号</td>
            <td>
                <input type="text" name="id">
            </td>
        </tr>
        <tr>
            <td>课程名称</td>
            <td>
                <input type="text" name="name">
            </td>
        </tr>
        <tr>
            <td>课程价格</td>
            <td>
                <input type="text" name="price">
            </td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="提交">
            </td>
            <td>
                <input type="reset" value="重置">
            </td>
        </tr>

    </table>

</form>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值