源代码:
链接:https://pan.baidu.com/s/1Lxb-riH–YQNIy3c0i8pFA
提取码:y3aq
文档地址:https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/
一、基本环境
- jdk 1.8
- IDEA 2019
- Maven 3.6.3
- Tomcat 9.0
二、准备工作
2.1 建立Maven工程
2.1.1 打开IDEA,选择【Create New Project】–> 【Maven】–> 【勾选Create from archetype】–>【maven-archetype-webapp】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yv4oukqV-1602078341144)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/1.jpg)]
2.1.2 给项目命名,然后一直下一步:【Next】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HjcwL14w-1602078341146)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/2.jpg)]
2.2 项目的基本结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akIdZ3Mf-1602078341149)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/3.jpg)]
2.3 导入基础的依赖
<!--spring核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<!--SpringMVC依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<!--Servlet 依赖,这里指定由Tomcat提供-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
三、编写配置类
3.1 创建一个 WebAppConfig 配置类,作为 SpringMVC 的配置类
/**
* @Configuration 标识该类是一个配置类
* @EnableWebMvc 相当于在xml中配置 <mvc:annotation-driven/>
* WebMvcConfigurerAdapter 继承该抽象类相当于指定该配置类是SpringMVC配置类
*/
@Configuration
@EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter {
}
3.2 创建一个RootConfig 配置类,作为 Spring 的配置类
@Configuration
public class RootConfig {
}
3.3 创建一个 MyWebAppInitializer 作为核心启动类,用于加载 SpringMVC 和 Spring 的配置类
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// 这里指定 Spring 的核心配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
// 这里指定 SpringMVC 的核心配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebAppConfig.class};
}
// 这里指定 DispatcherServlet 的拦截规则,我们这里拦截所有请求
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
四、编写测试项目
4.1 编写Controller
4.1.1 这里编写一个 UserController
@Controller
public class UserController {
@Autowired
private IUserService service;
@RequestMapping(value = "/user")
@ResponseBody
public String getUserById(@RequestParam(value = "id", defaultValue = "0", required = false) int id) {
User user = service.getUserById(id);
return user.toString();
}
}
4.1.2 我们需要将 UserController 扫描到容器中
这里我们使用@ComponentScan
将组件扫描进 SpringMVC 容器,因此我们需要在WebAppConfig
配置类添加该注解
@ComponentScan(basePackages = "com.shph.controller")
4.2 编写 Service
4.2.1 这里编写一个 IUserService 接口并完成其实现类
// 接口类
public interface IUserService {
User getUserById(int id);
}
// 实现类
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private IUserDao userDao;
@Override
public User getUserById(int id) {
return userDao.selectUserById(id);
}
}
4.2.2 将 UserServiceImpl 扫描到容器中
这里我们将 UserServiceImpl 扫描到 Spring 容器中,因此我们需要在 RootConfig
配置组件扫描注解
@ComponentScan(basePackages = "com.shph", excludeFilters = @ComponentScan.Filter({Controller.class}))
4.2 编写 Dao
4.2.1 这里编写一个 IUserDao 接口并完成其实现类
// 接口类
public interface IUserDao {
User selectUserById(int id);
}
// 实现类
@Repository
public class UserDaoImpl implements IUserDao {
// 这里向使用 Map 提供数据,暂时不去数据库查询数据
private static Map<Integer, User> map = new HashMap<>();
static {
map.put(0, new User(0, "jack", 18, "man"));
map.put(1, new User(1, "tom", 30, "man"));
map.put(2, new User(2, "翠花", 20, "女"));
map.put(3, new User(3, "张三", 22, "男"));
}
@Override
public User selectUserById(int id) {
return map.get(id);
}
}
4.2.2 将 UserDaoImpl 扫描到容器中
在编写 UserService 时,我们指定的组件扫描注解已经可以将该实例扫描到Spring容器了,因此不需要再次配置。
4.4 实体 User
// 这里使用了 lombok 创建,用于简化实例类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private int age;
private String gender;
}
4.5 配置 Tomcat【Tomcat需要我们提前安装好】
4.5.1 在IDEA 右上角有个 Add Configuration…,进入这里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rHldE0gQ-1602078341152)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/4.jpg)]
4.5.2 点击’+‘号,选择’Tomcat Server’,然后选择‘Local’,点击 ok 即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7uxqvci-1602078341155)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/5.jpg)]
4.5.3 配置Tomcat参数
这里重点时搭建SpringMVC全注解项目,有关Tomcat的配置就不再细说。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJifLjPT-1602078341156)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/6.jpg)]
4.5.4 完成配置,然后启动Tomcat
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4nKh0sh-1602078341158)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/7.jpg)]
4.5.5 使用浏览器访问测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONZCbQu7-1602078341159)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/8.jpg)]
五、中文乱码问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GCyWh49p-1602078341161)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/9.jpg)]
我们可以看到,查询id=3
的用户会出现中文乱码问题
// 实际上我们的数据是这样的
map.put(3, new User(3, "张三", 22, "男"));
我们再看看浏览器的【响应信息】,我们可以看到响应的数据编码格式并不是UTF-8
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WB9D2Syu-1602078341162)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/10.jpg)]
5.1 配置 CharacterEncodingFilter
以前我们在web.xml
会配置 CharacterEncodingFilter 过滤器,然而现在我们没有web.xml
配置文件,我们又该如何配置?
我们来到我们的MyWebAppInitializer
,我们知道MyWebAppInitializer
继承了抽象类AbstractAnnotationConfigDispatcherServletInitializer
,我们需要重写里面的方法void onStartup(...)
@Override
public void onStartup(ServletContext sc) throws ServletException {
super.onStartup(sc); // 调用父类方法
// 注册 CharacterEncodingFilter 过滤器
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setForceEncoding(true);
filter.setEncoding("UTF-8");
FilterRegistration.Dynamic encodingFilter = sc.addFilter("filter", filter);
// 配置过滤规则 '/*' 拦截所有请求
encodingFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
}
在ServletContext
类里面提供了对servlet
,filter
,listener
的组成方法
sc.addServlet();
sc.addFilter();
sc.addListener();
好了,我们配置好 CharacterEncodingFilter 过滤器后,是不是觉得可以解决中文乱码了?我们在访问一下看看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKVhFFEK-1602078341163)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/11.jpg)]
怎么回事???
这是因为在返回消息的是否,我们返回的是字符串,在 SpringMVC 内部会调用StringHttpMessageConverter
的方法转换,而这里StringHttpMessageConverter
设置的编码格式为Charset.forName("ISO-8859-1")
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSXTeUMB-1602078341165)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/12.jpg)]
5.2 配置 MessageConverter
这里我们打开WebAppConfig
配置类,它继承的WebMvcConfigurerAdapter
有一个空方法
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
我们需要注册一个StringHttpMessageConverter
转换策略
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 配置 String 转换编码格式为 UTF-8
converters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
}
这里我们在测试一次:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TGJzzbce-1602078341166)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/13.jpg)]
看到这个结果,是不是很开心,让我再来测试一下上传过程,作为是否会乱码???
5.3 测试请求体中文乱码
这里再写一个方法,处理接收的请求体
// 测试链接:http://localhost:8080/user-info?name="王五"&age=30&gender="男"
@RequestMapping("/user-info")
public String getUser(User user, Model model) {
System.out.println(user);
// 将数据放到 request 域
model.addAttribute("user",user);
return "/user.jsp";
}
我们来看控制台的打印,可以看到中文没有出现乱码【在Tomcat 8以后,服务器默认的编码格式就是 UTF-8
,因此request
请求不会出现乱码的现象了】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmd0ORvC-1602078341168)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/14.jpg)]
六、视图解析、返回 JSON 数据和解决静态资源访问配置
6.1 视图解析器
一般我们返回视图的是否,不建议使用xxx.jsp
的路径作为返回参数,这是我们通常会在web.xml
配置视图解析器。
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
然而,在全注解的SpringMVC中,我们只需要来到我们的WebAppconfig
配置类,重写父类WebMvcConfigurerAdapter
的方法void configureViewResolvers(...)
,来配置视图解析
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// 向容器注册了一个 InternalResourceViewResolver 视图解析器
registry.jsp("/WEB-INF/view/",".jsp");
}
/*
// 这是上面注册视图解析的底层代码实现,可以看到底层会给我们创建一个InternalResourceViewResolver,
//并指定我们的视图前缀和后缀
public UrlBasedViewResolverRegistration jsp() {
return this.jsp("/WEB-INF/", ".jsp");
}
public UrlBasedViewResolverRegistration jsp(String prefix, String suffix) {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(prefix);
resolver.setSuffix(suffix);
this.viewResolvers.add(resolver);
return new UrlBasedViewResolverRegistration(resolver);
}
*/
启动Tomcat测试视图解析器是否生效[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VoWeGiDU-1602078341169)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/15.jpg)]
访问的地址:/WEB-INF/view/user.jsp.jsp
返回的地址:return "/user.jsp";
可以看出视图解析器已经生效了,我们需要修改返回的地址,并将视图放到/WEB-INF/view/
目录即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vGEFCwq4-1602078341170)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/16.jpg)]
6.2 返回 JSON 数据
对于一个Web应用,返回 JSON 数据应该是必要的功能,我们测试一下 SpringMVC 是否可以返回 JSON 数据
// 返回任意对象并转换成JSON对象
@RequestMapping("/all-users")
@ResponseBody
public Object getAllUsers() {
List<User> userList = service.getAllUsers();
return userList;
}
当我们访问该地址时我们可以看到如下结果:
java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList
这是因为我们没有jackson-databind
的依赖,在转换成 json 数据时,会执行MappingJackson2HttpMessageConverter
,而该类型需要jackson-databind
的支持,我们需要导入它的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
并且将MappingJackson2HttpMessageConverter
重新注册到容器中;我们还是需要来到WebAppConfig
配置类,在void configureMessageConverters(...)
完成消息转换的注册
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 向容器注册一个 MappingJackson2HttpMessageConverter 实例
converters.add(new MappingJackson2HttpMessageConverter(new ObjectMapper()));
}
这样我们就可以解析对象为 json数据了[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6E7mJqxA-1602078341171)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/18.jpg)]
6.3 解决静态资源访问问题
在spring-mvc.xml
配置中,我们需要使用以下配置解决静态资源访问问题
<mvc:default-servlet-handler/>
而在全注解配置里面,我们需要在WebAppconfig
配置文件完成上面配置。
同样我们需要重写WebMvcConfigurerAdapter
的void configureDefaultServletHandling(...)
方法,开启即可。
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
七、SpringMVC 集成 Mybatis
7.1 环境搭建
7.1.1 导入Maven依赖
<!--Spring 操作数据库的一些依赖和控制事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<!--mybatis和spring的整合依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mysql驱动【需要和本地的数据库版本一致】-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--alibaba druid数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
7.1.2 建立测试数据库和表
drop database TestSpringMVC;
create database TestSpringMVC;
use TestSpringMVC;
create table tbl_user(
id int auto_increment primary key ,
name varchar(32),
age int,
birthday datetime
);
insert into tbl_user(name, age, birthday)
values ('张三',30,'1999-08-09'),('李四',22,'1998-03-09'),
('王五',20,'1987-08-19'),('余阳',21,'1999-08-03');
7.1.3 编写 db.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/TestSpringMVC?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8
jdbc.username=root
jdbc.password=1234
7.1.4 编写测试Dao接口
接口:
@Repository
public interface IUserDao {
User selectUserById(int id);
List<User> selectAllUsers();
int insertUser(User user);
}
Mybatis的 IUserDao.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shph.dao.IUserDao">
<sql id="user_column">
id, name, age,gender, birthday
</sql>
<!--根据 id 查询-->
<select id="selectUserById" parameterType="int" resultType="User">
select <include refid="user_column"></include> from tbl_user where id=#{arg0};
</select>
<!--查询所有用户-->
<select id="selectAllUsers" resultType="User">
select <include refid="user_column"></include> from tbl_user
</select>
<!--插入数据,并返回自增主键回填到 User对象-->
<insert id="insertUser" parameterType="User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into tbl_user(name,age,gender,birthday) values (#{name},#{age},#{gender},#{birthday})
</insert>
</mapper>
7.1.5 解决 XXXMapper.xml 编译问题
在IDEA工具中,位于 java 文件夹下的必须是 java 文件,否则不能编译,我们需要到 pom.xml 里面配置如下内容来解决。
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>com/shph/dao/**/*.xml</include>
</includes>
</resource>
</resources>
</build>
7.2 组件注册和事务控制配置
这里我们需要注册的组件主要有:
DataSource
【数据源】
SqlSessionFactoryBean
【这是Mybatis整合Spring提供的一个Bean用于mybatis的环境配置,这样就不需要添加mybatis-config.xml
配置文件了】
MapperScannerConfigurer
【这个也是Mybatis整合Spring封装的一个配置类,用于Mapper相关的配置,如指定Mapper所在的位置,指定SqlSession】
DataSourceTransactionManager
【关于事务相关的配置】
有关整合Mybatis的组件组成配置我们应该在Spring的配置类完成,因此我们需要在RootConfig
配置类完成相关配置:
// 开启事务控制
@EnableTransactionManagement
// 将 db.properties 的配置导入到 Spring 的环境里面
@PropertySource(value = "classpath:db.properties")
@Configuration
@ComponentScan(basePackages = "com.shph", excludeFilters = @ComponentScan.Filter({Controller.class}))
public class RootConfig {
// 配置数据库连接池
@Bean(value = "dataSource", initMethod = "init", destroyMethod = "close")
public DruidDataSource initDruidDataSource(
@Value("${jdbc.driverClassName}") String driverClassName,
@Value("${jdbc.url}") String url,
@Value("${jdbc.username}") String username,
@Value("${jdbc.password}") String password
) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
// 初始化 SqlSessionFactoryBean
@Bean("sqlSessionFactory")
public SqlSessionFactoryBean initSqlSessionFactoryBean(DataSource dataSource) throws IOException {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactory.setMapperLocations(resolver.getResources("classpath:com/shph/dao/*.xml"));
sqlSessionFactory.setTypeAliasesPackage("com.shph.entity");
return sqlSessionFactory;
}
@Bean
public MapperScannerConfigurer initMapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.shph.dao");
// 这里的 sqlSessionFactory 字符串必须与注册 SqlSessionFactoryBean 时指定的 id 值一样
configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
return configurer;
}
// 配置事务管理
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
return transactionManager;
}
}
【注意:这里有一个小问题,在DataSource数据源配置时,使用 @Value
注解从Spring的环境去配置信息可能会失效,关于失效原因这里可以参考该文档:@Value不能注入解决方案】
7.3 Mybatis 日志打印
关于日志配置在Mybatis官网有介绍环境配置https://mybatis.org/mybatis-3/zh/logging.html,这里就简单概述一些。
在Mybatis官方推荐我们使用 log4j 日志框架,因此我们这里就介绍一些 log4j 的配置。
7.3.1 导入 log4j 依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
7.3.2 编写 log4j 配置文件log4j.properties
这里需要关注一些 log4j 的日志打印级别OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果我们想要看到 mysql 的sql语句执行输出日志,日志级别需要 DEBUG及以下
# 全局日志配置
log4j.rootLogger=DEBUG, stdout
# MyBatis 日志配置
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
7.4 测试Mybatis的集成
7.4.1 测试查询所有
URL地址:http://localhost:8080/all-users
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VcsFApx1-1602078341173)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/19.jpg)]
7.4.2 测试通过 id 查询用户
URL地址:http://localhost:8080/user?id=1
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QBmIPcjA-1602078341174)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/20.jpg)]
7.4.3 测试插入一条用户数据
这里编写了一个简单的 jsp页面,用于提交用户信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PtcSlY7N-1602078341175)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/21.jpg)]
URL地址:http://localhost:8080/add-user?name=翠芬&age=19&gender=女&birthday=2000-02-09
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3eihR0Y-1602078341177)(https://shphuang_aliyun.gitee.io/pictures-of-the-warehouse/spring-mvc-annotation-all-demo-img/22.jpg)]
这是由于在提交的数据里面有一个日期birthday=2000-02-09
数据,在后端接收数据时需要转换成Date
对象类型,但是2000-02-09
是字符串,无法转换成日期类型。
解决方案一:
在Spring的org.springframework.format.annotation.DateTimeFormat
提供了一个注解,用于格式化日期,在属性或者set方法上添加该注解即可解决。
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
我们需要编写一个实现类实现接口Converter
,该接口有一个方法,用于数据转换
public class StringToDateConvert implements Converter<String, Date> {
@Override
public Date convert(String source) {
if (!Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$",source)) {
return null;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = dateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
同时,我们还需要去注册到 Formatter 转换器才能使用:
来到配置类WebAppConfig
重写其父类方法void addFormatters(...)
// 注册 Formatter 转换器
@Override
public void addFormatters(FormatterRegistry registry) {
// 将自定义字符串日期转换器添加到 FormatterRegistry
registry.addConverter(new StringToDateConvert());
}
nverter<String, Date> {
@Override
public Date convert(String source) {
if (!Pattern.matches("^\d{4}-\d{2}-\d{2}$",source)) {
return null;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = dateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
同时,我们还需要去注册到 Formatter 转换器才能使用:
来到配置类`WebAppConfig`重写其父类方法`void addFormatters(...) `
```java
// 注册 Formatter 转换器
@Override
public void addFormatters(FormatterRegistry registry) {
// 将自定义字符串日期转换器添加到 FormatterRegistry
registry.addConverter(new StringToDateConvert());
}