转载自: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依赖
123456789101112131415161718192021222324252627282930313233 | <!-- 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即可
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 | <? 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配置
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 | <? 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
123456789101112131415161718 | <?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实体类
12345678910111213141516171819202122232425262728293031323334353637383940 | 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 | <%@ 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
123456789101112131415161718192021222324252627282930313233343536373839 | <%@ 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
123456789101112131415161718192021222324252627282930313233343536373839 | <%@ 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
1234567891011121314151617181920212223242526272829303132333435363738394041 | <%@ 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 > |
运行截图