REST是设计风格而不是标准
-
资源是由URI来指定。
-
对资源的操作包括获取、创建、修改和删除资源
这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
-
通过操作资源的表现形式来操作资源。
常用操作
| GET | 获取 | | POST | 提交 | | PUT | 更新 | | Delete | 删除 |
REST确实不是标准,只是设计风格,目的只是让url看起来更简洁实用,是资源状态的一种表达。
实战篇
Demo下载地址http://pan.baidu.com/s/1o6sJLZs
项目结构
Maven依赖
<!-- 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方法而设计的,通过在表单中设置隐藏域,来分发到相应的处理器上,如:
开发后记:最近把RESTful风格融入到了项目中去了,在开发过程中发现一个问题,就是aJax提交的PUT请求,无法通过HiddenHttpMethodFilter这个过滤器拿到值,后来搜索一番,改用HttpPutFormContentFilter即可
<?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配置**
<?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
<?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实体类
package org.xdemo.example.springrestful.entity;
/***
* @描述 用户实体类
*/
public class User {
private String userId;
private String userName;
public User(){}
public User(String userId,String userName){
this.userId=userId;
this.userName=userName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
UserController
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;
@Controller
@RequestMapping("/user")
public class UserController {
// user路径下默认显示用户列表
public List<User> list=null;
@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(){}
// 新增保存用户
@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);
}
// 查看用户详细信息
@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);
}
// 删除用户
@ResponseBody
@RequestMapping(method=RequestMethod.DELETE,value="{id}")
public String deleteUser(@PathVariable("id")String id){
if(list==null){
list=getUserList();
}
removeUserByUserId(id);
return "suc";
}
// 跳转到编辑页面
@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);
}
// 更新用户并跳转到用户列表页面
@RequestMapping(method=RequestMethod.PUT)
public ModelAndView edit(User user){
updateUser(user);
return new ModelAndView("redirect:/user/");
}
/********************下面方法是操作数据的*********************/
/**
* 造10个用户
* @return
*/
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
*/
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
*/
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
<%@ 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"/>
<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
<%@ 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
<%@ 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
<%@ 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>
运行截图