Springmvc构造RESTful详细讲解
Rest介绍
 /blog/1 HTTP GET =>  得到id = 1的blog
/blog/1 HTTP GET =>  得到id = 1的blog /blog/1 HTTP DELETE => 删除 id = 1的blog
/blog/1 HTTP DELETE => 删除 id = 1的blog /blog/1 HTTP PUT =>  更新id = 1的blog
/blog/1 HTTP PUT =>  更新id = 1的blog /blog   HTTP POST =>  新增BLOG
/blog   HTTP POST =>  新增BLOG
以下详细解一下spring rest使用.
首先,我们带着如下两个问题查看本文。
1.如何在java构造没有扩展名的RESTful url,如 /forms/1,而不是 /forms/1.do
2.浏览器的form标签不支持提交delete,put请求,如何曲线解决
springmvc rest 实现
    springmvc的resturl是通过@RequestMapping 及@PathVariable annotation提供的,
    通过如@RequestMapping(value="/blog /{id}",method=RequestMethod.DELETE)即可处理/blog/1 的delete请求.
 @RequestMapping(value="/blog/{id}",method=RequestMethod.DELETE)
@RequestMapping(value="/blog/{id}",method=RequestMethod.DELETE)2
 public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {
public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {3
 blogManager.removeById(id);
  blogManager.removeById(id);4
 return new ModelAndView(LIST_ACTION);
  return new ModelAndView(LIST_ACTION);5
 }
}
@RequestMapping @PathVariable如果URL中带参数,则配合使用,如
 @RequestMapping(value="/blog/{blogId}/message/{msgId}",method=RequestMethod.DELETE)
@RequestMapping(value="/blog/{blogId}/message/{msgId}",method=RequestMethod.DELETE)2
 public ModelAndView delete(@PathVariable("blogId") Long blogId,@PathVariable("msgId") Long msgId,HttpServletRequest request,HttpServletResponse response) {
public ModelAndView delete(@PathVariable("blogId") Long blogId,@PathVariable("msgId") Long msgId,HttpServletRequest request,HttpServletResponse response) {3
 }
}
1.springmvc web.xml配置
 <!-- 该servlet为tomcat,jetty等容器提供,将静态资源映射从/改为/static/目录,如原来访问 http://localhost/foo.css ,现在http://localhost/static/foo.css -->
<!-- 该servlet为tomcat,jetty等容器提供,将静态资源映射从/改为/static/目录,如原来访问 http://localhost/foo.css ,现在http://localhost/static/foo.css -->2
 <servlet-mapping>
  <servlet-mapping>3
 <servlet-name>default</servlet-name>
  <servlet-name>default</servlet-name>4
 <url-pattern>/static/*</url-pattern>
  <url-pattern>/static/*</url-pattern>5
 </servlet-mapping>
  </servlet-mapping>6
 <servlet>
  <servlet>7
 <servlet-name>springmvc</servlet-name>
    <servlet-name>springmvc</servlet-name>8
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>9
 <load-on-startup>1</load-on-startup>
    <load-on-startup>1</load-on-startup>10
 </servlet>
  </servlet>11

12
 <!-- URL重写filter,用于将访问静态资源http://localhost/foo.css 转为http://localhost/static/foo.css -->
  <!-- URL重写filter,用于将访问静态资源http://localhost/foo.css 转为http://localhost/static/foo.css -->13
 <filter>
  <filter>14
 <filter-name>UrlRewriteFilter</filter-name>
  <filter-name>UrlRewriteFilter</filter-name>15
 <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
  <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>16
 <init-param>
  <init-param>17
 <param-name>confReloadCheckInterval</param-name>
     <param-name>confReloadCheckInterval</param-name>18
 <param-value>60</param-value>
     <param-value>60</param-value>19
 </init-param>
    </init-param>20
 <init-param>
  <init-param>21
 <param-name>logLevel</param-name>
        <param-name>logLevel</param-name>22
 <param-value>DEBUG</param-value>
        <param-value>DEBUG</param-value>23
 </init-param>
      </init-param>24
 </filter>
  </filter>25
 <filter-mapping>
  <filter-mapping>26
 <filter-name>UrlRewriteFilter</filter-name>
  <filter-name>UrlRewriteFilter</filter-name>27
 <url-pattern>/*</url-pattern>
  <url-pattern>/*</url-pattern>28
 </filter-mapping>
  </filter-mapping>29

30
 <!-- 覆盖default servlet的/, springmvc servlet将处理原来处理静态资源的映射 -->
  <!-- 覆盖default servlet的/, springmvc servlet将处理原来处理静态资源的映射 -->31
 <servlet-mapping>
  <servlet-mapping>32
 <servlet-name>springmvc</servlet-name>
    <servlet-name>springmvc</servlet-name>33
 <url-pattern>/</url-pattern>
    <url-pattern>/</url-pattern>34
 </servlet-mapping>
  </servlet-mapping>35

36
 <!-- 浏览器不支持put,delete等method,由该filter将/blog?_method=delete转换为标准的http delete方法 -->
  <!-- 浏览器不支持put,delete等method,由该filter将/blog?_method=delete转换为标准的http delete方法 -->37
 <filter>
  <filter>38
 <filter-name>HiddenHttpMethodFilter</filter-name>
  <filter-name>HiddenHttpMethodFilter</filter-name>39
 <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>40
 </filter>
  </filter>41

42
 <filter-mapping>
  <filter-mapping>43
 <filter-name>HiddenHttpMethodFilter</filter-name>
  <filter-name>HiddenHttpMethodFilter</filter-name>44
 <servlet-name>springmvc</servlet-name>
  <servlet-name>springmvc</servlet-name>45
 </filter-mapping>
  </filter-mapping>
2.webapp/WEB-INF/springmvc-servlet.xml配置,使用如下两个class激活@RequestMapping annotation
 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>   2
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  3

3.Controller编写
 /**
/**2
 * @RequestMapping("/userinfo") 具有层次关系,方法级的将在类一级@RequestMapping之一,
  * @RequestMapping("/userinfo") 具有层次关系,方法级的将在类一级@RequestMapping之一,3
 * 如下面示例, 访问方法级别的@RequestMapping("/new"),则URL为 /userinfo/new
  * 如下面示例, 访问方法级别的@RequestMapping("/new"),则URL为 /userinfo/new4
 */
  */5
 @Controller
@Controller6
 @RequestMapping("/userinfo")
@RequestMapping("/userinfo")7
 public class UserInfoController extends BaseSpringController{
public class UserInfoController extends BaseSpringController{8
 //默认多列排序,example: username desc,createTime asc
  //默认多列排序,example: username desc,createTime asc9
 protected static final String DEFAULT_SORT_COLUMNS = null;
  protected static final String DEFAULT_SORT_COLUMNS = null;10

11
 private UserInfoManager userInfoManager;
  private UserInfoManager userInfoManager;12

13
 private final String LIST_ACTION = "redirect:/userinfo";
  private final String LIST_ACTION = "redirect:/userinfo";14

15
 /**
  /**16
 * 通过spring自动注入
  * 通过spring自动注入17
 **/
  **/18
 public void setUserInfoManager(UserInfoManager manager) {
  public void setUserInfoManager(UserInfoManager manager) {19
 this.userInfoManager = manager;
  this.userInfoManager = manager;20
 }
  }21

22
 /** 列表 */
  /** 列表 */23
 @RequestMapping
  @RequestMapping24
 public ModelAndView index(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) {
  public ModelAndView index(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) {25
 PageRequest<Map> pageRequest = newPageRequest(request,DEFAULT_SORT_COLUMNS);
  PageRequest<Map> pageRequest = newPageRequest(request,DEFAULT_SORT_COLUMNS);26
 //pageRequest.getFilters(); //add custom filters
  //pageRequest.getFilters(); //add custom filters 27

28
 Page page = this.userInfoManager.findByPageRequest(pageRequest);
  Page page = this.userInfoManager.findByPageRequest(pageRequest);29
 savePage(page,pageRequest,request);
  savePage(page,pageRequest,request);30
 return new ModelAndView("/userinfo/list","userInfo",userInfo);
  return new ModelAndView("/userinfo/list","userInfo",userInfo);31
 }
  }32

33
 /** 进入新增 */
  /** 进入新增 */34
 @RequestMapping(value="/new")
  @RequestMapping(value="/new")35
 public ModelAndView _new(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {
  public ModelAndView _new(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {36
 return new ModelAndView("/userinfo/new","userInfo",userInfo);
  return new ModelAndView("/userinfo/new","userInfo",userInfo);37
 }
  }38

39
 /** 显示 */
  /** 显示 */40
 @RequestMapping(value="/{id}")
  @RequestMapping(value="/{id}")41
 public ModelAndView show(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
  public ModelAndView show(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {42
 UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
  UserInfo userInfo = (UserInfo)userInfoManager.getById(id);43
 return new ModelAndView("/userinfo/show","userInfo",userInfo);
  return new ModelAndView("/userinfo/show","userInfo",userInfo);44
 }
  }45

46
 /** 编辑 */
  /** 编辑 */47
 @RequestMapping(value="/{id}/edit")
  @RequestMapping(value="/{id}/edit")48
 public ModelAndView edit(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
  public ModelAndView edit(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {49
 UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
  UserInfo userInfo = (UserInfo)userInfoManager.getById(id);50
 return new ModelAndView("/userinfo/edit","userInfo",userInfo);
  return new ModelAndView("/userinfo/edit","userInfo",userInfo);51
 }
  }52

53
 /** 保存新增 */
  /** 保存新增 */54
 @RequestMapping(method=RequestMethod.POST)
  @RequestMapping(method=RequestMethod.POST)55
 public ModelAndView create(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {
  public ModelAndView create(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {56
 userInfoManager.save(userInfo);
  userInfoManager.save(userInfo);57
 return new ModelAndView(LIST_ACTION);
  return new ModelAndView(LIST_ACTION);58
 }
  }59

60
 /** 保存更新 */
  /** 保存更新 */61
 @RequestMapping(value="/{id}",method=RequestMethod.PUT)
  @RequestMapping(value="/{id}",method=RequestMethod.PUT)62
 public ModelAndView update(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
  public ModelAndView update(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {63
 UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
  UserInfo userInfo = (UserInfo)userInfoManager.getById(id);64
 bind(request,userInfo);
  bind(request,userInfo);65
 userInfoManager.update(userInfo);
  userInfoManager.update(userInfo);66
 return new ModelAndView(LIST_ACTION);
  return new ModelAndView(LIST_ACTION);67
 }
  }68

69
 /** 删除 */
  /** 删除 */70
 @RequestMapping(value="/{id}",method=RequestMethod.DELETE)
  @RequestMapping(value="/{id}",method=RequestMethod.DELETE)71
 public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {
  public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {72
 userInfoManager.removeById(id);
  userInfoManager.removeById(id);73
 return new ModelAndView(LIST_ACTION);
  return new ModelAndView(LIST_ACTION);74
 }
  }75

76
 /** 批量删除 */
  /** 批量删除 */77
 @RequestMapping(method=RequestMethod.DELETE)
  @RequestMapping(method=RequestMethod.DELETE)78
 public ModelAndView batchDelete(HttpServletRequest request,HttpServletResponse response) {
  public ModelAndView batchDelete(HttpServletRequest request,HttpServletResponse response) {79
 String[] items = request.getParameterValues("items");
  String[] items = request.getParameterValues("items");80
 for(int i = 0; i < items.length; i++) {
  for(int i = 0; i < items.length; i++) {81
 java.lang.Long id = new java.lang.Long(items[i]);
   java.lang.Long id = new java.lang.Long(items[i]);82
 userInfoManager.removeById(id);
   userInfoManager.removeById(id);83
 }
  }84
 return new ModelAndView(LIST_ACTION);
  return new ModelAndView(LIST_ACTION);85
 }
  }86

87
 }
}88

 /userinfo  => index()
/userinfo  => index()2
 /userinfo/new => _new()
  /userinfo/new => _new()3
 /userinfo/{id} => show()
  /userinfo/{id} => show()4
 /userinfo/{id}/edit  => edit()
  /userinfo/{id}/edit  => edit()5
 /userinfo POST => create()
  /userinfo POST => create()6
 /userinfo/{id} PUT => update()
  /userinfo/{id} PUT => update()7
 /userinfo/{id} DELETE => delete()
  /userinfo/{id} DELETE => delete()8
 /userinfo DELETE => batchDelete()
  /userinfo DELETE => batchDelete()9

    
    注(不使用 /userinfo/add  => add() 方法是由于add这个方法会被maxthon浏览器当做广告链接过滤掉,因为包含ad字符)
 
4.jsp 编写
 <form:form action="${ctx}/userinfo${userInfo.userId}" method="put">
<form:form action="${ctx}/userinfo${userInfo.userId}" method="put">2
 </form:form>
</form:form>
生成的html内容如下, 生成一个hidden的_method=put,并于web.xml中的HiddenHttpMethodFilter配合使用,在服务端将post请求改为put请求
 <form id="userInfo" action="/springmvc_rest_demo/userinfo/2" method="post">
<form id="userInfo" action="/springmvc_rest_demo/userinfo/2" method="post">2
 <input type="hidden" name="_method" value="put"/>
  <input type="hidden" name="_method" value="put"/>3
 </form>
</form>
    另外一种方法是你可以使用ajax发送put,delete请求.
5.静态资源的URL重写
如上我们描述,现因为将default servlet映射至/static/的子目录,现我们访问静态资源将会带一个/static/前缀.
如 /foo.gif, 现在访问该文件将是 /static/foo.gif.
那如何避免这个前缀呢,那就是应用URL rewrite,现我们使用 http://tuckey.org/urlrewrite/, 重写规则如下
 <urlrewrite>
<urlrewrite>2
 <!-- 访问jsp及jspx将不rewrite url,其它.js,.css,.gif等将重写,如 /foo.gif => /static/foo.gif -->
   <!-- 访问jsp及jspx将不rewrite url,其它.js,.css,.gif等将重写,如 /foo.gif => /static/foo.gif -->3
 <rule>
   <rule>4
 <condition operator="notequal" next="and" type="request-uri">.*.jsp</condition>
    <condition operator="notequal" next="and" type="request-uri">.*.jsp</condition>5
 <condition operator="notequal" next="and" type="request-uri">.*.jspx</condition>
    <condition operator="notequal" next="and" type="request-uri">.*.jspx</condition>6
 <from>^(/.*\..*)$</from>
     <from>^(/.*\..*)$</from>7
 <to>/static$1</to>
     <to>/static$1</to>8
 </rule>
   </rule>9
 </urlrewrite>
</urlrewrite>
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号