超级通道 :Spring MVC代码实例系列-绪论
本章主要记录如何通过@RestController
和@PathVariable
构建RESTFul风格的Web服务。涉及到的知识点有:
- REST
:Representational State Transfer
表现层状态转化,一种软件架构风格、设计风格。
- @RestController
:一种控制器,@Controller
与@ResponseBody
的结合,此控制器内的方法返回的不是View,而是对象。
- @PathVariable
通过获取URL
上以模板{}
标记的参数。
- @ModelAttribute
设置Model
里的属性,本例中用来模拟数据库。
REST,全称为Representational State Transfer
,翻译为表现层状态转化
。以我的理解就是:
REST:通过URL名词定位资源,通过HTTP请求方式(GET/POST/PUT/PATCH/DELETE)描述操作。
示例:
序号 | URL | 请求方式 | 实际URL | 解释 |
---|---|---|---|---|
1 | localhost:8080/student/{id} | GET | [GET] localhost:8080/student/1 | 获得id=1的student信息 |
2 | localhost:8080/student/{id} | DELETE | [DELETE] localhost:8080/student/1 | 删除id=1的student信息 |
3 | localhost:8080/student/ | GET | [GET] localhost:8080/student/ | 获取所有的student信息 |
4 | localhost:8080/student/ | DELETE | [DELETE] localhost:8080/student/ | 删除所有的student信息 |
5 | localhost:8080/student/ | POST | [POST] localhost:8080/student/ | 添加一个新的student信息 |
6 | localhost:8080/student/ | PUT | [PUT] localhost:8080/student/ | 替换一个student信息 |
7 | localhost:8080/student/ | PATCH | [PATCH] localhost:8080/student/ | 修改一个student信息 |
说明:
1. PUT倾向于修改一个对象的全部信息,我理解为所有的属性不论是否为空,全部修改。
2. PATCH倾向于修改一个对象的部分属性,我理解为所有的属性值只修改不为空的字段。
3. REST是一种风格,一种规范,而不是协议。可以只用PUT,不用PATCH。
@RestController
@RestController
= @Controller
+ @ResponseBody
,表示此控制器的每一个方法返回域对象代替一个视图。
@Controller
+ @ResponseBody
的写法
@Controller
public class DemoController{
@RequestMapping
@ResponseBody
public User getUser(){}
}
@RestController
的写法
@RestController
public class DemoController{
@RequestMapping
public User getUser(){}
}
@PathVariable
@PathVariable
用于获取URL
上的模板参数
@RestController
public class DemoController{
@GetMapping("/student/{id}")
public User getUser(@PathVariable String id){}
}
src
\---main
\---java
| \---pers
| \---hanchao
| \---hespringmvc
| \---restful
| \---Question.java
| \---MyJsonResult.java
| \---QuestionController.java
\---webapp
\---restful
| \---question.jsp.jsp
\---WEB-INF
| \---spring-mvc-servlet.xml
| \---web.xml
\---index.jsp
package pers.hanchao.hespringmvc.restful;
/**
* 题目对象
* @author hanchao 2018/1/21 11:30
**/
public class Question {
/** 试题id */
private Integer id;
/** 题目 */
private String title;
/** 分数 */
private Integer score;
/** 答案 */
private String answer;
public Question(){}
public Question(Integer id, String title, Integer score, String answer) {
this.id = id;
this.title = title;
this.score = score;
this.answer = answer;
}
//toString
//setter and getter
}
package pers.hanchao.hespringmvc.restful;
import java.util.Arrays;
import java.util.List;
/**
* 用来封装返回值
* @author hanchao 2018/1/21 11:29
**/
public class MyJsonResult {
/** 状态码 */
private String code = "1";
/** 状态消息 */
private String message = "success!";
/** 返回消息 */
private Question[] questions;
public MyJsonResult(){
}
public MyJsonResult(Question[] data){
this.questions = data;
}
public void setCodeAndMessage(String code,String message){
this.code = code;
this.message = message;
}
//toString
//setter and getter
}
package pers.hanchao.hespringmvc.restful;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
/**
* Restful风格URL的简单实例
* @author hanchao 2018/1/21 11:30
**/
@RestController
@RequestMapping("restful")
public class QuestionController {
/**
* 定义一个Question的列表,用来模拟数据集
* @author hanchao 2018/1/20 23:15
**/
@ModelAttribute
public Question[] init(Model model){
Question[] questions = new Question[10];
String title = "题目";
int score = 90;
String answer = "答案";
for(int i = 0 ; i < 10 ; i ++){
questions[i] = new Question(i,title + i,score + i,answer + i);
}
model.addAttribute("questions",questions);
return questions;
}
/**
* [GET]获取一个题目
* @author hanchao 2018/1/20 22:08
**/
@GetMapping("/question/{id}")
public MyJsonResult getQuestion(@PathVariable Integer id, @ModelAttribute("questions") Question[] questions) {
MyJsonResult myJsonResult = new MyJsonResult();
//查找题目,找到则返回
for (Question question : questions){
if (id.equals(question.getId())){
myJsonResult.setQuestions(new Question[]{question});
break;
}
}
return myJsonResult;
}
/**
* [GET]获取全部的题目
* @author hanchao 2018/1/20 23:50
**/
@GetMapping("/question/")
public MyJsonResult getAll(@ModelAttribute("questions") Question[] questions) {
MyJsonResult myJsonResult = new MyJsonResult(questions);
return myJsonResult;
}
/**
* [POST]新增一个题目
* @author hanchao 2018/1/21 10:10
**/
@PostMapping("/question/")
public MyJsonResult postQuestion(@RequestBody Question question,@ModelAttribute("questions") Question[] questions) {
MyJsonResult myJsonResult = new MyJsonResult();
boolean isExist = false;
//查找题目,如果找到,则表明已经存在,不能再添加
for (int i = 0 ; i < questions.length; i ++){
Question qi = questions[i];
if (question.getId().equals(qi.getId())){
myJsonResult.setCodeAndMessage("0","改题目已经存在,不能再添加!");
isExist = true;
break;
}
}
//如果题目不存在,则新增题目
if (!isExist){
Question[] newQuestions = new Question[questions.length + 1];
newQuestions[0] = question;
System.arraycopy(questions,0,newQuestions,1,questions.length);
myJsonResult.setQuestions(newQuestions);
}
return myJsonResult;
}
/**
* [PUT]替换一个题目(全部修改)
* @author hanchao 2018/1/21 10:44
**/
@PutMapping("/question/")
public MyJsonResult putQuestion(@RequestBody Question question,@ModelAttribute("questions") Question[] questions) {
MyJsonResult myJsonResult = new MyJsonResult();
boolean isExist = false;
//查找题目,如果找到,直接替换全部属性
for (int i = 0 ; i < questions.length; i ++){
Question qi = questions[i];
if (question.getId().equals(qi.getId())){
questions[i] = question;
myJsonResult.setQuestions(questions);
break;
}
}
//如果找不到,则提示不存在此题目
if (!isExist){
myJsonResult.setCodeAndMessage("0","不存在此题目,无法替换!");
}
return myJsonResult;
}
/**
* [PATCH]修改一个题目,修改不为空的属性值
* @author hanchao 2018/1/21 11:15
**/
@PatchMapping("/question/")
public MyJsonResult patchQuestion(@RequestBody Question question,@ModelAttribute("questions") Question[] questions) {
MyJsonResult myJsonResult = new MyJsonResult();
boolean isExist = false;
//查找题目,如果找到,替换不为空的属性
for (int i = 0 ; i < questions.length; i ++){
Question qi = questions[i];
if (question.getId().equals(qi.getId())){
if (null != question.getTitle() && !"".equals(question.getTitle())){
questions[i].setTitle(question.getTitle());
}
if (null != question.getAnswer() && !"".equals(question.getAnswer())){
questions[i].setAnswer(question.getAnswer());
}
if (null != question.getScore() && !"".equals(question.getScore())){
questions[i].setScore(question.getScore());
}
myJsonResult.setQuestions(questions);
break;
}
}
//如果找不到,则提示不存在此题目
if (!isExist){
myJsonResult.setCodeAndMessage("0","不存在此题目,无法替换!");
}
return myJsonResult;
}
/**
* [DELETE]删除一个题目
* @author hanchao 2018/1/21 11:21
**/
@DeleteMapping("/question/{id}")
public MyJsonResult deleteQuestion(@PathVariable Integer id,@ModelAttribute("questions") Question[] questions ) {
MyJsonResult myJsonResult = new MyJsonResult();
boolean isExist = false;
//查找题目,如果找到,直接删除
for (int i = 0 ; i < questions.length; i ++){
Question qi = questions[i];
if (id.equals(qi.getId())){
questions[i] = null;
myJsonResult.setQuestions(questions);
break;
}
}
//如果找不到,则提示不存在此题目
if (!isExist){
myJsonResult.setCodeAndMessage("0","不存在此题目,无法删除!");
}
return myJsonResult;
}
/**
* [DELETE]删除所有题目
* @author hanchao 2018/1/21 11:24
**/
@DeleteMapping("/question/")
public MyJsonResult deleteAllQuestion() {
MyJsonResult myJsonResult = new MyJsonResult();
return myJsonResult;
}
}
<%--
Created by IntelliJ IDEA.
User: hanchao
Date: 2018/1/20
Time: 22:40
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>题目信息管理title>
<style type="text/css">
div{margin: 5px 5px; }
.div-left {float: left;margin: 5px 5px;}
.div-text-center {text-align:center; border:1px solid #96c2f1; background:#eff7ff;}
textarea{border:1px solid #9bdf70;background:#f0fbeb}
.in-text{width: 30px;}
style>
head>
<body>
<div class="div-left">
<textarea id="message" cols="50" rows="50">textarea>
div>
<div class="div-left">
<div class="div-text-center">
<label>题目id:label><input class="in-text" type="text" id="id" value="1"/><input type="button" value="查询一个(GET)" onclick="question('GET')"/>
div>
<div class="div-text-center">
<label>题目列表label><input type="button" value="查询所有(GET)" onclick="questions('GET')"/>
div>
<div class="div-text-center">
<table style="text-align: right">
<tr>
<td><label>idlabel>td>
<td><input id="new_id" type="text" value="1"/> td>
tr>
<tr>
<td><label>titlelabel>td>
<td><input id="new_title" type="text" value="新题目"/> td>
tr>
<tr>
<td><label>scorelabel>td>
<td><input id="new_score" type="text" value="100"/> td>
tr>
<tr>
<td><label>answerlabel>td>
<td><input id="new_answer" type="text" value="新答案"/> td>
tr>
<tr>
<td colspan="2"><input type="button" value="新增(POST)" onclick="question1('POST')"> td>
tr>
<tr>
<td><input type="button" value="替换(PUT)" onclick="question1('PUT')"> td>
<td><input type="button" value="修改(PATCH)" onclick="question1('PATCH')"> td>
tr>
table>
div>
<div class="div-text-center">
<label>题目id:label><input class="in-text" type="text" id="del_id" value="1"/>
<input type="button" value="删除一个(DELETE)" onclick="question('DELETE')">
div>
<div class="div-text-center">
<label>删除所有label><td><input type="button" value="删除所有(DELETE)" onclick="questions('DELETE')">
div>
div>
body>
<script type="text/javascript" src="../static/jquery-3.2.1.min.js">script>
<script type="text/javascript">
/**
* 获取一个题目:[GET]/restful/question/{id}
*/
/**
* 删除一个题目:[DELETE]/restful/question/{id}
*/
function question(type) {
$.ajax({
type:type,
url:"/restful/question/" + $("#id").val(),
contentType:"application/json;charset=utf-8",
success:function (data) {
console.log(data);
var html = "url[" + type + "]:/restful/question/" + $("#id").val() + "\n\nresult:\n" + JSON.stringify(data, null, 4);
$("#message").html(html);
}
});
}
/**
* 获取全部题目:[GET]/restful/question/
*/
/**
* 删除全部题目:[DELETE]/restful/question/
*/
function questions(type) {
$.ajax({
type:type,
url:"/restful/question/",
contentType:"application/json;charset=utf-8",
success:function (data) {
console.log(data);
var html = "url[" + type + "]:/restful/question/\n\nresult:\n" + JSON.stringify(data, null, 4);
$("#message").html(html);
}
});
}
/**
* 新增一个题目:[POST]/restful/question/
*/
/**
* 替换一个题目:[PUT]/restful/question/
*/
/**
* 修改一个题目:[PATCH]/restful/question/
*/
function question1(type) {
$.ajax({
type:type,
url:"/restful/question/",
data:JSON.stringify({
id:$("#new_id").val(),
title:$("#new_title").val(),
score:$("#new_score").val(),
answer:$("#new_answer").val()
}),
contentType:"application/json;charset:utf-8",
success:function (data) {
console.log(data);
var html = "url[" + type + "]:/restful/question/\n\nresult:\n" + JSON.stringify(data,null,4);
$("#message").html(html);
}
});
}
script>
html>