5.5 控制器响应前端请求
5.4.1 响应同步请求
响应同步请求:前端发送请求到控制器类中的方法,控制器方法处理完请求之后需要跳转到下一个页面
-
前端请求
<a href="book/list?pageNum=1&pageSize=10">获取图书信息(同步)<a>
-
控制器响应同步请求:处理同步请求的控制器方法返回类型为String或ModelAndView
- 转发
@RequestMapping("/list") public String list(int pageNum,int pageSize){ //... return "/book-list.jsp"; } @RequestMapping("/list") public ModelAndView list(int pageNum, int pageSize){ //... ModelAndView modelAndView = new ModelAndView("/book-list.jsp"); return modelAndView; }
- 重定向
@RequestMapping("/list") public String list(int pageNum, int pageSize){ //... return "redirect:/book-list.jsp"; } @RequestMapping("/list") public ModelAndView list(int pageNum, int pageSize){ //... ModelAndView modelAndView = new ModelAndView("redirect:/book-list.jsp"); return modelAndView; }
5.4.2 响应异步请求
响应异步请求:不会发生页面跳转,直接将数据返回给ajax请求
-
前端发送ajax请求
<button id="listBtn">获取图书信息(异步)</button> <script type="text/javascript" src="js/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $("#listBtn").click(function(){ $.ajax({ url:"book/list2", type:"get", data:{pageNum:1,pageSize:10}, success:function (res) { console.log(res); } }); }); </script>
-
控制方法响应ajax请求
方式1:使用response对象的输出流响应ajax请求
@RequestMapping("/list2") public void list2(int pageNum, int pageSize, HttpServletResponse response) throws IOException { List<Book> bookList = new ArrayList<Book>(); bookList.add(new Book(1,"Java1","张小三",22.22,new Date(),"666")); bookList.add(new Book(2,"Java2","张三",22.22,new Date(),"666")); bookList.add(new Book(3,"Java3","张大三",22.22,new Date(),"666")); String jsonStr = new ObjectMapper().writeValueAsString(bookList); response.setContentType("application/json;charset=utf-8"); PrintWriter out = response.getWriter(); out.write(jsonStr); out.flush(); out.close(); }
方式2:将控制方法的返回类型修改为要响应的数据的类型,在控制器方法中直接return要响应的数据
- 需要依赖
jackson-databind
依赖 - 需要在控制器方法上添加
@ResponseBody
注解
@ResponseBody @RequestMapping("/list2") public List<Book> list2(int pageNum, int pageSize) throws IOException { List<Book> bookList = new ArrayList<Book>(); bookList.add(new Book(1,"Java1","张小三",22.22,new Date(),"666")); bookList.add(new Book(2,"Java2","张三",22.22,new Date(),"666")); bookList.add(new Book(3,"Java3","张大三",22.22,new Date(),"666")); return bookList; }
- 需要依赖
5.6 控制器传值到下一个页面
针对处理同步请求的控制器方法
方式一:控制器方法返回类型为ModelAndView,直接使用ModelAndView对象携带数据
@RequestMapping("/list")
public ModelAndView list(int pageNum, int pageSize){
List<Book> bookList = new ArrayList<Book>();
bookList.add(new Book(1,"Java1","张小三",22.22,new Date(),"666"));
bookList.add(new Book(2,"Java2","张三",22.22,new Date(),"666"));
bookList.add(new Book(3,"Java3","张大三",22.22,new Date(),"666"));
ModelAndView modelAndView = new ModelAndView("/book-list.jsp");
modelAndView.addObject("bookList",bookList);
return modelAndView;
}
方式二:控制器方法返回类型为String,在控制方法中添加HttpServletRequest参数,使用request对象传值
@RequestMapping("/list")
public String list(int pageNum, int pageSize, HttpServletRequest request){
List<Book> bookList = new ArrayList<Book>();
bookList.add(new Book(1,"Java1","张小三",22.22,new Date(),"666"));
bookList.add(new Book(2,"Java2","张三",22.22,new Date(),"666"));
bookList.add(new Book(3,"Java3","张大三",22.22,new Date(),"666"));
request.setAttribute("bookList",bookList);
return "/book-list.jsp";
}
方式三:控制器方法返回类型为String,在控制方法中添加Model
参数,使用model对象传值
@RequestMapping("/list")
public String list(int pageNum, int pageSize, Model model){
List<Book> bookList = new ArrayList<Book>();
bookList.add(new Book(1,"Java1","张小三",22.22,new Date(),"666"));
bookList.add(new Book(2,"Java2","张三",22.22,new Date(),"666"));
bookList.add(new Book(3,"Java3","张大三",22.22,new Date(),"666"));
model.addAttribute("bookList",bookList);
return "/book-list.jsp";
}
5.7 解决中文乱码问题
5.7.1 前端编码设置
-
JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
-
html
<meta charset="UTF-8">
5.7.2 服务器Tomcat编码设置
-
tomcat_home/conf/server.xml
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
5.7.3 项目中的编码设置
-
Servlet类
request.setCharacterEncoding("UTF-8"); //必须在接收request中第一个数据之前
-
SpringMVC: SpringMVC提供了专门的编码过滤器,我们只需在web.xml中进行配置即可:
<filter> <filter-name>springmvcEncodingFilter</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>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>springmvcEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
六、日期格式处理
自定义SpringMVC的日期格式转换器
6.1 自定义日期转换器
/**
* 实现Converter接口
*/
public class MyDateConverter implements Converter<String, Date> {
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd");
@Override
public Date convert(String source) {
Date date = null;
try {
if(source.matches("[0-9]{4}-[0-9]{2}-[0-9]{2}")){
date = sdf1.parse(source);
}else if(source.matches("[0-9]{4}/[0,1][0-9]/[0-3][0-9]")){
date = sdf2.parse(source);
}
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
6.2 配置给SpringMVC
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.qfedu.converters.MyDateConverter"/>
</set>
</property>
</bean>
七、统一异常处理
我们的应用系统在运行过程,可能由于运行环境、用户操作、资源不足、程序偶发性异常等等各方面的原因导致系统出现异常(http状态、程序中的exception);如果系统出现了异常,这些异常就会通过浏览器显示在网页中,但是这些异常提示显示给用户是没有必要,用户体验性也不好,我们可以针对这些异常显示特定的网页给用户。
7.1 HTTP状态异常统一处理
404 为例
-
创建状态异常跳转页面 404.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> 您访问的页面不存在,请检查输入的网址是否正常。 </body> </html>
-
在web.xml文件中配置异常状态码和异常页面的映射
<error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page>
7.2 程序异常统一处理
程序抛出的各种exception: NullPointerException ArithmeticException…
-
Servlet处理方式:
<error-page> <exception-type>java.lang.NullPointerException</exception-type> <location>/err.jsp</location> </error-page>
-
SpringMVC处理方式:
@ControllerAdvice public class MyExceptionHandler { @ExceptionHandler(NullPointerException.class) public String nullHandler(Model model){ model.addAttribute("tips","空指针"); return "/err.jsp"; } @ExceptionHandler(ArithmeticException.class) public String arithmeticHandler(Model model){ return "/err.jsp"; } }
八、拦截器
8.1 拦截器介绍
SpringMVC提供的拦截器就类似于servlet-api中的过滤器,可以对控制器的请求进行拦截实现相关的预处理和后处理工作。
- 过滤器
- 是Servlet规范的一部分,所有的web项目都可以使用过滤器
- 过滤器在web.xml进行配置(可以使用注解),能够拦截所有请求
- 拦截器
- 是SpringMVC框架的实现,只有在SpringMVC项目中才能使用
- 拦截器是在SpringMVC的配置文件进行配置,不会拦截被SpringMVC放行的资源(mvc:resources)
8.2 自定义拦截器
-
创建拦截器
public class MyInterceptor implements HandlerInterceptor { /** * 拦截器的预处理方法,在进入到控制器方法之前执行 * return true表示放行,进入到控制器方法的执行 * return false表示不放行,通过response直接响应浏览器,控制方法不会执行 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--------------------preHandle"); //示例:如果提交的参数中不包含bookId则不放行 Enumeration<String> keys = request.getParameterNames(); while(keys.hasMoreElements()){ String key = keys.nextElement(); if("bookId".equals(key)){ return true; } } response.setStatus(400); return false; } /** * 后处理方法:控制器方法执行完成之后,响应浏览器之前执行 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("--------------------postHandle"); } }
-
配置拦截器: 在springmvc的配置文件
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/book/**"/> <mvc:exclude-mapping path="/book/list"/> <mvc:exclude-mapping path="/book/list2"/> <bean class="com.qfedu.handlers.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
8.3 拦截器链
将多个拦截器配置拦截同一个控制器请求,构成一个拦截器链,多个拦截器按照配置顺序执行。
九、SSM整合
9.1 创建web项目
略
9.2 添加依赖
9.2.1 MyBatis
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
9.2.2 Spring
<properties>
<spring.version>5.3.15</spring.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
9.2.3 整合
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
9.2.4 其他
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
9.3 配置文件
9.3.1 myabtis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
9.3.2 druid.properties
druid.driver=com.mysql.cj.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/db_2111?characterEncoding=utf-8
druid.username=root
druid.password=@QFedu123
druid.pool.init=1
druid.pool.minIdle=3
druid.pool.maxActive=20
druid.pool.timeout=30000
9.3.3 spring-servlet.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
<!-- 声明注解配置 -->
<context:annotation-config/>
<!-- 声明注解扫描范围 -->
<context:component-scan base-package="com.qfedu"/>
<!-- 声明MVC注解配置 -->
<mvc:annotation-driven/>
<!-- 数据库连接池 -->
<context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driver}"/>
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
<property name="maxActive" value="${druid.pool.maxActive}"/>
<property name="minIdle" value="${druid.pool.minIdle}"/>
<property name="initialSize" value="${druid.pool.init}"/>
<property name="maxWait" value="${druid.pool.timeout}"/>
</bean>
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<property name="typeAliasesPackage" value="com.qfedu.beans"/>
</bean>
<!-- MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.qfedu.dao"/>
</bean>
<!-- 配置Spring事务管理 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- mvc静态资源 -->
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
<mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
<mvc:resources mapping="/images/**" location="/images/"></mvc:resources>
<mvc:resources mapping="/pages/**" location="/pages/"></mvc:resources>
</beans>
9.3.4 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--SpringMVC 前端控制器-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- SpringMVC编码过滤器 -->
<filter>
<filter-name>springmvcEncodingFilter</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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springmvcEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
十、SSM整合应用
案例:图书信息管理
10.1 准备工作
-
SSM整合配置
-
创建图书信息表
create table tb_books( book_id int primary key auto_increment, book_name varchar(100) not null, book_author varchar(20) not null, book_price decimal(10,2) not null, book_img varchar(100) , book_date datetime not null, book_desc varchar(200) );
-
案例业务流程
- 添加图书
- 图书列表
10.2 图书列表功能
10.2.1 数据库操作实现
-
创建实体类
@Data @NoArgsConstructor @AllArgsConstructor @ToString public class Book { private int bookId; private String bookName; private String bookAuthor; private double bookPrice; private String bookImg; private Date bookDate; private String bookDesc; }
-
创建DAO接口,定义操作方法
public interface BookDAO { public List<Book> selectBooks(); }
-
MyBatis映射文件配置
<?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"> <!--namespace = 所需实现的接口全限定名--> <mapper namespace="com.qfedu.dao.BookDAO"> <resultMap id="bookMap" type="Book"> <id column="book_id" property="bookId"/> <result column="book_name" property="bookName"/> <result column="book_author" property="bookAuthor"/> <result column="book_price" property="bookPrice"/> <result column="book_img" property="bookImg"/> <result column="book_date" property="bookDate"/> <result column="book_desc" property="bookDesc"/> </resultMap> <select id="selectBooks" resultMap="bookMap"> select book_id,book_name,book_author,book_price,book_img,book_date,book_desc from tb_books </select> </mapper>
10.2.2 业务逻辑层实现
-
创建分页帮助类
@Data @NoArgsConstructor @AllArgsConstructor public class PageBean<T> { private int pageNum; private int pageSize; private int pageCount; private int prePage; private int nextPage; private List<T> data; }
-
添加MyBatis分页插件
- 添加依赖
- 配置分页插件
-
创建servcie接口
public interface BookService { public PageBean listBooks(int pageNum, int pageSize); }
-
创建service实现类
@Service public class BookServiceImpl implements BookService { @Autowired private BookDAO bookDAO; public PageBean listBooks(int pageNum, int pageSize) { PageHelper.startPage(pageNum,pageSize); List<Book> books = bookDAO.selectBooks(); PageInfo<Book> pageInfo = new PageInfo<Book>(books); int pageCount = pageInfo.getPages(); int prePage = pageNum-1==0?1:pageNum-1; int nextPage = pageNum+1>pageCount?pageCount:pageNum+1; PageBean<Book> bookPageBean = new PageBean<Book>(pageNum, pageSize, pageCount, prePage, nextPage, pageInfo.getList()); return bookPageBean; } }
10.2.3 业务流程实现
-
创建控制器及处理图书列表请求的方法
@Controller @RequestMapping("/book") public class BookController { @Autowired private BookService bookService; @RequestMapping("/list") public String list(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "5") int pageSize, Model model){ PageBean pageBean = bookService.listBooks(pageNum, pageSize); model.addAttribute("pageBean",pageBean); return "/book-list.jsp"; } }
-
创建index.jsp,点击“图书列表”发送同步请求到 book/list
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <table style="width: 100%; height: 800px"> <tr style="height: 100px; background: deepskyblue"> <td colspan="2">图书信息管理系统</td> </tr> <tr style="height: 700px"> <td width="200" valign="top"> <ul> <li><a href="book-add.jsp" target="mainFrame">添加图书</a></li> <li><a href="book/list" target="mainFrame">图书列表</a></li> </ul> </td> <td> <iframe name="mainFrame" width="100%" height="700px"></iframe> </td> </tr> </table> </body> </html>
-
在book-list.jsp显示图书列表信息
- 添加jstl依赖
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <base href="${pageContext.request.contextPath}/"> <title>Title</title> </head> <body> 图书列表页面 <table style="width: 96%;" align="center" border="1" cellspacing="0"> <thead> <tr> <th>编号</th> <th>名称</th> <th>作者</th> <th>价格</th> <th>图片</th> <th>日期</th> <th>描述</th> <th>操作</th> </tr> </thead> <tbody> <c:forEach items="${pageBean.data}" var="book"> <tr> <td>${book.bookId}</td> <td>${book.bookName}</td> <td>${book.bookAuthor}</td> <td>${book.bookPrice}</td> <td><img src="${book.bookImg}" height="35"/></td> <td>${book.bookDate}</td> <td>${book.bookDesc}</td> <td> <a href="">删除</a> <a href="">修改</a> </td> </tr> </c:forEach> <tr> <td colspan="8" align="center"> <c:if test="${pageBean.pageNum == 1}"> <label style="color: gray">首页</label> | <label style="color: gray">上一页</label> </c:if> <c:if test="${pageBean.pageNum > 1}"> <a href="book/list?pageNum=1">首页</a> | <a href="book/list?pageNum=${pageBean.prePage}">上一页</a> </c:if> 当前第${pageBean.pageNum}页 / 共${pageBean.pageCount}页 <c:if test="${pageBean.pageNum < pageBean.pageCount}"> <a href="book/list?pageNum=${pageBean.nextPage}">下一页</a> | <a href="book/list?pageNum=${pageBean.pageCount}">尾页</a> </c:if> <c:if test="${pageBean.pageNum == pageBean.pageCount}"> <label style="color: gray">下一页</label> | <label style="color: gray">尾页</label> </c:if> </td> </tr> </tbody> </table> </body> </html>
10.3 添加图书功能—文件上传
添加图书信息,图书中包含图片——涉及文件上传
10.3.1 数据库操作实现
-
在BookDAO中定义添加方法
public interface BookDAO { public List<Book> selectBooks(); public int insertBook(Book book); }
-
配置映射文件
<insert id="insertBook"> insert into tb_books(book_name,book_author,book_price,book_img,book_date,book_desc) values(#{bookName},#{bookAuthor},#{bookPrice},#{bookImg},#{bookDate},#{bookDesc}) </insert>
10.3.2 业务逻辑层实现
-
在BookService接口中定义添加业务方法
public interface BookService { public PageBean listBooks(int pageNum, int pageSize); public int addBook(Book book); }
-
在BookServiceImpl实现类中实现添加图书业务
@Service public class BookServiceImpl implements BookService { @Autowired private BookDAO bookDAO; public PageBean listBooks(int pageNum, int pageSize) { //.... return bookPageBean; } public int addBook(Book book) { int i = bookDAO.insertBook(book); return i; } }
10.3.3 业务流程实现
- 图片异步上传流程图
-
设计book-add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="" method="post"> <p>名称:<input type="text" name="bookName"/></p> <p>作者:<input type="text" name="bookAuthor"/></p> <p>价格:<input type="text" name="bookPrice"/></p> <p>图片: <br/> <img src="" height="100" id="imgTag"/><br/> <input type="file" id="bookImgFile"/> <input type="hidden" name="bookImg" id="bookImg"/> </p> <p>日期:<input type="text" name="bookDate"/></p> <p>描述:<input type="text" name="bookDesc"/></p> <p><input type="submit" value="提交"/></p> </form> </body> </html>
-
当选择图片触发ajax异步提交图片信息到控制器
<img src="" height="100" id="imgTag"/><br/> <input type="file" onchange="uploadImg()" id="bookImgFile"/> <input type="hidden" name="bookImg" id="bookImg"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script> <script type="text/javascript"> function uploadImg(){ //前端提交图片:1.表单post提交文件,2.非压缩提交 var file = $("#bookImgFile")[0].files[0]; var formData = new FormData(); formData.append("bookImgFile",file); $.ajax({ url:"file/upload", type:"post", data:formData, processData:false, contentType:false, success:function(res){ console.log(res); } }); } </script>
-
创建接收上传图片的控制器
-
导入文件上传所需要的jar
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
-
SpringMVC文件上传配置: 在Spring配置文件配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10240000"/> <property name="maxInMemorySize" value="102400"/> <property name="defaultEncoding" value="utf-8"/> </bean>
-
在控制器接收文件
@Controller @RequestMapping("/file") public class FileController { @ResponseBody @RequestMapping("/upload") public Map<String, String> upload(MultipartFile bookImgFile, HttpServletRequest request) throws IOException { //文件保存 String originalFilename = bookImgFile.getOriginalFilename(); String ext = originalFilename.substring(originalFilename.lastIndexOf(".")); String fileName = UUID.randomUUID().toString().replace("-","")+ext; String dir = request.getServletContext().getRealPath("images"); bookImgFile.transferTo( new File(dir+"/"+fileName)); Map<String, String> map = new HashMap<String, String>(); map.put("filePath","images/"+fileName); return map; } }
-
在book-add.jsp将文件上传请求返回的图片路径设置到img标签的src属性 和 隐藏域的value属性
<script type="text/javascript"> function uploadImg(){ //前端提交图片:1.表单post提交文件,2.非压缩提交 var file = $("#bookImgFile")[0].files[0]; var formData = new FormData(); formData.append("bookImgFile",file); $.ajax({ url:"file/upload", type:"post", data:formData, processData:false, contentType:false, success:function(res){ if(res.code == "200"){ $("#imgTag").attr("src",res.filePath); $("#bookImg").val(res.filePath); } } }); } </script>
-
在BookController创建保存图书的方法(创建tips.jsp提示页面)
@RequestMapping("/add") public String add(Book book,Model model){ int i = bookService.addBook(book); String tips = i>0? "<label style='color:green'>添加成功!</label>": "<label style='color:red'>添加失败!</label>"; model.addAttribute("tips",tips); return "/tips.jsp"; }
-
book-add.jsp提交图书信息到 book/add (保证输入框的name属性与控制器Book对象属性名一致)
<form action="book/add" method="post"> <p>名称:<input type="text" name="bookName"/></p> <p>作者:<input type="text" name="bookAuthor"/></p> <p>价格:<input type="text" name="bookPrice"/></p> <p>图片: <br/> <img src="" height="100" id="imgTag"/><br/> <input type="file" onchange="uploadImg()" id="bookImgFile"/> <input type="hidden" name="bookImg" id="bookImg"/> </p> <p>日期:<input type="text" name="bookDate"/></p> <p>描述:<input type="text" name="bookDesc"/></p> <p><input type="submit" value="提交"/></p> </form>
-
tips.jsp页面显示提示信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${tips} </body> </html>
-
";
model.addAttribute(“tips”,tips);
return “/tips.jsp”;
}
```
-
book-add.jsp提交图书信息到 book/add (保证输入框的name属性与控制器Book对象属性名一致)
<form action="book/add" method="post"> <p>名称:<input type="text" name="bookName"/></p> <p>作者:<input type="text" name="bookAuthor"/></p> <p>价格:<input type="text" name="bookPrice"/></p> <p>图片: <br/> <img src="" height="100" id="imgTag"/><br/> <input type="file" onchange="uploadImg()" id="bookImgFile"/> <input type="hidden" name="bookImg" id="bookImg"/> </p> <p>日期:<input type="text" name="bookDate"/></p> <p>描述:<input type="text" name="bookDesc"/></p> <p><input type="submit" value="提交"/></p> </form>
-
tips.jsp页面显示提示信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${tips} </body> </html>