Spring MVC自定义数据类型转换器、Spring MVC与RESTful的集成

Spring MVC自定义数据类型转换器

1、创建 DateConverter 类,并实现 org.springframework.core.convert.converter.Converter 接口,
这样它就成为了⼀个自定义数据类型转换器,需要指定泛型 <String,Date>,表示将 String 类型转为Date 类型。

package com.southwind.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String,Date> {
 private String pattern;
 public DateConverter(String pattern){
 this.pattern = pattern;
 }
 @Override
 public Date convert(String s) {
 SimpleDateFormat simpleDateFormat = new
SimpleDateFormat(this.pattern);
 try {
 return simpleDateFormat.parse(s);
 } catch (ParseException e) {
 e.printStackTrace();
 }
 return null;
 }
}

2、在 springmvc.xml 中配置 conversionService bean,这个 bean 是
org.springframework.context.support.ConversionServiceFactoryBean 的实例化对象,同时 bean 中必须包含⼀个 converters 属性,在其中注册所有需要使用的自定义转换器。

<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
 <property name="converters">
 <list>
 <bean class="com.southwind.converter.DateConverter">
 <constructor-arg type="java.lang.String" value="yyyy-MM-dd">
</constructor-arg>
 </bean>
 </list>
 </property>
</bean> <mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>

Student

package com.southwind.entity;
import lombok.Data;
@Data
public class Student {
 private Integer id;
 private String name;
 private Integer age; }

StudentConverter

package com.southwind.converter;
import com.southwind.entity.Student;
import org.springframework.core.convert.converter.Converter;
public class StudentConverter implements Converter<String, Student> {
 @Override
 public Student convert(String s) {
 String[] args = s.split("-");
 Student student = new Student();
 student.setId(Integer.parseInt(args[0]));
 student.setName(args[1]);
 student.setAge(Integer.parseInt(args[2]));
 return student;
 }
}

Handler

@RequestMapping("/student")
@ResponseBody
public Student student(Student student, HttpServletResponse response){
 response.setCharacterEncoding("UTF-8");
 return student; }

如果需要将业务数据转换成 JSON,中文乱码需要在业务方法中通过设置 response 的编码格式来解决,springmvc.xml 中的 bean 不起作用,如果不需要将业务数据转成 JSON,springmvc.xml 的配置可以中文乱码的处理。

<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
 <property name="converters">
 <list>
 <bean class="com.southwind.converter.DateConverter">
 <constructor-arg type="java.lang.String" value="yyyy-MM-dd">
</constructor-arg>
 </bean>
 <bean class="com.southwind.converter.StudentConverter"></bean>
 </list>
 </property>
</bean> <mvc:annotation-driven conversion-service="conversionService">
 <!-- 消息转换器 -->
 <mvc:message-converters>
 <bean
class="org.springframework.http.converter.StringHttpMessageConverter">
 <property name="supportedMediaTypes" value="text/json;charset=UTF-8">
</property>
 </bean>
 <!-- fastjson -->
 <bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4">
</bean>
 </mvc:message-converters>
</mvc:annotation-driven>

Spring MVC与RESTful的集成

什么是 RESTful?
RESTful 是当前比较流⾏的⼀种互联网软件架构模型,通过统一的规范完成不同终端的数据访问和交互,REST 全称是 Representaional State Transfer(资源表现层状态转换)。

RESTful 的优点:结构清晰、有统⼀的标准、扩展性好。

Resources
资源指的是网络中的某个具体文件,类型不限,可以是文本、图片、视频、音频、数据流等,是网络中真实存在的⼀个实体。如何获取它?可以通过统⼀资源定位符找到这个实体,URI,每个资源都有一个特定的 URI,通过 URI 就可以找到⼀个具体的资源。

Pepresentation
资源表现层,资源的具体表现形式,例如⼀段文字,可以使用 TXT、HTML、XML、JSON 等不同的形式来来描述它。

State Transfer
状态转化是指客户端和服务端之间的数据交互,因为 HTTP 请求不能传输数据的状态,所有的状态都保存在服务端,如果客户端希望访问服务端的数据,就需要使其发生状态改变,同时这种状态转化是建立在表现层,完成转换就表示资源的表现形式发生了改变。

RESTful 的概念比较抽象,特点有两个:
1、URL 传参更加简洁
传统形式 URL:http://localhost:8080/findById?id=1
RESTful URL:http://localhost:8080/findById/1

2、完成不同终端之间的资源共享,RESTful 提供了⼀套规范,不同终端之间只需要遵守该规范,就可以实现数据交互。

RESTful 具体来讲就是四种表现形式,HTTP 协议中四种请求类型(GET、POST、PUT、DELETE)分别表示四种常规操作,CRUD
GET 用来获取资源

POST 用来创建资源

PUT 用来修改资源

DELETE 用来删除资源

在这里插入图片描述
两个终端要完成数据交互,基于 RESTful 的方式,增删改查操作分别需要使用不同的 HTTP 请求类型来访问。

传统的 Web 开发中,from 只支持 GET 和 POST,不支持 DELETE 和 PUT,如何解决?通过添加HiddenHttpMethodFilter 过滤器,可以将 POST 请求转为 PUT 或者 DELETE。

HiddenHttpMethodFilter 的实现原理

HiddenHttpMethodFilter 检测请求参数重是否包含 _method 参数,如果包含则取出它的值,并且判断请求类型之后完成请求类型的转换,然后继续传递。
在这里插入图片描述
实现步骤
1、在 form 表单中添加隐藏域标签,name 为 _method,value 为 DELETE/PUT。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html> <head>
 <title>Title</title>
</head> <body>
 <form action="/rest/update" method="post">
 <input type="hidden" name="_method" value="PUT"/>
 <input type="submit" value="提交"/>
 </form>
</body>
</html>

2、web.xml 中配置 HiddenHttpMethodFilter。

<!-- HiddenHttpMethodFilter -->
<filter>
 <filter-name>HiddenHttpMethodFilter</filter-name>
 <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filterclass>
</filter> <filter-mapping>
 <filter-name>HiddenHttpMethodFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

3、Handler

@PutMapping("/update")
@ResponseBody
public String update(HttpServletResponse response){
 response.setCharacterEncoding("UTF-8");
 return "已接收到PUT请求"; }
@DeleteMapping("/delete")
@ResponseBody
public String delete(HttpServletResponse response){
 response.setCharacterEncoding("UTF-8");
 return "已接收到DELETE请求"; }

需求分析

添加课程,成功则返回全部课程信息。
查询课程,通过 id 查询对应课程信息。
修改课程,成功则返回修改之后的全部课程信息。
删除课程,成功则返回删除之后的全部课程信息。

代码实现

1、JSP
添加课程:add.jsp
修改课程:edit.jsp
课程展示:index.jsp

2、Course 实体类

public class Course{
 private Integer id;
 private String name;
 private Double price; }

3、CourseRepository

package com.southwind.repository;
import com.southwind.entity.Course;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class CourseRepository {
 private Map<Integer, Course> courseMap;
 public CourseRepository() {
 courseMap = new HashMap<>();
 courseMap.put(1,new Course(1,"Java基础",Double.parseDouble("500")));
 courseMap.put(2,new Course(2,"Java⾼级",Double.parseDouble("600")));
 courseMap.put(3,new Course(3,"企业级框架",Double.parseDouble("700")));
 }
 public Collection<Course> findAll(){
 return courseMap.values();
 }
 public Course findById(Integer id){
 return courseMap.get(id);
 }
 public void saveOrUpdate(Course course){
 courseMap.put(course.getId(),course);
 }
 public void deleteById(Integer id){
 courseMap.remove(id);
 }
}

4、CourseController

package com.southwind.controller;
import com.southwind.entity.Course;
import com.southwind.repository.CourseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/course")
public class CourseController {
 @Autowired
 private CourseRepository courseRepository;
 @PostMapping("/save")
 public String save(Course course){
 courseRepository.saveOrUpdate(course);
 return "redirect:/course/findAll";
 }
 @GetMapping("/findAll")
 public ModelAndView findAll(){
 ModelAndView modelAndView = new ModelAndView();
 modelAndView.setViewName("index");
 modelAndView.addObject("list",courseRepository.findAll());
 return modelAndView;
 }
 @DeleteMapping("/deleteById/{id}")
 public String deleteById(@PathVariable("id") Integer id){
 courseRepository.deleteById(id);
 return "redirect:/course/findAll";
 }
 @GetMapping("/findById/{id}")
 public ModelAndView findById(@PathVariable("id") Integer id){
 ModelAndView modelAndView = new ModelAndView();
 modelAndView.setViewName("edit");
 modelAndView.addObject("courser",courseRepository.findById(id));
 return modelAndView;
 }
 @PutMapping("/update")
 public String update(Course course){
 courseRepository.saveOrUpdate(course);
 return "redirect:/course/findAll";
 }
}

5、JSP
save.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html> <head>
 <title>Title</title>
</head> <body>
 <form action="/course/save" method="post">
 <table>
 <tr>
 <td>课程编号:</td>
 <td>
 <input type="text" name="id"/>
 </td>
 </tr>
 <tr>
 <td>课程名称:</td>
 <td>
 <input type="text" name="name"/>
 </td>
 </tr>
 <tr>
 <td>课程价格:</td>
 <td>
 <input type="text" name="price"/>
 </td>
 </tr>
 <tr>
 <td>
 <input type="submit" value="提交"/>
 </td>
 <td>
 <input type="reset" value="重置"/>
 </td>
 </tr>
 </table>
 </form>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<html> <head>
 <title>Title</title>
</head> <body>
 <table>
 <tr>
 <th>编号</th>
 <th>名称</th>
 <th>价格</th>
 <th>操作</th>
 </tr>
 <c:forEach items="${list}" var="course">
 <tr>
 <td>${course.id}</td>
 <td>${course.name}</td>
 <td>${course.price}</td>
 <td>
 <form action="/course/deleteById/${course.id}"
method="post">
 <input type="hidden" name="_method" value="DELETE"/>
 <input type="submit" value="删除"/>
 </form>
 <a href="/course/findById/${course.id}">修改</a>
 </td>
 </tr>
 </c:forEach>
 </table>
</body>
</html>

edit.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html> <head>
 <title>Title</title>
</head> <body>
 <form action="/course/update" method="post">
 <input type="hidden" name="_method" value="PUT"/>
 <table>
 <tr>
 <td>编号:</td>
 <td>
 <input type="text" name="id" readonly
value="${courser.id}"/>
 </td>
 </tr>
 <tr>
 <td>名称:</td>
 <td>
 <input type="text" name="name" value="${courser.name}"/>
 </td>
 </tr>
 <tr>
 <td>价格:</td>
 <td>
 <input type="text" name="price" value="${courser.price}"/>
 </td>
 </tr>
 <tr>
 <td>
 <input type="submit" value="修改"/>
 </td>
 </tr>
 </table>
 </form>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走不尽的心路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值