一、SSM 概述
Spring 作为一站式框架,其本质是一个容器,就是一个存放了一个个描述不同对象属性和方法的定义单元,需要使用的时候就通过反射机制根据把对象创建好,再将描述的属性初始化。
一般我们所说的 SSM 是指 Spring、SpringMVC 和 Mybatis 。我们所熟悉的数据持久层、业务逻辑层和表现层在 SSM 中体现为:
表现层:SpringMVC,其中 Controller 作为前后的中介接收前端请求调用 Service;
业务逻辑层:使用 AOP 完成事务管理的工作;
数据持久层:使用 Spring 与 Mybatis 完成整合。
各层之间通过 DI 的的方式来完成各层之间的调用。
二、使用注解开发一个 SSM 项目
先不要着急看不懂,慢慢就明白了
老规矩,从 mvn 模板创建一个 webapp
(一)引入所需要的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.15</version>
</dependency>
</dependencies>
(二)编写两个配置文件
要连接的数据库的信息
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=UTF-8&useUnicode=true
&serverTimezone=UTC
jdbc.user=root
jdbc.password=
日志信息
# 定义输出级别为 debug,输出名称为 stdout
log4j.rootLogger=debug,stdout
# 定义 stdout 的输出采用哪个类来执行
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 定义 stdout 的输出类型的样式布局
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 定义 stdout 样式布局的消息格式
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
(三)编写所需要的配置文件
1. spring-service.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.ls.bookmanager.service.impl " />
<!-- 配置 Spring事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置 Spring 注解形式的事务管理驱动 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
2.spring-dao.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置属性占位符资源文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置 C3P0 数据库链接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="${jdbc.driver}" p:jdbcUrl="${jdbc.url}" p:user="${jdbc.user}"
p:password="${jdbc.password}" p:initialPoolSize="5"
p:maxPoolSize="20" p:minPoolSize="5" p:maxIdleTime="200" />
<!-- 配置 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource" p:configLocation="classpath:mybatis-config.xml" />
<!-- 配置 mapper 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:basePackage="com.ls.bookmanager.mapper" p:sqlSessionFactoryBeanName="sqlSessionFactory"/>
</beans>
3.spring-mvc.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 批量扫描 Controller -->
<context:component-scan base-package="com.ls.bookmanager.controller" />
<!-- 配置注解方式的映射器、适配器 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
(四)配置 web.xml
<!-- 加载 Spring 容器的 Service 层、 Dao 层的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-service.xml,classpath:spring-dao.xml</param-value>
</context-param>
<!-- 配置 CharacterEncodingFilter 过滤器, 解决中文乱码 -->
<filter>
<filter-name>CharacterFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置前端控制器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载 spring-mvc.xml 配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<!-- 配置前端控制器的映射 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
(四)从 dao 开始理清业务逻辑
主要的类有 :
XXXController:用于接受前端请求,找到应该调用的 Service,其实就是调用 Service 用的;
XXXService:负责业务逻辑的,主要作用就是来操作数据持久层,也就是 XXXDao/XXXMapper;
XXXMapper:mybatis 的文件,给一个操作 pojo 的接口,我们就可以在 XXXMapper.xml 文件写 sql 来操作数据库了。
1.POJO 和 Mapper
//为了节省内容只给了包名,import删除了
package com.ls.bookmanager.model;
@Data
@Accessors(chain = true)
public class Book {
private Long id;
private String bookName;
private String bookAuthor;
private Date createTime;
private Date updateTime;
}
//———————————————————————————————————————————————————————————————————————————————————————————————
package com.ls.bookmanager.mapper;
public interface BookMapper {
List<Book> list();
}
这个 XXXMapper 接口就相当于是一个 XXXDao 的 Interface ,按照传统功夫点到为止我们得在这里面写方法再去 XXXDaoImpl 中实现,但是我们有 spring-mybatis 。有了 Mapper 接口之后 之后就要配置相应的 XXXMapper.xml 文件,切记放在同一包名下方便自动扫描。
CREATE TABLE `book` (
`id` int NOT NULL AUTO_INCREMENT,
`book_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`book_author` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ls.bookmanager.mapper.BookMapper">
<resultMap id="BookMap" type="com.ls.bookmanager.model.Book">
<id column="id" property="id"></id>
<result column="book_name" property="bookName"></result>
<result column="book_author" property="bookAuthor"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<sql id="COLUMNS">
id,book_name,book_author,create_time,update_time
</sql>
<select id="list" resultMap="BookMap">
select <include refid="COLUMNS"></include> from book
</select>
</mapper>
2.Service 层
我们再 Service 中需要调用 dao 的方法,所以使用注解把 bookMapper 注入进来,可以看到 Service 里面还是通过注入的 bookMapper 来操作 Mapper 中的方法。
package com.ls.bookmanager.service.impl;
public interface BookService {
List<Book> list();
}
//————————————————————————————————————————————————————————————————————————————————
package com.ls.bookmanager.service.impl;
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public List<Book> list() {
List<Book> list = bookMapper.list();
return list;
}
}
3.Controller 层
同样是用了依赖注入的方式,把需要用到的bookService 注入进来,在内部调用 bookService 的方法。
注解有新的,但是不要慌,这个 @RequestMapping("/list.action") 就是说我如果前端访问 list.action 就会找到这个方法,进而找到对听的 service 和 dao,这个一会细。
在 list 方法中,我们选择让他返回一个字符串来表示逻辑视图的名称。
package com.ls.bookmanager.controller;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "bookList";
}
}
4.前端显示页面
没什么好说的,楼下细。
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>图书列表</title>
</head>
<body>
${bookList}
</body>
</html>
三、配置解析
(一)Dao 层 - spring-dao.xml
参考:
dao 层依赖 spring-mybatis 这个包。在 mybatis 中,SqlSessionFactory 是由 SqlSessionFactoryBuilder 所创建的,而在 mybatis-spring 中 是由 SqlSessionFactoryBean 创建的。
SqlSessionFactoryBean 实现了 Spring 的 FactoryBean 接口。这意味着由 Spring 最终创建的 bean 并不是 SqlSessionFactoryBean 本身,而是工厂类(SqlSessionFactoryBean)的 getObject() 方法的返回结果。这种情况下,Spring 将会在应用启动时为你创建 SqlSessionFactory,并使用 sqlSessionFactory 这个名字存储起来。
//上述内容的等效代码
@Bean
public SqlSessionFactory sqlSessionFactory() {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
通常在mybatis-spring的使用中,不需要直接使用 SqlSessionFactoryBean 或者对应的 SqlSessionFactory 。Session factory 会被注入到 MapperFactoryBean 或者其他继承 SqlSessionDaoSupport 的 DAO 。
我们通过 MapperScannerConfigurer 自动扫描所有的 Mapper 接口,使用时可以直接注入接口。
basePackage : 用于配置基本的包路径。可以使用分号或逗号作为分隔符设置多于一个的包路径,每个映射器将会在指定的包路径中递归地被搜索到 。
annotationClass : 用于过滤被扫描的接口,如果设置了该属性,那么 MyBatis 的接口只有包含该注解才会被扫描进去
MapperScannerConfigurer 中,我们知道 sqlSessionFactory 的注入方式有四种,分别是 sqlSessionFactory,sqlSessionFactoryBeanName,sqlSessionTemplate,sqlSessionTemplateBeanName ,而sqlSessionFactory这种已经过时,所以我们用到的是sqlSessionFactoryBeanName,区别可以看这里。总之我们通过这种方式就可以 openSession 了。
在 SqlSessionFactory 的配置中我们指定了数据源的配置,这里使用的是 c3p0 连接池
(二)Service 层 - spring-service.xml
Service 层中主要就是配置了事务管理,其依赖于配置好的数据源。在 Service 层加上 @Transactional 注解即可。
四、注解解析
(一)@RequestMapping
通过 @RequestMapping 注解可以定义不同的处理器映射规则。
URL 路径映射:@RequestMapping(value={"/item"})或 @RequestMapping("/item"),value 的值是数组,可以将多个 url 映射到同一个方法。
//URL 路径映射
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "bookList";
}
//限制只能通过 POST 或 GET 进行访问
@RequestMapping(value = "/add.action",method = {RequestMethod.POST,RequestMethod.GET})
public String add() {
System.out.println("add 添加图书");
return "bookList";
}
//只能通过 POST 或者 GET 的另一种方式
@PostMapping("/delete.action")
//@PostMapping("/delete.action")
public String delete() {
System.out.println("delete 删除");
return "bookList";
}
窄化请求映射:在 class 上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求 url 必须以请求前缀开头,通过此方法对 url 进行分类管理。
访问方式应该为 : /book/list.action
//窄化请求映射
@RequestMapping("/book")
public class BookController {
@Autowired
private BookService bookService;
//URL 路径映射
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "bookList";
}
}
(二)@Controller (Controller 方法的返回值)
1.返回一个 ModeAndeView 对象
Controller 方法中定义 ModelAndView 对象为返回类型,对象中可添加 model 数据、指定 view 视图等。
2.返回字符串
返回逻辑视图名 : return "bookList";
Controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图。物理视图地址=视图解析器前缀+逻辑视图名+视图解析器后缀。
实现重定向:使用 SpringMVC 框架,处理一次请求时,Controller 层会将数据模型 model 放到 request 域中。而重定向实际是发起了两次请求。那么在第一次请求中获取的数据,是无法与第二次的 request 进行共享。所以在重定向时,一般做法是让 SpringMVC 重新执行另一个 action 动作。如下图,输入的是 list.action
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "redirect:add.action";
}
实现请求转发:SpringMVC 中请求转发与 Servlet 中的请求转发一致,服务器的多次处理在一个请求范围内,所以数据模型 model 可以实现共享。 请求转发返回的字符串使用 "forward:" 作为前缀,SpringMVC 就是根据 ":" 来进行字符串拆分,如果拆分正确,并且":" 前面的字符串为 "forward" 则进行请求转发操作。
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "forward:add.action";
}
3.返回 void
进行 url 映射的方法,使用 void 关键字去修饰,定义方法没有任何数据返回。这种情况,实际上是利用了 Controller 方法的形参,request 和 response 进行开发,变为原始的 servlet 开发方式了。
//request 请求转发
request.getRequestDispatcher("url").forwart(request,response);
//response 重定向
response.sendRedirect("url");
4.返回 JSON 数据
楼下细
(三)Controller 参数绑定
1.普通类型
在 Controller 层中定义的方法默认支持的形参中包括了 request 对象,除了可以通过 request 对象来获取客户端发送的请求中包含 key/value 对的数据。SpringMVC 框架还可以把 key/value 对数据绑定到 Controller 层中方法 的形参上。这步操作是由 SpringMVC 框架中的参数绑定组件来帮我们完成的,这步操作就称为参数绑定。
//在访问的时候我们通过 GET 方式将参数显式传过去
@RequestMapping("/list.action")
public String list(HttpServletRequest request,HttpServletResponse response) {
String name = request.getParameter("name");
System.out.println(name);
List<Book> bookList = bookService.list();
request.setAttribute("bookList",bookList);
return "forward:add.action";
}
SpringMVC 进行简单参数绑定时,需要遵循如下规则:url 请求中包含的参数名称,必须与 url 映射方法的形参名称保持一致,才会将 url 请求中参数与方法的形参绑定成功,否则不进行绑定。
SpringMVC 默认支持的简单类型绑定包括:整型、字符串、单精度/双精度、布尔类型。
@RequestMapping(value = "/add.action",method = {RequestMethod.POST,RequestMethod.GET})
public String add(String bookName,String bookAuthor) {
System.out.println("add 添加图书,bookName"+bookName+";"+"bookAuthor:"+bookAuthor);
return "bookList";
}
但是在实际中可能对于简单类型的传参前后端的参数名称可能不一样,SpringMVC 提供了 @RequestParam 注解协助对简单类型的绑定。Controller 内的参数名称是 String 类型的 bookName 和 bookAuthor ,前端传入的是 name 和 author。
@RequestMapping(value = "/add.action",method = {RequestMethod.POST,RequestMethod.GET})
public String add(@RequestParam("name") String bookName, @RequestParam("author")String bookAuthor) {
System.out.println("add 添加图书,bookName"+bookName+";"+"bookAuthor:"+bookAuthor);
return "bookList";
}
2.实体类型POJO
如果在 Controller 层的方法中直接定义 pojo 的形参,如果想要将表单中的数据绑定到 pojo 对象里面去,需要 页面中 input 的 name 属性值和 Controller 的 pojo 形参中的成员变量名一致,这样页面中数据将直接绑定到 pojo 对象上,不需要额外的注解。
SpringMVC 对 pojo 类型的属性进行参数绑定时,实际上就是调用的 pojo 属性的 set 方法完成的。
@RequestMapping("/update.action")
public String update(Book book) {
System.out.println("修改图书"+book);
System.out.println("update 修改图书");
return "bookList";
}
3.实体类的包装类
包装类型的 pojo 参数绑定,就是如何将 url 请求中的参数绑定到 pojo 成员对象的属性中去。
如果想把 IdCard 作为 Person 的属性传入的话,可以使用 OGNL 的形式,并且可以看到实际上还是调用了 IdCard 的 setter。
package com.ls.bookmanager.model;
@Data
@Accessors(chain = true)
public class Person {
private String name;
private IdCard idCard;
}
//————————————————————————————————————————————————————————————————————————————————————
package com.ls.bookmanager.model;
@Data
@Accessors(chain = true)
public class IdCard {
private String cardNum;
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
System.out.println("set");
}
}
4.自定义类型参数绑定
这个在 SpringBoot 中有更简单的方式,所以这儿就有个印象了。
<!-- 通过注解驱动属性 conversion-service 指定转换服务组件 -->
<mvc:annotation-driven conversion-service="conversionService"/>
5.数组、Map、List 参数绑定
数组绑定
Map 参数绑定
List 参数绑定
五、JSON 数据交互
(一)@RequestBody
SpringMVC 对于客户端的请求参数,既支持 key/value 对的形式,也支持 json 串的形式。在大部分情况下, 前端的参数格式都采用普通 form 表单的 k/v 对的形式。
SpringMVC 框架需要使用 jackson 的 jar 包进行 json 格式的转换,因此需要引入依赖
<!-- 引入 json 格式转换依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
此外还需要配置 json 转换器,如果使用注解方式的处理器映射器、处理器适配置,即 mvc:annotation-driven,则可以不用定义下面的内容。
<!-- 配置 json 格式转换器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
我们使用 postman 作为工具,向 update.action 发送一个 json 字符串,在下面这个 controller 方法中,参数列表使用注解 @RequestBody 将 json 串转换成 Java 的 Map 对象并输出。
@RequestMapping("/update.action")
public String updatePerson(@RequestBody Map<String,Object> param) {
System.out.println(param);
return "personList";
}
对于含有包装类的返回,json 格式也更方便,比如上面:
@RequestMapping("/add.action")
public String addPerson(@RequestBody Person person) {
System.out.println(person);
return "personList";
}
(二)@ResponesBody
使用注解 @ResponseBody 将 Java 对象转换成 json 串输出,比如我们使用 BookController 的 list 方法,其本质是通过 Service 调用Dao 的 list 方法查询数据库中的所有数据,我们通过 @ResopnseBody 把这些数据的返回变成 JSON 格式,在 PostMan 中可以看见。
@RequestMapping("/list1.action")
@ResponseBody
public List<Book> list1(HttpServletRequest request,HttpServletResponse response) {
return bookService.list();
}
六、文件上传下载
如果在开发时需要实现文件上传,则 form 表单的 enctype 属性需要指定为 multipart/form-data 类型,如果 使用 SpringMVC 框架,那么就需要 SpringMVC 框架来实现对这种数据类型的解析。
需要添加commons-fileupload.jar包,因为下面的 MVC 多部件数据类型解析器在实现上传时会用到此JAR包的相关类。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
配置 SpringMVC 框架对 multipart 类型的数据进行处理的解析器,在 spring-mvc.xml 配置文件中,配置 CommonsMultipartResolver 类。此类的作用就是可以解析 multipart 类型的数据。
<!-- 配置 SpringMVC 多部件数据类型解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5242880"/>
</bean>
直接更改 index.jsp 作为文件上传的起始页。
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<body>
<h2>Hello World!</h2>
<form action="${pageContext.request.contextPath}/file/upload.action" method="post"
enctype="multipart/form-data">
choice:<input type="file" name="file">
<input type="submit" value="submit">
</form>
</body>
</html>
选择文件上传到本机的 D 盘并获得时间戳和文件后缀名。
package com.ls.bookmanager.controller;
@Controller
@RequestMapping("/file")
public class FileController {
@RequestMapping("/upload.action")
public Map<String, Object> updateItem(HttpServletRequest request, MultipartFile file) throws
Exception {
if (file != null) {
String fileName = file.getOriginalFilename();
//文件的拓展名
String fileType = fileName.substring(fileName.lastIndexOf("."));
File newFile = new File("D://" + System.currentTimeMillis() + fileType);
file.transferTo(newFile);
}
HashMap<String, Object> result = new HashMap<>();
result.put("result","ok");
return result;
}
}
以 debug 模式更方便看见内容。