二、SpringMVC视图
1、ThymeleafView
-
SpringMVC中的视图是View接口,视图的作用是渲染数据,将模型Model中的数据展示给用户
-
SpringMVC中视图的种类有很多,默认有转发视图和重定向视图
-
若使用的视图技术为Thymeleaf,则在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得的是ThymeleafView
-
配置之后,当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发实现视图跳转
@RequestMapping("/") public String index(){ return "index"; }
-
2、转发视图(forward:)
-
SpringMVC中默认的转发视图是InternalResourceView
-
当控制器方法中所配置的视图名称以"forward:"为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,将剩余部分作为最终路径通过转发的方式实现页面跳转
@RequestMapping("/success") public String testSuccess(){ return "success"; } /** * 通过SpringMVC转发视图,将页面跳转到成功页面 * @return */ @RequestMapping("/testForward") public String testForward(){ return "forward:/success"; }
<a th:href="@{/testForward}">通过SpringMVC转发到success页面</a>
3、重定向视图(redirect:)
-
SpringMVC中默认的重定向视图是RedirectView
-
当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向方式实现跳转
-
重定向视图在解析时,会先将redirect:前缀去掉,然后会判断剩余部分是否以/开头,若是则会自动拼接上下文路径
/** * 通过SpringMVC重定向视图,将页面重定向到成功页面 * @return */ @RequestMapping("/testRedirect") public String testRedirect(){ return "redirect:/success"; }
4、视图控制器view-controller
-
当控制器方法中,仅仅用来实现页面跳转(即只需要视图名称,不需要其他参数时),可以将处理器方法使用view-controller标签进行表示
<!-- path:设置处理的请求地址--> <!-- view-controller:设置请求地址所对应的视图名称--> <mvc:view-controller path="/" view-name="index"/> <!-- 当SpringMVC中配置任何一个view-controller时,其他控制器中的请求映射全部失效--> <!-- 此时需要在SpringMVC配置文件中开启mvc注解开发驱动的标签--> <mvc:annotation-driven/>
5、RestFul
-
REST : Representational State Transfer , 表现层资源状态转移
-
RestFul的实现
-
具体来说就是HTTP协议里面,四种表示操作方式的动词: GET 、POST 、PUT 、DELETE
-
具体对应四种操作: GET:获取资源 POST:新建资源 PUT:更新资源 DELETE:删除资源
-
RestFul风格提倡URL地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数而是将要发送给服务器的数据作为URL地址的一部分,以保证风格的一致性
操作 传统方式 RestFul 查询操作 getUserById?id=1 user/1 -->get请求方式 保存操作 saveUser user —>post请求方式 删除操作 deleteUser?id=1 user/1 —>delete请求方式 更新操作 updateUser user/ —>put请求方式
-
6、HiddenHttpMethodFilter
-
浏览器只支持发送get和post请求,若要发送put或delete请求,必须使用SpringMVC中提供的HiddenHttpMethodFilter,该过滤器可以将POST请求转换为DELETE或PUT请求
-
HiddenHttpMethodFilter处理put和delete请求的条件:
- 当前请求方式必须为post
- 当前请求参数必须传递参数_method
-
在web.xml中注册HiddenHttpMethodFilter
<!-- 若要使用PUT或DELETE请求需要配置HiddenHttpMethodFilter过滤器--> <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中提供了两个过滤器CharacterEncodingFilter和HiddenHttpMethodFilter在web.xml中配置,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter
-
在CharacterEncodingFilter通过request.setCharacterEncoding(encoding)方法设置字符集
-
request.setCharacterEncoding(encoding)方法要求前面不能任何有获取请求参数的操作
-
HiddenHttpMethodFilter有一个获取请求方式的操作:
String paramValue = request.getParameter(this.method);
-
-
7、RestFul案例
-
web.xml配置文件
<!-- 配置编码过滤器--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置HiddenHttpMethodFilter--> <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> <!-- 配置核心DispatcherServlet--> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
springMVC.xml配置文件
<!-- 开启扫描包--> <context:component-scan base-package="day01.rest"/> <!-- 配置thymeleaf视图解析器--> <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="order" value="1"/> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <!-- 视图前缀 --> <property name="prefix" value="/WEB-INF/page/"/> <!-- 视图后缀 --> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML5"/> <property name="characterEncoding" value="UTF-8" /> </bean> </property> </bean> </property> </bean> <!-- 配置视图控制器--> <mvc:view-controller path="/" view-name="index"/> <mvc:view-controller path="/toAdd" view-name="addEmployee"/> <!-- 将静态资源交由原始容器解析--> <mvc:default-servlet-handler/> <!-- 开启注解驱动--> <mvc:annotation-driven/>
-
EmployeeController
@Controller public class EmployeeController { @Autowired private EmployeeDao employeeDao; /** * 查询全部员工信息 * @param model * @return */ @GetMapping("/employee") public String getAllEmployee(Model model){ Collection<Employee> employees = employeeDao.getAll(); model.addAttribute("employees",employees); return "employeeList"; } /** * 根据id删除员工信息 * @param id * @return */ @DeleteMapping("/employee/{id}") public String deleteEmployee(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/employee"; } /** * 添加用户 * @param employee * @return */ @PostMapping("/employee") public String addEmployee(Employee employee){ employeeDao.save(employee); return "redirect:/employee"; } /** * 根据id获取员工信息 * @param id * @param model * @return */ @GetMapping("/employee/{id}") public String getEmployeeById(@PathVariable("id") Integer id, Model model){ Employee employee = employeeDao.get(id); model.addAttribute("employee",employee); return "updateEmployee"; } /** * 修改用户信息 * @param employee * @return */ @PutMapping("/employee") public String updateEmployeeById(Employee employee){ employeeDao.save(employee); return "redirect:/employee"; } }
-
addEmployee.html
<form th:action="@{/employee}" method="post"> 员工姓名:<input type="text" name="lastName"> <br> 邮箱<input type="text" name="email"> <br> 性别<input type="radio" name="gender" value="1"> <input type="radio" name="gender" value="2"><br> <input type="submit" value="添加"> <br> </form>
-
employeelist.html
<table id="empTable" border="1" cellspacing="0" style="text-align: center;"> <tr> <th colspan="5">员工信息</th> </tr> <tr> <th>员工编号</th> <th>员工姓名</th> <th>员工邮箱</th> <th>员工性别</th> <th>操作(<a th:href="@{/toAdd}">add</a>)</th> </tr> <tr th:each="employee : ${employees}"> <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 @click.prevent="deleteEmployee" th:href="@{'/employee/' + ${employee.id}}">delete</a> <!-- 或者使用这样方式--> <!-- <a th:href="@{/employee/} + ${employee.id}">delete</a>--> <a th:href="@{'/employee/' + ${employee.id}}">update</a> </td> </tr> </table> <!-- 用来提交delete请求--> <form action="" method="post"> <input type="hidden" name="_method" value="delete"> </form> <script> new Vue({ el : '#empTable', methods : { deleteEmployee(e){ // 获取表单对象 let form = document.querySelector('form'); form.action = e.target.href; //提交表单 form.submit(); } } }) </script>
-
updateEmployee.html
<form th:action="@{/employee}" method="post"> <input type="hidden" name="_method" value="PUT"> <input type="hidden" name="id" th:value="${employee.id}"> 员工姓名: <input type="text" name="lastName" th:value="${employee.lastName}"> <br> 员工邮箱: <input type="text" name="email" th:value="${employee.email}"> <br> 员工性别: <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"> </form>