badqiu

          XPer
          隨筆 - 46, 文章 - 3, 評論 - 195, 引用 - 0
          數據加載中……

          spring 3.0 應用springmvc 構造RESTful URL 詳細講解

          由于下一版本的rapid-framwork需要集成spring RESTful URL,所以研究了一下怎么搭建. 并碰到了一下問題。

           

          springmvc 3.0 中增加 RESTful URL功能,構造出類似javaeye現在的URL。 rest介紹
          比如如下URL

          Java代碼 
          1. /blog/1  HTTP GET =>    得到id = 1的blog  
          2. /blog/1  HTTP DELETE => 刪除 id = 1的blog  
          3. /blog/1  HTTP PUT  =>   更新id = 1的blog  
          4. /blog     HTTP POST =>   新增BLOG  

           

           

          以下詳細解一下spring rest使用.

           

          首先,我們帶著如下三個問題查看本文。

          1. 如何在java構造沒有擴展名的RESTful url,如 /forms/1,而不是 /forms/1.do

          2. 由于我們要構造沒有擴展名的url本來是處理靜態資源的容器映射的,現在被我們的spring占用了,沖突怎么解決?

          3. 瀏覽器的form標簽不支持提交delete,put請求,如何曲線解決?

           

          springmvc rest 實現


          springmvc的resturl是通過@RequestMapping 及@PathVariable annotation提供的,通過如@RequestMapping(value="/blog/{id}",method=RequestMethod.DELETE)即可處理/blog/1 的delete請求.

          Java代碼 
          1. @RequestMapping(value="/blog/{id}",method=RequestMethod.DELETE)  
          2. public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {  
          3.     blogManager.removeById(id);  
          4.     return new ModelAndView(LIST_ACTION);  
          5. }  

           

          @RequestMapping @PathVariable如果URL中帶參數,則配合使用,如

          Java代碼 
          1. @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) {  
          3. }  

           

           spring rest配置指南

          1. springmvc web.xml配置

          Xml代碼 
          1. <!-- 該servlet為tomcat,jetty等容器提供,將靜態資源映射從/改為/static/目錄,如原來訪問 http://localhost/foo.css ,現在http://localhost/static/foo.css -->  
          2. <servlet-mapping>  
          3.     <servlet-name>default</servlet-name>  
          4.     <url-pattern>/static/*</url-pattern>  
          5. </servlet-mapping>  
          6. <servlet>  
          7.     <servlet-name>springmvc</servlet-name>  
          8.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
          9.     <load-on-startup>1</load-on-startup>  
          10. </servlet>  
          11.   
          12. <!-- URL重寫filter,用于將訪問靜態資源http://localhost/foo.css 轉為http://localhost/static/foo.css -->  
          13. <filter>  
          14.     <filter-name>UrlRewriteFilter</filter-name>  
          15.     <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>  
          16.     <init-param>  
          17.             <param-name>confReloadCheckInterval</param-name>  
          18.             <param-value>60</param-value>  
          19.         </init-param>  
          20.     <init-param>  
          21.                 <param-name>logLevel</param-name>  
          22.                 <param-value>DEBUG</param-value>  
          23.         </init-param>       
          24. </filter>  
          25. <filter-mapping>  
          26.     <filter-name>UrlRewriteFilter</filter-name>  
          27.     <url-pattern>/*</url-pattern>  
          28. </filter-mapping>  
          29.   
          30. <!-- 覆蓋default servlet的/, springmvc servlet將處理原來處理靜態資源的映射 -->  
          31. <servlet-mapping>  
          32.     <servlet-name>springmvc</servlet-name>  
          33.     <url-pattern>/</url-pattern>  
          34. </servlet-mapping>  
          35.   
          36. <!-- 瀏覽器不支持put,delete等method,由該filter將/blog?_method=delete轉換為標準的http delete方法 -->  
          37. <filter>  
          38.     <filter-name>HiddenHttpMethodFilter</filter-name>  
          39.     <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>  
          40. </filter>  
          41.   
          42. <filter-mapping>  
          43.     <filter-name>HiddenHttpMethodFilter</filter-name>  
          44.     <servlet-name>springmvc</servlet-name>  
          45. </filter-mapping>  

           

           

          2. webapp/WEB-INF/springmvc-servlet.xml配置,使用如下兩個class激活@RequestMapping annotation

          Java代碼 
          1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>  
          2. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  

           

          完整配置

          Java代碼 
          1. <beans default-autowire="byName"   >  
          2.   
          3.     <!-- 自動搜索@Controller標注的類 -->  
          4.     <context:component-scan base-package="com.**.controller"/>  
          5.       
          6.     <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>  
          7.   
          8.     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  
          9.   
          10.     <!-- Default ViewResolver -->  
          11.     <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
          12.         <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
          13.         <property name="prefix" value="/pages"/>  
          14.         <property name="suffix" value=".jsp"></property>  
          15.     </bean>  
          16.       
          17.     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="i18n/messages"/>  
          18.   
          19.     <!-- Mapping exception to the handler view -->  
          20.     <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
          21.         <!-- to /commons/error.jsp -->  
          22.         <property name="defaultErrorView" value="/commons/error"/>  
          23.         <property name="exceptionMappings">  
          24.             <props>  
          25.             </props>  
          26.         </property>  
          27.     </bean>  
          28.           
          29. </beans>  

           

           

          3. Controller編寫

          Java代碼 
          1. /** 
          2.  * @RequestMapping("/userinfo") 具有層次關系,方法級的將在類一級@RequestMapping之一, 
          3.  * 如下面示例, 訪問方法級別的@RequestMapping("/new"),則URL為 /userinfo/new 
          4.  */  
          5. @Controller  
          6. @RequestMapping("/userinfo")  
          7. public class UserInfoController extends BaseSpringController{  
          8.     //默認多列排序,example: username desc,createTime asc  
          9.     protected static final String DEFAULT_SORT_COLUMNS = null;   
          10.       
          11.     private UserInfoManager userInfoManager;  
          12.       
          13.     private final String LIST_ACTION = "redirect:/userinfo";  
          14.       
          15.     /**  
          16.      * 通過spring自動注入 
          17.      **/  
          18.     public void setUserInfoManager(UserInfoManager manager) {  
          19.         this.userInfoManager = manager;  
          20.     }  
          21.       
          22.     /** 列表 */  
          23.     @RequestMapping  
          24.     public ModelAndView index(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) {  
          25.         PageRequest<Map> pageRequest = newPageRequest(request,DEFAULT_SORT_COLUMNS);  
          26.         //pageRequest.getFilters(); //add custom filters  
          27.           
          28.         Page page = this.userInfoManager.findByPageRequest(pageRequest);  
          29.         savePage(page,pageRequest,request);  
          30.         return new ModelAndView("/userinfo/list","userInfo",userInfo);  
          31.     }  
          32.       
          33.     /** 進入新增 */  
          34.     @RequestMapping(value="/new")  
          35.     public ModelAndView _new(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {  
          36.         return new ModelAndView("/userinfo/new","userInfo",userInfo);  
          37.     }  
          38.       
          39.     /** 顯示 */  
          40.     @RequestMapping(value="/{id}")  
          41.     public ModelAndView show(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {  
          42.         UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
          43.         return new ModelAndView("/userinfo/show","userInfo",userInfo);  
          44.     }  
          45.       
          46.     /** 編輯 */  
          47.     @RequestMapping(value="/{id}/edit")  
          48.     public ModelAndView edit(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {  
          49.         UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
          50.         return new ModelAndView("/userinfo/edit","userInfo",userInfo);  
          51.     }  
          52.       
          53.     /** 保存新增 */  
          54.     @RequestMapping(method=RequestMethod.POST)  
          55.     public ModelAndView create(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {  
          56.         userInfoManager.save(userInfo);  
          57.         return new ModelAndView(LIST_ACTION);  
          58.     }  
          59.       
          60.     /** 保存更新 */  
          61.     @RequestMapping(value="/{id}",method=RequestMethod.PUT)  
          62.     public ModelAndView update(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {  
          63.         UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
          64.         bind(request,userInfo);  
          65.         userInfoManager.update(userInfo);  
          66.         return new ModelAndView(LIST_ACTION);  
          67.     }  
          68.       
          69.     /** 刪除 */  
          70.     @RequestMapping(value="/{id}",method=RequestMethod.DELETE)  
          71.     public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {  
          72.         userInfoManager.removeById(id);  
          73.         return new ModelAndView(LIST_ACTION);  
          74.     }  
          75.   
          76.     /** 批量刪除 */  
          77.     @RequestMapping(method=RequestMethod.DELETE)  
          78.     public ModelAndView batchDelete(@RequestParam("items") Long[] items,HttpServletRequest request,HttpServletResponse response) {  
          79.           
          80.         for(int i = 0; i < items.length; i++) {  
          81.               
          82.             userInfoManager.removeById(items[i]);  
          83.         }  
          84.         return new ModelAndView(LIST_ACTION);  
          85.     }  
          86.       
          87. }  

           

           

          上面是rapid-framework 新版本生成器生成的代碼,以后也將應用此規則,rest url中增刪改查等基本方法與Controller的方法映射規則

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

           注(不使用 /userinfo/add  => add() 方法是由于add這個方法會被maxthon瀏覽器當做廣告鏈接過濾掉,因為包含ad字符)

           

          4. jsp 編寫

          Html代碼 
          1. <form:form action="${ctx}/userinfo/${userInfo.userId}" method="put">  
          2. </form:form>  

           生成的html內容如下, 生成一個hidden的_method=put,并于web.xml中的HiddenHttpMethodFilter配合使用,在服務端將post請求改為put請求

          Java代碼 
          1. <form id="userInfo" action="/springmvc_rest_demo/userinfo/2" method="post">  
          2.     <input type="hidden" name="_method" value="put"/>  
          3. </form>  

           

          另外一種方法是你可以使用ajax發送put,delete請求.

           

          5. 靜態資源的URL重寫

             如上我們描述,現因為將default servlet映射至/static/的子目錄,現我們訪問靜態資源將會帶一個/static/前綴.

             如 /foo.gif, 現在訪問該文件將是 /static/foo.gif.
             那如何避免這個前綴呢,那就是應用URL rewrite,現我們使用 http://tuckey.org/urlrewrite/, 重寫規則如下

           

          Xml代碼 
          1. <urlrewrite>  
          2.     <!-- 訪問jsp及jspx將不rewrite url,其它.js,.css,.gif等將重寫,如 /foo.gif => /static/foo.gif -->  
          3.     <rule>  
          4.         <condition operator="notequal" next="and" type="request-uri">.*.jsp</condition>  
          5.         <condition operator="notequal" next="and" type="request-uri">.*.jspx</condition>  
          6.         <from>^(/.*\..*)$</from>  
          7.         <to>/static$1</to>  
          8.     </rule>  
          9. </urlrewrite>  

             另筆者專門寫了一個 RestUrlRewriteFilter來做同樣的事件,以后會隨著rapid-framework一起發布. 比這個更加輕量級.

           

          并且該代碼已經貢獻給spring,不知會不會在下一版本發布

           

          posted on 2009-09-22 20:49 badqiu 閱讀(28550) 評論(9)  編輯  收藏

          評論

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          http://s.click.taobao.com/t_1?i=rWs3FkQtwkA%3D&p=mm_14068224_0_0&n=12
          2009-09-23 02:49 | dff

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解[未登錄]  回復  更多評論   

          如果spring用filter代替servlet來做dispatcher就不需要url rewrite了
          2009-09-26 16:05 | chen

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          這種玩具夠多了,
          2010-01-22 18:39 | 孩子你太天真了

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          請問,spring3.0中如何獲取表單數據,放到一個javabean對象中呢?急啊。。。。。。。。謝謝!
          2010-03-02 05:07 | 夜星

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          我參考了你的例子后,發現
          2010-08-18 16:02 | chyenu

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          我參考了你的例子后,發現方法的@RequestMapping只要沒有給定值,在返回的時候返回的是ModelAndView的時候就不按我給定的頁面跳轉。只有返回的是String時才會按我給定的頁面跳。請問是為什么呀?
          /** 刪除 */
          @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
          public String delete(@PathVariable
          Long id, HttpServletRequest request, HttpServletResponse response) {

          return "/rest/delete";
          }
          這是個例子,如果把返回改為ModelAndView時:
          return new ModelAndView("/rest/delete").返回的頁面是我Controller定義的@RequestMapping+方法名.jsp.這是為什么呢?
          不知道我描述的是否清楚。
          期待你的回復。謝謝
          2010-08-18 16:06 | chyenu

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解[未登錄]  回復  更多評論   

          添加后綴是由于這個起作用:

          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
          <property name="prefix" value="/pages"/>
          <property name="suffix" value=".jsp"/>
          </bean>
          2010-08-18 18:26 | badqiu

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          jjk
          2013-04-04 00:03 | mmm

          # re: spring 3.0 應用springmvc 構造RESTful URL 詳細講解  回復  更多評論   

          springmvc demo源代碼下載:http://zuidaima.com/share/kspringmvc-p1-s1.htm
          2014-08-09 10:16 | zuidaima

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: SHOW| 犍为县| 桐乡市| 绥中县| 通海县| 孟村| 巴彦县| 慈利县| 昂仁县| 揭东县| 通许县| 胶南市| 长葛市| 多伦县| 祥云县| 利辛县| 陕西省| 舒城县| 山阳县| 乾安县| 云阳县| 西贡区| 合山市| 观塘区| 长治市| 拉萨市| 长阳| 宁都县| 宜宾县| 阿合奇县| 桐庐县| 双牌县| 习水县| 城固县| 弥渡县| 靖西县| 瑞丽市| 高唐县| 松溪县| 五河县| 扎赉特旗|