`

SpringMVC + RESTful URL

 
阅读更多
Spring REST是什么? http://blog.csdn.net/pilou5400/article/details/6096861
Spring3.0实现REST实例 http://blog.csdn.net/leecho571/article/details/6559758
spring 3.0 应用springmvc 构造RESTful URL 详细讲解 http://badqiu.iteye.com/blog/473301,文章里面的UrlRewriteFilter功能,springMVC自己已经实现,就是 <mvc:resources location="/image/" mapping="/image/**"/>同能同等。
springmvc定制REST风格 以及 与JSR303 Bean校验整合 http://www.cnblogs.com/dennisit/archive/2013/04/13/3019391.html
用 UrlRewriteFilter 实现 URL 重写 http://panyongzheng.iteye.com/blog/1901290
Spring MVC静态资源处理——<mvc:resources /> ||<mvc:default-servlet-handler /> http://perfy315.iteye.com/blog/2008763


拦截器:
SpringMVC中使用Interceptor拦截器 http://panyongzheng.iteye.com/blog/2084629
基于注解风格的Spring-MVC的拦截器 http://blog.csdn.net/li_xiao_ming/article/details/9704337

springmvc的resturl是通过@RequestMapping 及@PathVariable annotation提供的
@RequestMapping 用法详解之地址映射  http://blog.sina.com.cn/s/blog_72827fb10101pl9i.html
@RequestParam @RequestBody @PathVariable 等参数绑定注解详解 http://panyongzheng.iteye.com/blog/1797446



传统的Web应用大都是B/S架构,它包括了如下一些规范:
1. 客户-服务器
    这种规范的提出,改善了用户接口跨多个平台的可移植性,并且通过简化服务器组件,改善了系统的可伸缩性。最为关键的是通过分离用户接口和数据存储这两个关注点,使得不同用户终端享受相同数据成为了可能。

2. 无状态性
    无状态性是在客户-服务器约束的基础上添加的又一层规范。他要求通信必须在本质上是无状态的,即从客户到服务器的每个request都必须包含理解该 request所必须的所有信息。这个规范改善了系统的可见性(无状态性使得客户端和服务器端不必保存对方的详细信息,服务器只需要处理当前 request,而不必了解所有的request历史),可靠性(无状态性减少了服务器从局部错误中恢复的任务量),可伸缩性(无状态性使得服务器端可以很容易的释放资源,因为服务器端不必在多个request中保存状态)。同时,这种规范的缺点也是显而易见得,由于不能将状态数据保存在服务器上的共享上下文中,因此增加了在一系列request中发送重复数据的开销,严重的降低了效率。

3.缓存
    为了改善无状态性带来的网络的低效性,我们填加了缓存约束。缓存约束允许隐式或显式地标记一个response中的数据,这样就赋予了客户端缓存 response数据的功能,这样就可以为以后的request共用缓存的数据,部分或全部的消除一部分交互,增加了网络的效率。但是用于客户端缓存了信息,也就同时增加了客户端与服务器数据不一致的可能,从而降低了可靠性。

B/S架构的优点是其部署非常方便,但在用户体验方面却不是很理想。为了改善这种情况,
我们引入了REST。


REST在原有的架构上增加了三个新规范:统一接口,分层系统和按需代码。
1.统一接口
    REST 架构风格的核心特征就是强调组件之间有一个统一的接口,这表现在REST世界里,网络上所有的事物都被抽象为资源,而REST就是通过通用的链接器接口对资源进行操作。这样设计的好处是保证系统提供的服务都是解耦的,极大的简化了系统,从而改善了系统的交互性和可重用性。并且REST针对Web的常见情况做了优化,使得REST接口被设计为可以高效的转移大粒度的超媒体数据,这也就导致了REST接口对其它的架构并不是最优的。

2.分层系统
    分层系统规则的加入提高了各种层次之间的独立性,为整个系统的复杂性设置了边界,通过封装遗留的服务,使新的服务器免受遗留客户端的影响,这也就提高了系统的可伸缩性。

3.按需代码
    REST允许对客户端功能进行扩展。比如,通过下载并执行applet或脚本形式的代码,来扩展客户端功能。但这在改善系统可扩展性的同时,也降低了可见性。所以它只是REST的一个可选的约束。

REST的设计准则
    REST架构是针对Web应用而设计的,其目的是为了降低开发的复杂性,提高系统的可伸缩性。REST提出了如下设计准则:
   1. 网络上的所有事物都被抽象为资源(resource);
   2. 每个资源对应一个唯一的资源标识符(resource identifier);
   3.通过通用的连接器接口(generic connector interface)对资源进行操作;
   4. 对资源的各种操作不会改变资源标识符;
   5. 所有的操作都是无状态的(stateless)。 

   REST中的资源所指的不是数据,而是数据和表现形式的组合,比如“最新访问的10位会员”和“最活跃的10为会员”在数据上可能有重叠或者完全相同,而由于他们的表现形式不同,所以被归为不同的资源,这也就是为什么REST的全名是Representational State Transfer的原因。资源标识符就是URI(Uniform Resource Identifier),不管是图片,Word还是视频文件,甚至只是一种虚拟的服务,也不管你是xml格式,txt文件格式还是其它文件格式,全部通过 URI对资源进行唯一的标识。
   REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现。以往的Web开发大多数用的都是Http协议中的GET和 POST方法,对其他方法很少使用,这实际上是因为对Http协议认识片面的理解造成的。Http不仅仅是一个简单的运载数据的协议,而是一个具有丰富内涵的网络软件的协议。他不仅仅能对互联网资源进行唯一定位,而且还能告诉我们如何对该资源进行操作。Http把对一个资源的操作限制在4个方法以内: GET, POST,PUT和DELETE,这正是对资源CRUD操作的实现。由于资源和URI是一一对应的,执行这些操作的时候URI是没有变化的,这和以往的 Web开发有很大的区别。正由于这一点,极大的简化了Web开发,也使得URI可以被设计成更为直观的反映资源的结构,这种URI的设计被称作 RESTful的URI。这位开发人员引入了一种新的思维方式:通过URL来设计系统结构。当然了,这种设计方式对一些特定情况也是不适用的,也就是说不是所有的URI都可以RESTful的。
    REST 之所以可以提高系统的可伸缩性,就是因为它要求所有的操作都是无状态的。由于没有了上下文(Context)的约束,做分布式和集群的时候就更为简单,也可以让系统更为有效的利用缓冲池(Pool)。并且由于服务器端不需要记录客户端的一系列访问,也减少了服务器端的性能。 
    REST 无状态的
    每一个来自客户端的request必须包含所有必要的信息,即不能从服务器端获得任何保存的上下文信息。
    REST 的 “客户机-无状态-服务器” 约束禁止在服务器上保存会话状态。符合这一约束进行设计
   1,可以提高系统的可靠性和可伸缩性。它不需要昂贵的维护和支持费用,因为状态并不在服务器上维护。
   2,可以进行资源缓存。Web的高速缓存既可以驻留在客户主机中,也可以驻留在中间网络高速缓存服务器主机中
    安全机制
    REST使用了简单有效的安全模型。REST中很容易隐藏某个资源,只需不发布它的U RI;而在资源上也很容易使用一些安全策略,比如可以在每个 URI 针对 4个通用接口设置权限;再者,以资源为中心的 Web服务是防火墙友好的,因为 GET的 意思就是GET, P UT 的意思就是PUT,管理员可以通过堵塞非GET请求把资源设置为只读的,而现在的基于RPC 模型的 SOAP 一律工作在 HTTP 的 POST上。
使用 SOAP RPC模型,要访问的对象名称藏在方法的参数中,因此需要创建新的安全模型。



例子源码:
web.xml
==========================================
<?xml version="1.0" encoding="UTF-8"?>
<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_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <display-name>Archetype Created Web Application</display-name>

    <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>

    <!-- 该servlet为tomcat,jetty等容器提供,将静态资源映射从/改为/static/目录,如原来访问 http://localhost/foo.css ,现在http://localhost/static/foo.css -->
   <!-- <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/static/*</url-pattern>
    </servlet-mapping>-->

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <!-- URL重写filter,用于将访问静态资源http://localhost/foo.css 转为http://localhost/static/foo.css -->
    <!--<filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>-->
    <!-- 浏览器不支持put,delete等method,由该filter将/blog?_method=delete转换为标准的http 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>




springmvc-servlet.xml
===============================================
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    <mvc:annotation-driven/>

    <!--        静态资源配置 -->
    <mvc:resources location="/resources/" mapping="/resources/**"/>
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/image/" mapping="/image/**"/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="requestContextAttribute" value="rc"/>
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>





controller: RESTful URL风格controller
==================================================
package com.controller;

import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by Administrator on 14-6-13.
 */
@Controller
@RequestMapping("/rsu")
public class RestFulUrlController {


    @RequestMapping(method = RequestMethod.GET, value = "/-1/add")
    public ModelAndView add(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("message","This is a test message[add]");
        return view;
    }

    @RequestMapping(method = RequestMethod.POST, value = "/{id}/insert")
    public ModelAndView insert(@PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("message","This is a test message[insert]");
        return view;
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/update")
    public ModelAndView update(@PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("message","This is a test message[update]");
        return view;
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}/del")
    public ModelAndView del(@PathVariable("id") Long id,HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("message","This is a test message[del]");
        return view;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}/detail")
    public ModelAndView detail(@PathVariable("id") Long id,HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("message","This is a test message[detail]");
        return view;
    }
}





View:RESTful URL风格URI
============================================
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SpringRestfulUrl</title>
    <link rel="stylesheet" href="/SpringRestfulUrl/css/main.css"/>
</head>
<body>

<a href="/SpringRestfulUrl/rsu/-1/add">add-get方式</a>
<br>
<a href="/SpringRestfulUrl/rsu/10/detail">detail-get方式</a>

<form action="/SpringRestfulUrl/rsu/10/insert" method="post">
    <button type="submit">insert-post方式</button>
</form>
<form action="/SpringRestfulUrl/rsu/10/update" method="post">
    <input type="hidden" name="_method" value="put"/>
    <button type="submit">update-put方式</button>
</form>
<form action="/SpringRestfulUrl/rsu/10/del" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <button type="submit">delete-delete方式</button>
</form>
<div>${message}</div>
<img src="/SpringRestfulUrl/image/01.png">
</body>
</html>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics