springMVC REST 风格

rest风格的定义  REST 即 Reoresentational State Transfer.资源现象表层状态转化。是目前最流行的一种互联网软件架构。
 
表现层:把资源具体呈现出来的形式,叫做他的表现层(Representation).比如,文本可以使用TXT格式表现。也可以yongHTML格式,xml格式,Json格式。
 
状态转化:没发送一个请求代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生  状态转化(State Transfer)。而这种转化数建立在表现层之上的,所以就是表现层状态转化。具体说,及时HTTP协议里面四个表示操作方式的动词:GET,POST,PUT,DELETE.分别对应四个基本操作。GET用来获取资源,POST用来新建资源,PUT用来更新资源,Delete用来删除
 
<!-- 配置HiddenHttpMethodFilter过滤器实现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>
    <url-pattern>/*</url-pattern>
</filter-mapping>
 
 
 
springMVC REST 风格
 
 
springMVC REST 风格
 
 
 
由于HTML只支持GET和POST请求,如果需要使用PUT和DELETE请求,需要做如下修改:添加过滤器HiddenHttpMethodFilter 发送POST请求 需要在POST请求中添加一个隐藏域,name="_method",value="PUT/DELETE"。
 
可以得知RESTful风格的特点如下:
(1)每一个URI代表一种资源,独一无二;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
值得注意的是RESTful风格的RUI中是不包含动词的。
阮一峰的博客对RESTful很清楚的解释清楚。但是RESTful风格的优势是什么?
REST的全称在文章里已经有了,其中的核心是第一个字母R,即资源(Resource)
REST的核心在于,当你设计一个系统的时候,资源是第一位的考虑,你首先从资源的角度进行系统的拆分、设计,而不是像以往一样以操作为角度来进行设计
我们平时搞系统是这样的:
1. 有新建用户功能
2. 新建用户需要一个URL
3. 往这个URL发送的数据要定义好
4. 开始写后端和前端
这是以操作为第一位的设计方法,首先我们确认了一个操作,然后围绕这个操作把周边需要的东西建设好,这种方式当然可以架构出一个系统,甚至是一个好系统,但是偶尔会有些问题:
1. 操作之间是会有关联,你的设计容易变成“第2个操作要求第1个操作进行过”,这种关系多起来你的系统就乱了
2. 你的URL设计会缺乏一致性
3. 操作通常被认为是有副作用(Side Effect)的,所以很少有人基于操作去设计缓存之类的东西
基于这些问题,我们的另一种方法是基于资源的角度来搞,但这个太难了我至今其实没想明白到底是怎么搞的,但基于资源会有一些好处:
1. 各个资源虽然可能有关联,但依旧是能够简单地切掉这些关联导致相互独立的,所以不会有非常乱的耦合性
2. 对资源的操作就这么几种,所以很容易设计一致的URL
3. 我们明白对资源的读操作是无副作用的,所以能玩缓存
但其实现在99%说自己是REST的情况,就是改了个URL风格,用了用PUT和POST,根本没有明白REST是一个什么,也没有按REST的思想来指导设计
要说自己会REST,我觉得至少回答2个问题:
1. 对于用户登录和用户退出这两个业务需求,REST指导下的架构和设计如何满足
2. 批量的删除、修改、新增如何满足
它的优势或优点。
首先,REST规范:
* 强调HTTP应当以资源为中心,并且规范了资源URI的风格;
* 规范了HTTP请求动作(PUT,POST等)的使用,具有对应的语义;
遵循REST规范的Web应用将会获得下面好处:
* URL具有很强可读性的,具有自描述性;
* 资源描述与视图的松耦合;
* 可提供OpenAPI,便于第三方系统集成,提高互操作性;
* 如果提供无状态的服务接口,可提高应用的水平扩展性;
下面再详细说明一下REST。了解事物,分三步走:
【基本概念】
REST是一种软件架构模式。核心概念包括:
资源(Resource):在REST中,资源可以简单的理解为URI,表示一个网络实体。比如,/users/1/name,对应id=1的用户的属性name。
既然资源是URI,就会具有以下特征:名词,代表一个资源;它对应唯一的一个资源,是资源的地址。
表现(Representation):是资源呈现出来的形式,比如上述URI返回的HTML或JSON,包括HTTP Header等;
【实践】
怎么用呢?不同的Server端框架提供了各种解决方案。比如JavaEE中的开箱即用的Spring-MVC。
但实践过程中,你自然会碰到一些需要思考的问题:
1)如何定义资源:一般对应数据库实体(在传统的关系型数据库中)。
2)需要对HTTP协议更多的理解
URL格式:协议://域名/路径?查询#HASH,实际的一个HTTP请求,还会包括Header(含Cookie、Method等)
资源的URI格式:协议://域名/路径,它只是URL的子集,表征一个资源实体。比如,http://a.com/users/1
恰当地理解和返回Http Status(状态码)。200=成功,404=资源不存在,500=服务器端错误等等。
3)REST操作
一般资源操作只有新增、删除、查询、更新,对应HTTP协议中四类请求:POST、DELETE、GET、PUT。其中,后三个操作是幂等的。(什么是幂等?)
查询资源时,更多的参数,比如分页、排序、过滤条件,一般都会放在URL的查询部分(Query String)。
新增、更新资源,关于资源实体的内容,一般放在请求体(Request Body)中。
实际发送请求,还需要有动词,表示对该资源执行什么样的操作。那么超出这个范围的操作该如何扩展
REST操作返回什么内容?对于删除、新增、更新等操作,通常是返回操作是否成功的标识;如果失败,需要返回错误代码和消息,方便客户端做进一步处理。如果是查询操作,通常包含实体或者实体列表。
在最佳实践中,应当还应该返回与此操作相关的其他操作。比如,查询得到实体的响应中,应包含该实体的删除、更新操作的地址。
 
请求和返回的Body,采用什么格式?常见的格式包括XML/JSON/HTML。
 
 
 
不是很规范  应该将数据的处理跟PUT这些方法分开写比较好
 
package com.znsd.action;
 
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.znsd.hibernate.bean.StaffBean;
import com.znsd.serlvce.StaffSerlvce;
import com.znsd.serlvce.impl.StaffServlceImpl;
 
@Controller
@RequestMapping("/action")
public class StaffController {
 
    @Autowired
    private StaffSerlvce staffSerlvce;
 
    @RequestMapping(value="/staff",method= {RequestMethod.POST})
    public String add(HttpServletRequest request) {
        System.out.println("-------------------------------ADD");
        String staffId=request.getParameter("staff_id");
        String staffName=request.getParameter("staff_name");
        String staffAge=request.getParameter("staff_age");
        String staffTime=request.getParameter("role_time");
        System.out.println(staffId+"----"+staffTime);
        StaffBean staff=new StaffBean();
        staff.setStaffId(Integer.parseInt(staffId));
        staff.setStaAge(Integer.parseInt(staffAge));
        staff.setStaName(staffName);
        staff.setJoinTime(staffTime);
        staffSerlvce.add(staff);
        return "../huodong_ChaoGuan11.html";
    }
    
    @ResponseBody
    @RequestMapping(value="/staff",method= {RequestMethod.DELETE})
    public String delete(Integer oldnum) {
        StaffBean staff=new StaffBean();
        staff.setStaffId(oldnum);
        System.out.println("StaffController.delete()======================="+oldnum);
        staffSerlvce.delete(staff);
        return "true";
    }
    
    @ResponseBody
    @RequestMapping(value="staff",method= {RequestMethod.GET})
    public List<StaffBean> query() {
        System.out.println("--------------");
        List<StaffBean> list=staffSerlvce.query();
        System.out.println(list);
        return list;
    }
 
    @RequestMapping(value="/staff",method= {RequestMethod.PUT})
    public String update(HttpServletRequest request) {
        String staffId=request.getParameter("role_id");
        String staffName=request.getParameter("role_name");
        String staffAge=request.getParameter("role_age");
        String staffTime=request.getParameter("role_time");
        
        System.out.println("StaffServlet.doPost()"+staffId);
        System.out.println("StaffServlet.doPost()"+staffName);
        System.out.println("StaffServlet.doPost()"+staffAge);
        StaffBean staff=new StaffBean();
        staff.setStaffId(Integer.parseInt(staffId));
        staff.setStaAge(Integer.parseInt(staffAge));
        staff.setStaName(staffName);
        staff.setJoinTime(staffTime);
        staffSerlvce.update(staff);
        return "redirect:/huodong_ChaoGuan11.html";
    }
    
    public List<StaffBean> queryName(String queryAll){
        List<StaffBean> list=staffSerlvce.queryName(queryAll);
        return list;
    }
 
    public List<StaffBean> queryTime(String queryTime) {
        List<StaffBean> listTime=staffSerlvce.queryName(queryTime);
        return listTime;
    }
    
}
 
页面的请求
 
    /* delete */
    function deleteRole(oldnum){
        var date={oldnum:oldnum};
        $.post("/Work3/action/staff.do?_method=DELETE",date,function(result){
            //window.location.href="/Work3/huodong_ChaoGuan11.html";
            console.info(result);
            location.reload();
        })
    }