转:http://www.xdemo.org/spring-restful/
口水篇
REST是设计风格而不是标准
-
资源是由URI来指定。
-
对资源的操作包括获取、创建、修改和删除资源
这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
-
通过操作资源的表现形式来操作资源。
常用操作
GET | 获取 |
POST | 提交 |
PUT | 更新 |
Delete | 删除 |
REST确实不是标准,只是设计风格,目的只是让url看起来更简洁实用,是资源状态的一种表达。
实战篇
Demo下载地址http://pan.baidu.com/s/1o6sJLZs
项目结构
Maven依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!-- Jar版本管理 -->
<
properties
>
<
springframework
>4.0.2.RELEASE</
springframework
>
<
log4j
>1.2.17</
log4j
>
<
jstl
>1.2</
jstl
>
</
properties
>
<
dependencies
>
<!-- Spring web mvc -->
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-webmvc</
artifactId
>
<
version
>${springframework}</
version
>
</
dependency
>
<!-- JSTL -->
<
dependency
>
<
groupId
>jstl</
groupId
>
<
artifactId
>jstl</
artifactId
>
<
version
>${jstl}</
version
>
</
dependency
>
<!-- log4j -->
<
dependency
>
<
groupId
>log4j</
groupId
>
<
artifactId
>log4j</
artifactId
>
<
version
>${log4j}</
version
>
</
dependency
>
<!-- 单元测试 -->
<
dependency
>
<
groupId
>junit</
groupId
>
<
artifactId
>junit</
artifactId
>
<
version
>3.8.1</
version
>
<
scope
>test</
scope
>
</
dependency
>
</
dependencies
>
|
web.xml配置
需要注意,HiddenHttpMethodFilter是针对浏览器表单不支持put和delete方法而设计的,通过在表单中设置隐藏域,来分发到相应的处理器上,如<input type="hidden" name="_method" value="put" />
开发后记:最近把RESTful风格融入到了项目中去了,在开发过程中发现一个问题,就是aJax提交的PUT请求,无法通过HiddenHttpMethodFilter这个过滤器拿到值,后来搜索一番,改用HttpPutFormContentFilter即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!-- 通过http://java.sun.com/xml/ns/javaee/获取最新的schemaLocation -->
<
web-app
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns
=
"http://java.sun.com/xml/ns/javaee"
xmlns:web
=
"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version
=
"3.0"
>
<
display-name
>SpringActivemqServer</
display-name
>
<!-- WebAppRootKey -->
<
context-param
>
<
param-name
>webAppRootKey</
param-name
>
<
param-value
>example.SpringActivemqServer</
param-value
>
</
context-param
>
<!-- Log4J Start -->
<
context-param
>
<
param-name
>log4jConfigLocation</
param-name
>
<
param-value
>classpath:log4j.properties</
param-value
>
</
context-param
>
<
context-param
>
<
param-name
>log4jRefreshInterval</
param-name
>
<
param-value
>6000</
param-value
>
</
context-param
>
<!-- Spring Log4J config -->
<
listener
>
<
listener-class
>org.springframework.web.util.Log4jConfigListener</
listener-class
>
</
listener
>
<!-- Log4J End -->
<!-- Spring 编码过滤器 start -->
<
filter
>
<
filter-name
>characterEncoding</
filter-name
>
<
filter-class
>org.springframework.web.filter.CharacterEncodingFilter</
filter-class
>
<
init-param
>
<
param-name
>encoding</
param-name
>
<
param-value
>UTF-8</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>forceEncoding</
param-name
>
<
param-value
>true</
param-value
>
</
init-param
>
</
filter
>
<
filter-mapping
>
<
filter-name
>characterEncoding</
filter-name
>
<
url-pattern
>/*</
url-pattern
>
</
filter-mapping
>
<!-- Spring 编码过滤器 End -->
<!-- Spring Application Context Listener Start -->
<
context-param
>
<
param-name
>contextConfigLocation</
param-name
>
<
param-value
>classpath*:applicationContext.xml</
param-value
>
</
context-param
>
<
listener
>
<
listener-class
>org.springframework.web.context.ContextLoaderListener</
listener-class
>
</
listener
>
<!-- Spring Application Context Listener End -->
<!-- Spring MVC Config Start -->
<
servlet
>
<
servlet-name
>SpringMVC</
servlet-name
>
<
servlet-class
>org.springframework.web.servlet.DispatcherServlet</
servlet-class
>
<
init-param
>
<
param-name
>contextConfigLocation</
param-name
>
<
param-value
>classpath:spring-mvc.xml</
param-value
>
</
init-param
>
<
load-on-startup
>1</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>SpringMVC</
servlet-name
>
<!-- Filter all resources -->
<
url-pattern
>/</
url-pattern
>
</
servlet-mapping
>
<!-- Spring MVC Config End -->
<!-- 隐藏的HttpMethod方法过滤器,表单提交中需要携带一个name=_method的隐藏域,value=put或者delete -->
<
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
>SpringMVC</
servlet-name
>
</
filter-mapping
>
<
welcome-file-list
>
<
welcome-file
>index.jsp</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
|
spring-mvc.xml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
xmlns:context
=
"http://www.springframework.org/schema/context"
xmlns:mvc
=
"http://www.springframework.org/schema/mvc"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 防止@ResponseBody中文乱码 -->
<
bean
class
=
"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
>
<
property
name
=
"messageConverters"
>
<
list
>
<
bean
class
=
"org.springframework.http.converter.StringHttpMessageConverter"
>
<
property
name
=
"supportedMediaTypes"
>
<
list
>
<
bean
class
=
"org.springframework.http.MediaType"
>
<
constructor-arg
index
=
"0"
value
=
"text"
/>
<
constructor-arg
index
=
"1"
value
=
"plain"
/>
<
constructor-arg
index
=
"2"
value
=
"UTF-8"
/>
</
bean
>
</
list
>
</
property
>
</
bean
>
</
list
>
</
property
>
</
bean
>
<!-- 启用MVC注解 -->
<
mvc:annotation-driven
/>
<!-- 静态资源文件,不会被Spring MVC拦截 -->
<
mvc:resources
location
=
"/resources/"
mapping
=
"/resources/**"
/>
<!-- 指定Sping组件扫描的基本包路径 -->
<
context:component-scan
base-package
=
"org.xdemo.example"
>
<!-- 这里只扫描Controller,不可重复加载Service -->
<
context:include-filter
type
=
"annotation"
expression
=
"org.springframework.stereotype.Controller"
/>
</
context:component-scan
>
<!-- JSP视图解析器-->
<
bean
class
=
"org.springframework.web.servlet.view.InternalResourceViewResolver"
>
<
property
name
=
"prefix"
value
=
"/WEB-INF/views/"
/>
<
property
name
=
"suffix"
value
=
".jsp"
/>
<
property
name
=
"order"
value
=
"1"
/>
</
bean
>
</
beans
>
|
applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!-- 查找最新的schemaLocation 访问 http:
//www.springframework.org/schema/ -->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:context=
"http://www.springframework.org/schema/context"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:
//www.springframework.org/schema/beans
http:
//www.springframework.org/schema/beans/spring-beans-4.0.xsd
http:
//www.springframework.org/schema/context
http:
//www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置扫描路径 -->
<context:component-scan base-
package
=
"org.xdemo.example"
>
<!-- 只扫描Service,也可以添加Repostory,但是要把Controller排除在外,Controller由spring-mvc.xml去加载 -->
<!-- <context:include-filter type=
"annotation"
expression=
"org.springframework.stereotype.Service"
/> -->
<!-- <context:include-filter type=
"annotation"
expression=
"org.springframework.stereotype.Repository"
/> -->
<!-- <context:include-filter type=
"annotation"
expression=
"org.springframework.stereotype.Component"
/> -->
<context:exclude-filter type=
"annotation"
expression=
"org.springframework.stereotype.Controller"
/>
</context:component-scan>
</beans>
|
User实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package
org.xdemo.example.springrestful.entity;
/**
* @作者 Goofy
* @邮件 252878950@qq.com
* @日期 2014-4-2下午1:40:32
* @描述 用户实体类
*/
public
class
User {
private
String userId;
private
String userName;
public
User(){}
public
User(String userId,String userName){
this
.userId=userId;
this
.userName=userName;
}
/**
* @return the userId
*/
public
String getUserId() {
return
userId;
}
/**
* @param userId the userId to set
*/
public
void
setUserId(String userId) {
this
.userId = userId;
}
/**
* @return the userName
*/
public
String getUserName() {
return
userName;
}
/**
* @param userName the userName to set
*/
public
void
setUserName(String userName) {
this
.userName = userName;
}
}
|
UserController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
package
org.xdemo.example.springrestful.controller;
import
java.util.ArrayList;
import
java.util.List;
import
org.springframework.stereotype.Controller;
import
org.springframework.ui.ModelMap;
import
org.springframework.web.bind.annotation.PathVariable;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod;
import
org.springframework.web.bind.annotation.ResponseBody;
import
org.springframework.web.servlet.ModelAndView;
import
org.xdemo.example.springrestful.entity.User;
/**
* @作者 Goofy
* @邮件 252878950@qq.com
* @日期 2014-4-2下午1:28:07
*/
@Controller
@RequestMapping
(
"/user"
)
public
class
UserController {
public
List<User> list=
null
;
/**
* user路径下默认显示用户列表
* @return
*/
@RequestMapping
(method=RequestMethod.GET)
public
ModelAndView index(){
if
(list==
null
){
list=getUserList();
}
ModelMap model=
new
ModelMap();
model.addAttribute(
"list"
,list);
return
new
ModelAndView(
"user/index"
,model);
}
/**
* 跳转到添加用户页面,约定优于配置,默认匹配文件/WEB-INF/views/user/add.jsp
*/
@RequestMapping
(
"add"
)
public
void
add(){}
/**
* 新增保存用户
* @param user
* @return ModelAndView
*/
@RequestMapping
(method=RequestMethod.POST)
public
ModelAndView addUser(User user){
if
(list==
null
){
list=getUserList();
}
list.add(user);
ModelMap model=
new
ModelMap();
model.addAttribute(
"list"
,list);
return
new
ModelAndView(
"user/index"
,model);
}
/**
* 查看用户详细信息
* @param id
* @return ModelAndView
*/
@RequestMapping
(method=RequestMethod.GET,value=
"{id}"
)
public
ModelAndView viewUser(
@PathVariable
(
"id"
)String id){
User user=findUserById(id);
ModelMap model=
new
ModelMap();
model.addAttribute(
"user"
,user);
return
new
ModelAndView(
"user/view"
,model);
}
/**
* 删除用户
* @param id
*/
@ResponseBody
@RequestMapping
(method=RequestMethod.DELETE,value=
"{id}"
)
public
String deleteUser(
@PathVariable
(
"id"
)String id){
if
(list==
null
){
list=getUserList();
}
removeUserByUserId(id);
return
"suc"
;
}
/**
* 跳转到编辑页面
* @param id
* @return ModelAndView
*/
@RequestMapping
(
"{id}/edit"
)
public
ModelAndView toEdit(
@PathVariable
(
"id"
)String id){
User user=findUserById(id);
ModelMap model=
new
ModelMap();
model.addAttribute(
"user"
,user);
return
new
ModelAndView(
"user/edit"
,model);
}
/**
* 更新用户并跳转到用户列表页面
* @param user
* @return ModelAndView
*/
@RequestMapping
(method=RequestMethod.PUT)
public
ModelAndView edit(User user){
updateUser(user);
return
new
ModelAndView(
"redirect:/user/"
);
}
/********************下面方法是操作数据的*********************/
/**
* 造10个用户
* @return List<User>
*/
private
List<User> getUserList(){
List<User> list=
new
ArrayList<User>();
for
(
int
i=
0
; i<
10
;i++){
list.add(
new
User((i+
1
)+
""
,
"李四"
+(i+
1
)));
}
return
list;
}
/**
* 删除用户
* @param id
* @return List<User>
*/
private
List<User> removeUserByUserId(String id){
if
(list==
null
)
return
null
;
for
(User user:list){
if
(user.getUserId().equals(id)){
list.remove(user);
break
;
}
}
return
list;
}
/**
* 查找用户
* @param id
* @return User
*/
private
User findUserById(String id){
User user=
null
;
if
(list==
null
)
return
null
;
for
(User _user:list){
if
(_user.getUserId().equals(id)){
user=_user;
break
;
}
}
return
user;
}
/**
* 更新用户
* @param user
*/
private
void
updateUser(User user){
for
(User _user:list){
if
(_user.getUserId().equals(user.getUserId())){
_user.setUserName(user.getUserName());
break
;
}
}
}
}
|
用户列表页面index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
<%@ page language=
"java"
import
=
"java.util.*"
pageEncoding=
"UTF-8"
%>
<%@ taglib uri=
"http://java.sun.com/jsp/jstl/core"
prefix=
"c"
%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() +
"://"
+ request.getServerName() +
":"
+ request.getServerPort()
+ path +
"/"
;
%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
>
<html>
<head>
<base href=
"<%=basePath%>"
>
<title>用户列表</title>
<script type=
"text/javascript"
src=
"<%=basePath%>resources/jquery-1.11.0.min.js"
></script>
<style type=
"text/css"
>
a {
border: 1px solid rgb(
73
,
58
,
58
);
background-color: rgb(
133
,
133
,
133
);
height: 50px;
line-height: 50px;
color: white;
text-decoration: none;
font-weight: bold;
padding: 5px;
margin: 5px;
}
</style>
<script type=
"text/javascript"
>
function deleteUser(id){
$.ajax({
type:
'delete'
,
url:
'<%=basePath%>user/'
+id,
dataType:
'text'
,
success:function(data){
if
(data==
"suc"
){
alert(
"删除成功"
);
location.reload();
}
},
error:function(data){
}
});
}
</script>
</head>
<body>
<div style=
"margin:0 auto;width:500px;"
>
<a href=
"<%=basePath%>user/add"
>新增用户</a>
<table>
<tr>
<th>用户ID</th>
<th>用户名称</th>
<th>操作</th>
</tr>
<c:forEach var=
"user"
items=
"${list }"
>
<tr>
<td>${user.userId }</td>
<td>${user.userName }</td>
<td>
<a href=
"<%=basePath %>user/${user.userId}/edit"
>编辑用户</a>
<a href=
"<%=basePath %>user/${user.userId}"
>查看用户</a>
<a href=
"javascript:void(0);"
onclick=
"deleteUser(${user.userId })"
>删除该用户</a>
</td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
|
编辑用户页面edit.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
base
href="<%=basePath%>">
<
title
>新增用户页面</
title
>
</
head
>
<
body
>
<
div
style
=
"margin:0 auto;width:400px;"
>
<
form
action="<%=basePath%>user" method="post">
<!--此隐藏域可以被HiddenHttpMethodFilter所处理,然后分发到不同的HttpMethod的处理器上-->
<
input
type
=
"hidden"
name
=
"_method"
value
=
"put"
/>
<
table
>
<
tr
>
<
th
>用户ID</
th
>
<
th
>用户名称</
th
>
</
tr
>
<
tr
>
<
td
><
input
type
=
"text"
name
=
"userId"
id
=
"userId"
value
=
"${user.userId }"
readonly
=
"readonly"
/>
</
td
>
<
td
><
input
type
=
"text"
name
=
"userName"
id
=
"userName"
value
=
"${user.userName }"
/>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
><
input
type
=
"submit"
value
=
"保存用户"
/>
</
td
>
</
tr
>
</
table
>
</
form
>
</
div
>
</
body
>
</
html
>
|
新增用户页面add.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
base
href="<%=basePath%>">
<
title
>新增用户页面</
title
>
<
meta
http-equiv
=
"description"
content
=
"This is my page"
>
</
head
>
<
body
>
<
div
style
=
"margin:0 auto;width:400px;"
>
<
form
action="<%=basePath%>user" method="post">
<
table
>
<
tr
>
<
th
>用户ID</
th
>
<
th
>用户名称</
th
>
</
tr
>
<
tr
>
<
td
><
input
type
=
"text"
name
=
"userId"
id
=
"userId"
/>
</
td
>
<
td
><
input
type
=
"text"
name
=
"userName"
id
=
"userName"
/>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
><
input
type
=
"submit"
value
=
"保存用户"
/>
</
td
>
</
tr
>
</
table
>
</
form
>
</
div
>
</
body
>
</
html
>
|
查看用户页面view.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
base
href="<%=basePath%>">
<
title
>用户详情页面</
title
>
<
meta
http-equiv
=
"pragma"
content
=
"no-cache"
>
<
meta
http-equiv
=
"cache-control"
content
=
"no-cache"
>
<
meta
http-equiv
=
"expires"
content
=
"0"
>
<
meta
http-equiv
=
"keywords"
content
=
"keyword1,keyword2,keyword3"
>
<
meta
http-equiv
=
"description"
content
=
"This is my page"
>
</
head
>
<
body
>
<
div
style
=
"margin:0 auto;width:400px;"
>
<
form
action="<%=basePath%>user" method="post">
<
table
>
<
tr
>
<
th
>用户ID</
th
>
<
th
>用户名称</
th
>
</
tr
>
<
tr
>
<
td
>${user.userId}</
td
>
<
td
>${user.userName}</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
><
input
type
=
"button"
value
=
"返回用户列表"
onclick
=
"history.go(-1)"
/>
</
td
>
</
tr
>
</
table
>
</
form
>
</
div
>
</
body
>
</
html
>
|
运行截图
[转载请注明出处http://www.xdemo.org/spring-restful/]