spring mvc RESTful url

详细讲解spring rest使用,简单例子如下:
/blog/
1
  HTTP GET =>    得到id = 
1
的blog  

 


/blog/1
  HTTP DELETE => 删除 id = 
1
的blog  

 


/blog/1
  HTTP PUT  =>   更新id = 
1
的blog  

 


/blog     HTTP POST =>   新增BLOG

首先,我们带着如下个问题查看本文。1. 如何在java构造没有扩展名的RESTful url,如 /forms/1,而不是 /forms/1.do

2. 由于我们要构造没有扩展名的url本来是处理静态资源的容器映射的,现在被我们的spring占用了,冲突怎么解决?

3. 浏览器的form标签不支持提交delete,put请求,如何曲线解决?

spring mvc rest 实现

spring mvc的resturl是通过@RequestMapping 及@PathVariable annotation提供的,通过如@RequestMapping(value="/blog/{id}",method=RequestMethod.DELETE)即可处理/blog/1 的delete请求.

@RequestMapping
(value=
"/blog/{id}"
,method=RequestMethod.DELETE)  

 


public
 ModelAndView delete(
@PathVariable
 Long id,HttpServletRequest request,HttpServletResponse response) {  

 


    blogManager.removeById(id);  
 


    return
 
new
 ModelAndView(LIST_ACTION);  

 


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

@RequestMapping @PathVariable如果URL中带参数,则配合使用,如

@RequestMapping
(value=
"/blog/{blogId}/message/{msgId}"
,method=RequestMethod.DELETE)  

 


public
 ModelAndView delete(
@PathVariable
(
"blogId"
) Long blogId,
@PathVariable
(
"msgId"
) Long msgId,HttpServletRequest request,HttpServletResponse response) {  

 


}
@RequestMapping(value="/blog/{blogId}/message/{msgId}",method=RequestMethod.DELETE)
public ModelAndView delete(@PathVariable("blogId") Long blogId,@PathVariable("msgId") Long msgId,HttpServletRequest request,HttpServletResponse response) {
}

spring rest配置指南

1. spring mvc web.xml配置

<bean 
class
=
"org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"
/>  

 


<bean class
=
"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

完整配置

<beans 
default
-autowire=
"byName"
   >  

 


  
 


    <!-- 自动搜索@Controller
标注的类 -->  

 


    <context:component-scan base-package
=
"com.**.controller"
/>  

 


      
 


    <bean class
=
"org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"
/>  

 


  
 


    <bean class
=
"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
/>  

 


  
 


    <!-- Default ViewResolver -->  
 


    <bean id="viewResolver"
 
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"
></property>  

 


    </bean>  
 


      
 


    <bean id="messageSource"
 
class
=
"org.springframework.context.support.ResourceBundleMessageSource"
 p:basename=
"i18n/messages"
/>  

 


  
 


    <!-- Mapping exception to the handler view -->  
 


    <bean id="exceptionResolver"
 
class
=
"org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
>  

 


        <!-- to /commons/error.jsp -->  
 


        <property name="defaultErrorView"
 value=
"/commons/error"
/>  

 


        <property name="exceptionMappings"
>  

 


            <props>  
 


            </props>  
 


        </property>  
 


    </bean>  
 


          
 


</beans>
<beans default-autowire="byName"   >

	<!-- 自动搜索@Controller标注的类 -->
	<context:component-scan base-package="com.**.controller"/>
	
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

    <!-- Default ViewResolver -->
    <bean id="viewResolver" 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"></property>
    </bean>
    
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="i18n/messages"/>

    <!-- Mapping exception to the handler view -->
    <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    	<!-- to /commons/error.jsp -->
        <property name="defaultErrorView" value="/commons/error"/>
        <property name="exceptionMappings">
            <props>
            </props>
        </property>
    </bean>
        
</beans>

3. Controller编写

/**
 
 


 * @RequestMapping("/userinfo") 具有层次关系,方法级的将在类一级@RequestMapping之一,
 
 


 * 如下面示例, 访问方法级别的@RequestMapping("/new"),则URL为 /userinfo/new
 
 


 */
  

 


@Controller
  

 


@RequestMapping
(
"/userinfo"
)  

 


public
 
class
 UserInfoController 
extends
 BaseSpringController{  

 


    //默认多列排序,example: username desc,createTime asc
  

 


    protected
 
static
 
final
 String DEFAULT_SORT_COLUMNS = 
null
;   

 


      
 


    private
 UserInfoManager userInfoManager;  

 


      
 


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

 


      
 


    /** 
 
 


     * 通过spring自动注入
 
 


     **/
  

 


    public
 
void
 setUserInfoManager(UserInfoManager manager) {  

 


        this
.userInfoManager = manager;  

 


    }  
 


      
 


    /** 列表 */
  

 


    @RequestMapping
  

 


    public
 ModelAndView index(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) {  

 


        PageRequest<Map> pageRequest = newPageRequest(request,DEFAULT_SORT_COLUMNS);  
 


        //pageRequest.getFilters(); //add custom filters
  

 


          
 


        Page page = this
.userInfoManager.findByPageRequest(pageRequest);  

 


        savePage(page,pageRequest,request);  
 


        return
 
new
 ModelAndView(
"/userinfo/list"
,
"userInfo"
,userInfo);  

 


    }  
 


      
 


    /** 进入新增 */
  

 


    @RequestMapping
(value=
"/new"
)  

 


    public
 ModelAndView _new(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) 
throws
 Exception {  

 


        return
 
new
 ModelAndView(
"/userinfo/new"
,
"userInfo"
,userInfo);  

 


    }  
 


      
 


    /** 显示 */
  

 


    @RequestMapping
(value=
"/{id}"
)  

 


    public
 ModelAndView show(
@PathVariable
 Long id,HttpServletRequest request,HttpServletResponse response) 
throws
 Exception {  

 


        UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
 


        return
 
new
 ModelAndView(
"/userinfo/show"
,
"userInfo"
,userInfo);  

 


    }  
 


      
 


    /** 编辑 */
  

 


    @RequestMapping
(value=
"/{id}/edit"
)  

 


    public
 ModelAndView edit(
@PathVariable
 Long id,HttpServletRequest request,HttpServletResponse response) 
throws
 Exception {  

 


        UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
 


        return
 
new
 ModelAndView(
"/userinfo/edit"
,
"userInfo"
,userInfo);  

 


    }  
 


      
 


    /** 保存新增 */
  

 


    @RequestMapping
(method=RequestMethod.POST)  

 


    public
 ModelAndView create(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) 
throws
 Exception {  

 


        userInfoManager.save(userInfo);  
 


        return
 
new
 ModelAndView(LIST_ACTION);  

 


    }  
 


      
 


    /** 保存更新 */
  

 


    @RequestMapping
(value=
"/{id}"
,method=RequestMethod.PUT)  

 


    public
 ModelAndView update(
@PathVariable
 Long id,HttpServletRequest request,HttpServletResponse response) 
throws
 Exception {  

 


        UserInfo userInfo = (UserInfo)userInfoManager.getById(id);  
 


        bind(request,userInfo);  
 


        userInfoManager.update(userInfo);  
 


        return
 
new
 ModelAndView(LIST_ACTION);  

 


    }  
 


      
 


    /** 删除 */
  

 


    @RequestMapping
(value=
"/{id}"
,method=RequestMethod.DELETE)  

 


    public
 ModelAndView delete(
@PathVariable
 Long id,HttpServletRequest request,HttpServletResponse response) {  

 


        userInfoManager.removeById(id);  
 


        return
 
new
 ModelAndView(LIST_ACTION);  

 


    }  
 


  
 


    /** 批量删除 */
  

 


    @RequestMapping
(method=RequestMethod.DELETE)  

 


    public
 ModelAndView batchDelete(
@RequestParam
(
"items"
) Long[] items,HttpServletRequest request,HttpServletResponse response) {  

 


          
 


        for
(
int
 i = 
0
; i < items.length; i++) {  

 


              
 


            userInfoManager.removeById(items[i]);  
 


        }  
 


        return
 
new
 ModelAndView(LIST_ACTION);  

 


    }  
 


      
 


}
/**
 * @RequestMapping("/userinfo") 具有层次关系,方法级的将在类一级@RequestMapping之一,
 * 如下面示例, 访问方法级别的@RequestMapping("/new"),则URL为 /userinfo/new
 */
@Controller
@RequestMapping("/userinfo")
public class UserInfoController extends BaseSpringController{
	//默认多列排序,example: username desc,createTime asc
	protected static final String DEFAULT_SORT_COLUMNS = null; 
	
	private UserInfoManager userInfoManager;
	
	private final String LIST_ACTION = "redirect:/userinfo";
	
	/** 
	 * 通过spring自动注入
	 **/
	public void setUserInfoManager(UserInfoManager manager) {
		this.userInfoManager = manager;
	}
	
	/** 列表 */
	@RequestMapping
	public ModelAndView index(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) {
		PageRequest<Map> pageRequest = newPageRequest(request,DEFAULT_SORT_COLUMNS);
		//pageRequest.getFilters(); //add custom filters
		
		Page page = this.userInfoManager.findByPageRequest(pageRequest);
		savePage(page,pageRequest,request);
		return new ModelAndView("/userinfo/list","userInfo",userInfo);
	}
	
	/** 进入新增 */
	@RequestMapping(value="/new")
	public ModelAndView _new(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {
		return new ModelAndView("/userinfo/new","userInfo",userInfo);
	}
	
	/** 显示 */
	@RequestMapping(value="/{id}")
	public ModelAndView show(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
		UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
		return new ModelAndView("/userinfo/show","userInfo",userInfo);
	}
	
	/** 编辑 */
	@RequestMapping(value="/{id}/edit")
	public ModelAndView edit(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
		UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
		return new ModelAndView("/userinfo/edit","userInfo",userInfo);
	}
	
	/** 保存新增 */
	@RequestMapping(method=RequestMethod.POST)
	public ModelAndView create(HttpServletRequest request,HttpServletResponse response,UserInfo userInfo) throws Exception {
		userInfoManager.save(userInfo);
		return new ModelAndView(LIST_ACTION);
	}
	
	/** 保存更新 */
	@RequestMapping(value="/{id}",method=RequestMethod.PUT)
	public ModelAndView update(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) throws Exception {
		UserInfo userInfo = (UserInfo)userInfoManager.getById(id);
		bind(request,userInfo);
		userInfoManager.update(userInfo);
		return new ModelAndView(LIST_ACTION);
	}
	
	/** 删除 */
	@RequestMapping(value="/{id}",method=RequestMethod.DELETE)
	public ModelAndView delete(@PathVariable Long id,HttpServletRequest request,HttpServletResponse response) {
		userInfoManager.removeById(id);
		return new ModelAndView(LIST_ACTION);
	}

	/** 批量删除 */
	@RequestMapping(method=RequestMethod.DELETE)
	public ModelAndView batchDelete(@RequestParam("items") Long[] items,HttpServletRequest request,HttpServletResponse response) {
		
		for(int i = 0; i < items.length; i++) {
			
			userInfoManager.removeById(items[i]);
		}
		return new ModelAndView(LIST_ACTION);
	}
	
}

上面是rapid-framework新版本生成器生成的代码,以后也将应用此规则,rest url中增删改查等基本方法与Controller的方法映射规则

/userinfo           => index()  

 


/userinfo/new
       => _new()  

 


/userinfo/{id}      => show()  
 


/userinfo/{id}/edit         => edit()  
 


/userinfo   POST        => create()  
 


/userinfo/{id}  PUT => update()  
 


/userinfo/{id}  DELETE  => delete()  
 


/userinfo   DELETE      => batchDelete()
/userinfo 			=> index()
	/userinfo/new		=> _new()
	/userinfo/{id}		=> show()
	/userinfo/{id}/edit 		=> edit()
	/userinfo 	POST		=> create()
	/userinfo/{id} 	PUT	=> update()
	/userinfo/{id} 	DELETE	=> delete()
	/userinfo 	DELETE		=> batchDelete()

注(不使用 /userinfo/add => add() 方法是由于add这个方法会被maxthon浏览器当做广告链接过滤掉,因为包含ad字符)

4. jsp 编写

<form id=
"userInfo"
 action=
"/springmvc_rest_demo/userinfo/2"
 method=
"post"
>  

 


    <input type="hidden"
 name=
"_method"
 value=
"put"
/>  

 


</form>
<form id="userInfo" action="/springmvc_rest_demo/userinfo/2" method="post">
	<input type="hidden" name="_method" value="put"/>
</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>

相关推荐