SpringMVC学习笔记-REST风格请求实现

RESTful概念及功能

  • RESTful的概念RESTful是 一种资源定位及资源操作的风格,其本身既不是标准也不是协议,而是一种设计风格,可以使得软件整体层次更加分明、代码更加简洁,并且有利于实现缓存等机制。

  • RESTful的功能RESTful主要体现在对软件资源的操作上,把请求方法分为了POST、DELETE、PUT、GET四个部分,各个方法对资源进行操作分别对应了增删改查四个功能,使得代码整体层次分明。

  • RESTful与传统操作资源的对比:传统方式对资源操作形式单一,只有GET、POST两种方式,对于增删改查各种方式往往难以加以区分,且部分参数在url中过于暴露,各种不同参数实现不同效果

    http://127.0.0.1/user/query?id=1 ;查询用户(GET)

    http://127.0.0.1/user/add ;新增用户(POST)

    http://127.0.0.1/user/update ;更新用户(POST)

    http://127.0.0.1/user/delete?id=1 ;删除用户(GET或POST)

    而RESTful确能很好地解决这个问题,可以将增删改查分为POST、DELETE、PUT、GET,并可以通过相同的请求地址实现

    http://127.0.0.1/user/1 ;查询用户(GET)

    http://127.0.0.1/user ;新增用户(POST)

    http://127.0.0.1/user ;更新用户(PUT)

    http://127.0.0.1/user/1 ;删除用户(DELETE)

SpringMVC实现RESTful风格

在传统jsp及大部分浏览器中只能处理POST、GET请求,在SpringMVC中针对这两种请求可以正常处理,并且在该框架控制器 @RequestMapping 注解中提供了method参数用以注明请求方式,可以使同参数请求实现不同功能

@RequestMapping(value="testRest/{id}",method = RequestMethod.POST)
public String testPost(@PathVariable("id") Integer id){
   System.out.println(id);
   return "success";
}


@RequestMapping(value="testRest/{id}",method = RequestMethod.GET)
public String testGet(@PathVariable("id") Integer id){
   System.out.println(id);
   return "success";
}

但对于 DELETEPUT而言则无法通过简单的注解标明实现,因此为了能够使RESTful风格能够正常实现,SpringMVC中通过在Filter过滤器中添加   HiddenHttpMethodFilter类处理来实现对DELETE、PUT的处理, HiddenHttpMethodFilter类源码中对请求的处理如下:

    /** Default method parameter: {@code _method}. */
public static final String DEFAULT_METHOD_PARAM = "_method"; //默认_method规范

private String methodParam = DEFAULT_METHOD_PARAM;


/**
* Set the parameter name to look for HTTP methods.
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

HttpServletRequest requestToUse = request;

if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) { //POST及隐藏域条件判断
String paramValue = request.getParameter(this.methodParam); // 获取name为_method的value
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method); //将name为_method的value设置为新的请求方式
}
}
}

filterChain.doFilter(requestToUse, response); // 返回更改后的request
}

在这段处理代码中,只针对了 POSTWebUtils.ERROR_EXCEPTION_ATTRIBUTE为空的请求进行处理,并且最终返回请求类型为method的value,因此SpringMVC处理DELETE、PUT等附加请求时,需要遵守 Method 为  POST且存在类型为 hiddennamemethodvalue 为指定请求方式的隐藏域约定,默认格式表单如下

<form action="SpringMVCHandler/testRest/1234" method="post">
 <input type="hidden" name="_method" value="DELETE">
 <input type="submit" value="删">
</form>

在经过HiddenHttpMethodFilter过滤器处理后,系统交由controller处理,此时@RequestMapping便可成功识别请求类型,成功完成映射跳转。

@RequestMapping(value="testRest/{id}",method = RequestMethod.DELETE)
public String testDelete(@PathVariable("id") Integer id){
  System.out.println("删"+id);
  return "success";
}

运行中存在的问题及解决方法

在SpringMVC的RESTful风格实现过程中,往往会遇到一系列问题,这里便给出一些常见问题及其解决方法。

  • 请求兼容问题:在按照上述步骤运行时,极大可能会遇到这一问题:

    产生原因:通常这一问题是由于jsp对于DELETE、PUT请求不兼容造成的,在HiddenHttpMethodFilter过滤器将请求处理完成后交由controller处理,但在传统SpringMVC控制器映射处理后,都会返回目标文件名字符串再由配置xml中的视图解析器对返回字符串进行前后缀追加处理,在这过程中DELETE、PUT请求便由jsp处理了,因此便出现了这一问题。

    解决方法:针对这一问题,只需要在控制器映射方法前增加@ResponseBody()注释表明返回的时json而不是jsp即可,使返回时跳过视图解析器,因此不会产生请求兼容错误。

  • 中文乱码问题:在表单中传入中文时,可能会产生乱码问题。

    产生原因:在发送请求时,虽然jsp页面已经设置了charset=“UTF-8”,但其实页面编码类型还是默认的ISO-8859-1,因此在接收时便会产生乱码。

    解决方法:可以参考Java Web中利用Filter过滤器进行编码处理来解决这一问题。

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
       req.setCharacterEncoding("utf-8");
       resp.setCharacterEncoding("utf-8");
       System.out.println("haha");
       chain.doFilter(req, resp);
    }

    但在SpringMvc中使用改该方法解决编码问题时还需要注意过滤先后问题,即如果在web.xml配置文件中HiddenHttpMethodFilter过滤器位于编码过滤器之前,则在编码过滤器处理编码之前先由HiddenHttpMethodFilter过滤器处理,这样依旧会造成乱码问题,因此需要注意配置文件中过滤器映射先后顺序,尽量将编码过滤器位于最上方,并且不要使用注释方法实现过滤器映射。

posted @ 2021-05-27 10:39  sazkuyo  阅读(83)  评论(0编辑  收藏  举报