[SSM]详解 SpringMVC 种常用的视图RESTful 风格编程实现报文信息转换器的应用与 AJAX 和 JSON 的处理

Posted Spring-_-Bear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SSM]详解 SpringMVC 种常用的视图RESTful 风格编程实现报文信息转换器的应用与 AJAX 和 JSON 的处理相关的知识,希望对你有一定的参考价值。

SpringMVC

一、SpringMVC 中的视图

1. SpringMVC 中的视图

  1. SpringMVC 中的视图是 View 接口,视图的作用渲染数据,将模型 Model 中的数据展示给用户
  2. SpringMVC 视图的种类很多,默认有转发视图(InternalResourceView)和重定向视图(RedirectView
  3. 若当前工程引入 JSTL 标签库依赖,转发视图(RedirectView)自动转换为 JstlView
  4. 若在 SpringMVC 的配置文件中配置了 Thymeleaf 的视图解析器,由此视图解析器解析之后所得到的是 ThymeleafView

2. ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被 SpringMVC 配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现页面跳转

@RequestMapping("/testHello")
public String testHello()
    return "hello";

3. InternalResourceView

SpringMVC 中默认的转发视图是 InternalResourceView,当控制器方法中所设置的视图名称以 “forward:” 为前缀时创建 InternalResourceView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 “forward:” 去掉,剩余部分作为最终路径通过转发的方式实现跳转

@RequestMapping("/testForward")
public String testForward()
    return "forward:/testHello";

4. RedirectView

SpringMVC 中默认的重定向视图是 RedirectView,当控制器方法中所设置的视图名称以 “redirect:” 为前缀时创建 RedirectView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 “redirect:” 去掉,剩余部分作为最终路径通过重定向的方式实现跳转(重定向视图在解析时,会先将 redirect: 前缀去掉,然后会判断剩余部分是否以 / 开头,若是则会自动拼接上下文路径)

@RequestMapping("/testRedirect")
public String testRedirect()
    // 重定向到首页
    // return "redirect:/";
    return "redirect:/testHello";

5. 视图控制器 view-controller

当控制器方法中仅仅用来实现页面跳转不需要处理业务逻辑时,可以将控制器方法使用 view-controller 标签进行替代,视图解析器需在 SpringMVC 的配置文件中进行配置

<!-- 当配置一个 view-controller 后,所有控制器的控制方法全部失效,需开启注解驱动 -->
<mvc:annotation-driven/>
<!-- 配置视图控制器,实现页面转发跳转功能 -->
<mvc:view-controller path="/" view-name="index"/>

6. 配置 JSP 的视图解析器

<!-- 配置 JSP 的视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
@RequestMapping("/success")
public String toIndex() 
    return "success";

<a href="$pageContext.request.contextPath/success">go to success</a>

二、RESTful 编程风格示例

7. RESTful 介绍

  1. REST(Representational State Transfer)表现层资源状态转移(是一种编程风格)。一个资源可以由一个或多个URIuniform resource identifer) 来标识,URI 既是资源的名称,也是资源在 Web 上的地址
  2. 统一资源标识符(Uniform Resource Identifier):是一个用于标识某一互联网资源名称的字符串
  3. 统一资源定位符(Uniform Resource Locator):是一个用于标识和定位某一互联网资源名称的字符串
  4. REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性
  5. RESTFul 的实现具体说就是对应 HTTP 协议里四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:
    5.1 GET 用来获取资源
    5.2 POST 用来新建资源
    5.3 PUT 用来更新资源
    5.4 DELETE 用来删除资源
操作传统方式REST风格
查询操作getUserById?id=1user/1 (GET)
保存操作saveUseruser (POST)
删除操作deleteUser?id=1user/1 (DELETE)
更新操作updateUseruser (PUT)

8. 请求方式过滤器处理 GET、POST 以外的请求

目前浏览器只支持 GET 和 POST 请求,需要发送 PUTDELETE 请求时需要在表单中指定方式为 POST 且通过隐藏域设置 name="_method" value="PUT" 的方式实现 PUT 或 DELETE 请求,需在 web.xml 中配置注册 HiddenHttpMethodFilter 请求方式过滤器

<!-- 配置注册 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>

HiddenHttpMethodFilter 实现 PUT 或 DELETE 请求的源码查看(思想:偷梁换柱)

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException 
    HttpServletRequest requestToUse = request;
    // 判断当前请求的请求方式是否是 POST
    if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) 
        // 获取隐藏域中 name="_method" value="" 的属性值
        String paramValue = request.getParameter(this.methodParam);
        // 如果 value 不为空
        if (StringUtils.hasLength(paramValue)) 
            String method = paramValue.toUpperCase(Locale.ENGLISH);
            // 是否是 ALLOWED_METHODS List 集合中的元素(PUT、DELETE、PATCH)
            if (ALLOWED_METHODS.contains(method)) 
                // 偷梁换柱:根据 method 的值创建新的请求方式
                requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
            
        
    

    filterChain.doFilter((ServletRequest)requestToUse, response);

PUT 请求

@PutMapping("/testPut")
public String testPut(String username, String password) 
    System.out.println(username + " " + password + " 信息已修改");
    return "success";

<form method="post" th:action="@/testPut">
    <input type="hidden" name="_method" value="put">
    <input type="text" name="username"><hr/>
    <input type="password" name="password"><hr/>
    <input type="submit">
</form>

9. RESTful 风格 GET 请求获取所有雇员信息

@GetMapping("/employee")
public ModelAndView getAllEmployees() 
    Collection<Employee> employeeList = employeeDao.getAll();
    ModelAndView modelAndView = new ModelAndView();
    for (Employee employee : employeeList) 
        System.out.println(employee);
    
    modelAndView.addObject("employeeList", employeeList);
    modelAndView.setViewName("employee");
    return modelAndView;

<a th:href="@/employee">查询所有员工信息</a>
<!-- 通过 thymeleaf 渲染页面,显示数据 -->
<table border="1" cellpadding="0" cellspacing="0" style="text-align: center">
    <tr>
        <th colspan="5">Employee Info</th>
    </tr>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>operation</th>
    </tr>
    <!-- thymeleaf 遍历 -->
    <tr th:each="employee : $employeeList">
        <td th:text="$employee.id"></td>
        <td th:text="$employee.lastName"></td>
        <td th:text="$employee.email"></td>
        <td th:text="$employee.gender"></td>
        <td>
            <a href="">update</a>
            <a href="">delete</a>
        </td>
    </tr>
</table>

10. RESTful 风格 POST 请求添加员工信息

@PostMapping("/employee")
public String addEmployee(Employee employee) 
    System.out.println(employee);
    employeeDao.save(employee);
    return "redirect:employee";

<form method="post" th:action="@/employee">
  lastName:<input type="text" name="lastName">
  email: <input type="text" name="email">
  gender <input type="text" name="gender">
  <input type="submit">
</form>

11. RESEful 风格 DELETE 请求删除员工信息

@DeleteMapping("employee/id")
public String deleteEmployeeById(@PathVariable("id") Integer id) 
    employeeDao.delete(id);
    return "redirect:/employee";

<form th:action="@'/employee/'+$employee.id" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="delete">
</form>

12. RESTful 风格 PUT 请求修改员工信息

<!-- 1. 发起 GET 请求,跳转到修改员工信息页面 -->
<a th:href="@'/employee/'+$employee.id">update</a>
/**
 * 2. 响应浏览器修改员工信息的请求,根据 id 查询员工数据以实现数据回显
 */
@GetMapping("/employee/id")
public String getEmployeeById(@PathVariable("id") Integer id, Model model)
    Employee employee = employeeDao.get(id);
    model.addAttribute("employee", employee);
    return "employee_update";

<!-- 3. employee_update.html 信息修改回显页面 -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Update Employee</title>
</head>
<body>

<form th:action="@/employee" method="post">
    <input type="hidden" name="_method" value="put">
    <input type="hidden" name="id" th:value="$employee.id">
    lastName:<input type="text" name="lastName" th:value="$employee.lastName"><br>
    email:<input type="text" name="email" th:value="$employee.email"><br>
    <!--
        th:field="$employee.gender" 可用于单选框或复选框的回显
        若单选框的 value 和 employee.gender 的值一致,则添加 checked="checked" 属性
    -->
    gender:<input type="radio" name="gender" value="1" th:field="$employee.gender">male
    <input type="radio" name="gender" value="0" th:field="$employee.gender">female<br>
    <input type="submit" value="update"><br>
</form>

</body>
</html>
/**
 * 4. 响应客户端的信息修改请求,修改成功跳转到信息显示页面 
 */
@PutMapping("/employee")
public String updateEmployee(Employee employee)
    employeeDao.save(employee);
    return "redirect:/employee";

13. 配置默认 Servlet 放行静态资源

<!-- 处理静态资源,若只设置该标签,则只能访问静态资源,其他请求无法访问。此时必须开启注解驱动 <mvc:annotation-driven/> 以解决问题 -->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>

三、信息报文转换

14. HttpMessageConverter 报文转换器

HttpMessageConverter(报文信息转换器)可以实现将请求报文转换为 Java 对象,或将 Java 对象转换为响应报文。HttpMessageConverter 提供了两个注解和两种类型:@RequestBody@ResponseBodyRequestEntityResponseEntity 以实现数据间的转换

15. @RequestBody 获取请求体内容

@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody)
    // Output:username=admin&password=123456
    System.out.println("requestBody:"+requestBody);
    return "success";

<form th:action="@/testRequestBody" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type=以上是关于[SSM]详解 SpringMVC 种常用的视图RESTful 风格编程实现报文信息转换器的应用与 AJAX 和 JSON 的处理的主要内容,如果未能解决你的问题,请参考以下文章

[SSM]详解 SpringMVC 中的拦截器异常处理器与执行流程及两种配置方式

SpringMVC+Spring+Mybatis(SSM~Demo)

SpringMVC+Spring+Mybatis(SSM~Demo)

SpringMVC+Spring+Mybatis(SSM~Demo)

SpringMVC详解------SSM三大框架整合之登录功能实现

spring mvc 常用注解详解