SpringMVC整合以及案例

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 为例

  1. 创建状态异常跳转页面 404.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
        	您访问的页面不存在,请检查输入的网址是否正常。
        </body>
    </html>
    
  2. 在web.xml文件中配置异常状态码和异常页面的映射

    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
    
7.2 程序异常统一处理

程序抛出的各种exception: NullPointerException ArithmeticException…

  1. Servlet处理方式:

    <error-page>
        <exception-type>java.lang.NullPointerException</exception-type>
        <location>/err.jsp</location>
    </error-page>
    
  2. 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 自定义拦截器
  1. 创建拦截器

    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");
        }
    }
    
  2. 配置拦截器: 在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 数据库操作实现
  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;
        
    }
    
  2. 创建DAO接口,定义操作方法

    public interface BookDAO {
        
        public List<Book> selectBooks(); 
        
    }
    
  3. 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 业务逻辑层实现
  1. 创建分页帮助类

    @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;
    
    }
    
  2. 添加MyBatis分页插件

    • 添加依赖
    • 配置分页插件
  3. 创建servcie接口

    public interface BookService {
    
        public PageBean listBooks(int pageNum, int pageSize);
    
    }
    
  4. 创建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 业务流程实现
  1. 创建控制器及处理图书列表请求的方法

    @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";
        }
        
    }
    
  2. 创建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>
    
  3. 在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 数据库操作实现
  1. 在BookDAO中定义添加方法

    public interface BookDAO {
    
        public List<Book> selectBooks();
    
        public int insertBook(Book book);
    
    }
    
  2. 配置映射文件

    <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 业务逻辑层实现
  1. 在BookService接口中定义添加业务方法

    public interface BookService {
    
        public PageBean listBooks(int pageNum, int pageSize);
        
        public int addBook(Book book);
    
    }
    
  2. 在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 业务流程实现
  1. 图片异步上传流程图

在这里插入图片描述

  1. 设计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>
    
  2. 当选择图片触发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>
    
  3. 创建接收上传图片的控制器

    • 导入文件上传所需要的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;
          }
      
      }
      
    1. 在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>
      
    2. 在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";
      }
      
    3. 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>
      
    4. 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”;
}
```

  1. 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>
    
  2. tips.jsp页面显示提示信息

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
        	${tips}
        </body>
    </html>
    
Spring SpringMVC 简单整合(初学者参考) demo项目对应地址说明 :https://blog.youkuaiyun.com/tianyu00/article/details/89186404 SpringMVC流程 1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。 4、 DispatcherServlet调用HandlerAdapter处理器适配器。 5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。 6、 Controller执行完成返回ModelAndView。 7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。 8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。 9、 ViewReslover解析后返回具体View。 10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。 11、 DispatcherServlet响应用户。 组件说明: 以下组件通常使用框架提供实现: DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。 HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。 ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值