SpringMVC

一、SpringMVC

1.1 引言

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。

Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。

使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等等。

1.2 MVC架构
1.2.1 概念
名称职责
Model模型:即业务模型,负责完成业务中的数据通信处理,对应项目中的 service和dao
View视图:渲染数据,生成页面。对应项目中的Jsp
Controller控制器:直接对接请求,控制MVC流程,调度模型,选择视图。对应项目中的Servlet
1.2.2 好处
  • MVC是现下软件开发中的最流行的代码结构形态;
  • 人们根据负责的不同逻辑,将项目中的代码分成 M V C 3个层次;
  • 层次内部职责单一,层次之间耦合度低;
  • 符合低耦合 高内聚的设计理念。也实际有利于项目的长期维护。
1.2.3 执行流程
SpringMVC执行流程
在这里插入图片描述

二、开发流程

2.1 导入依赖
 <!--  导入Spring的依赖  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.6</version>
</dependency>
<!--  导入SpringMVC的依赖  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.6</version>
</dependency>
2.2 配置核心(前端)控制器

作为一个MVC框架,首先要解决的是:如何能够收到请求!

所以MVC框架大都会设计一款前端控制器,选型在 Servlet 或 Filter两者之一,在框架最前沿率先工作,接收所有请求。

此控制器在接收到请求后,还会负责springMVC的核心的调度管理,所以既是前端又是核心。

<?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">
    <!--  配置前端控制器  -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--   加载Springmvc的配置文件     -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>    
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--
               完全匹配
                    /aaa     /hello   /user/xxx
               通配符匹配
                    /          匹配所有路径     不包含.jsp
                    /*         匹配所有路径
               后缀名匹配
                    *.xxx       *.do     *.action
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>  
</web-app>
2.3 springmvc核心配置文件
<?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: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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启Spring的注解扫描-->
    <context:component-scan base-package="com.qf"/>
    <!--开启SpringMVC的注解扫描-->
    <mvc:annotation-driven />
    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
2.4 创建处理器(Handler)
@Controller
public class TestController {
    @RequestMapping("/test01")
    public String test01(){
        return "success";
    }
}
2.5 测试访问

http://localhost:8080/test01

三、接收请求参数

3.1 使用原生ServletAPI获取

使用HttpServletRequest对象获取参数

@RequestMapping("/test01")
public String test01(HttpServletRequest request){
    System.out.println(request.getParameter("name"));
    System.out.println(request.getParameter("age"));
    return "success";
}
3.2 基本类型参数

请求参数和方法的形参 同名即可

@RequestMapping("/test02")
public String test02(String name,int age){
    System.out.println(name);
    System.out.println(age);
    return "success";
}

请求路径:http://localhost:8080/test2?name=cxk&age=20

3.3 实体收参【重点

请求参数和实体的属性 同名即可

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
    private Double money;
}
@RequestMapping("/test03")
public String test03(User user){
    System.out.println(user);
    return "success";
}
<form action="/springmvc02__war_exploded/test03" method="post">
    用户名:<input name="name" type="text"><br>
    年龄:<input name="age" type="text"><br>
    金额:<input name="money" type="text"><br>
    <input name="hobby" type="checkbox" value="lq">打篮球<br>
    <input type="submit" value="提交">
</form>
3.4 接收复杂类型参数

在一个类中包含另一个类的对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
    private Double money;
    private Product product;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private String name;
    private Double price;
}

前端传参

<form action="/springmvc02__war_exploded/test03" method="post">
    用户名:<input name="name" type="text"><br>
    年龄:<input name="age" type="text"><br>
    金额:<input name="money" type="text"><br>
    商品名称:<input name="product.name" type="text"><br>
    商品价格:<input name="product.price" type="text"><br>
    <input type="submit" value="提交">
</form>

后端收值

@RequestMapping("/test03")
public String test03(User user){
    System.out.println(user);
    return "success";
}
3.5 接受数组类型参数

前端传参

<form>
    .....
   	爱好:
    <input name="hobby" type="checkbox" value="song"><input name="hobby" type="checkbox" value="tiao"><input name="hobby" type="checkbox" value="rap">rap
    <input name="hobby" type="checkbox" value="lq">打篮球<br>
    .....
</form>

后端收值

@RequestMapping("/test04")
public String test04(String[] hobby){
    System.out.println(Arrays.toString(hobby));
    return "success";
}
3.6 接收Date类型参数
3.6.1 解决1:使用自定义类型转换器

定义自定义转换类

@Component
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        if(s != null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date date = sdf.parse(s);
                return  date;
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

配置自定义类型转换器

<!-- 自定义类型转换器  -->
<bean id="myConverter" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <ref bean="dateConverter"></ref>
        </set>
    </property>
</bean>

配置SpringMVC使用自定义类型转换器

<mvc:annotation-driven conversion-service="myConverter"/>
3.6.2 解决2: 使用@DateTimeFormat注解

在类的属性中或者方法形参上直接添加注解

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String username;
    private String password;
    private Integer age;
    private String[] hobby;
    private String sex;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    private Book book;
}
3.7 中文乱码问题

在web.xml文件中配置编码过滤器

<!-- 配置编码过滤器-->
<filter>
    <filter-name>enCoding</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>enCoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

四、跳转

Controller中方法的返回值

  • 1、void (利用原生的ServletAPI实现跳转)
  • 2、String (利用视图解析器实现跳转、利用两个关键字实现页面跳转)
  • 3、ModelAndView (利用视图解析器实现跳转)
4.1 利用原生的ServletAPI实现跳转
 @RequestMapping("/test01")
public void test01(HttpServletRequest request, HttpServletResponse response) throws IOException {
    //重定向
    response.sendRedirect(request.getContextPath()+"/pages/ok.jsp");
}
@RequestMapping("/test02")
public void test02(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    //转发
    request.getRequestDispatcher("/pages/ok.jsp").forward(request,response);
}
4.2 利用视图解析器实现跳转
@RequestMapping("/test03")
public String test03()  {
    return "ok"; //转发
}
4.3 利用两个关键字实现页面跳转
@RequestMapping("/test04")
public String test04()  {
    return "redirect:/pages/ok.jsp"; //重定向
}
@RequestMapping("/test05")
public String test05()  {
    return "forward:/pages/ok.jsp"; //转发
}
4.4 利用ModelAndView实现页面跳转
@RequestMapping("/test06")
public ModelAndView test06()  {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("ok");
    return modelAndView;
}

五、SpringMVC中的注解

5.1 @RequestMapping

表示请求的映射路径

/**
 *  @RequestMapping注解
 *      value  :表示请求路径
 *      method :表示请求方式(restful)
 *      params :表示请求参数(必填)
 *
 *      headers:表示请求头信息
 *      consumes:请求的MIME配置    text/html   application/json
 *      produces:响应的MIME配置
 */
@RequestMapping(value = {"/test01","/test001"},
                method= RequestMethod.POST,params={"name","age"})
public String test01(String name,int age){
    System.out.println(name);
    System.out.println(age);
    return "success";
}

该注解可以添加在类上。可以用于窄化请求

@RequestMapping("/user") //窄化请求路径,表示在每一个映射路径的前面添加了此路径

那么以后请求该类中的方法,都需要添加 /user

5.2 @RequestParam

表示处理请求的参数

/**
     *  @RequestParam注解
     *   value: 当请求参数与接收的参数不一致,通过value指定
     *   required:是否设置为必填参数。(默认为true)
     *   defaultValue:参数的默认值(在没有传递参数的时候生效)
     */
@RequestMapping("/test02")
public String test02(@RequestParam(value = "username",required=true,defaultValue="cxk")
                     String name){
    System.out.println(name);
    return "success";
}
5.3 @PathVariable

表示获取路径上的参数

/**
* @PathVariable   获取路径 参数
*    /test03/{id}
*    @PathVariable("id") int id
*
*/
@RequestMapping("/test03/{id}")
public String test03(@PathVariable("id") int id){
    System.out.println(id);
    return "success";
}
5.4 @ModelAttribute

优先于当前Controller中其他的方法先执行

/**
*  @ModelAttribute  在所有当前Controller的请求方法之前执行
*/
@ModelAttribute //     /user
public User test04(User user){  //传入user对象的时候属性值并不全
    //System.out.println("执行了吗?、、、");
    //假设, 根据用户名查询数据库返回user对象
    user.setName("aaa");
    user.setAge(30);
    user.setMoney(1000d);
    return user;
}

该注解在执行其他方法之前先执行,可以先利用接收到的参数,去查询数据库,拿到完整的数据,然后通过方法的返回值再传递到其他的请求方法上

六、向前端传值


Controller得到数据后,跳转到View,并向View传递数据。

进而View中可以渲染数据,让用户看到含有数据的页面

6.1 通过原生Servlet的API向前端响应数据

Servlet中的三大域对象

  • request域
  • session域
  • application域
@RequestMapping("/test01")
public String test01(HttpServletRequest request){
    request.setAttribute("requestMsg","request对象");
    request.getSession().setAttribute("sessionMsg","session对象");
    request.getServletContext().setAttribute("applicationMsg","application对象");
    return "success";
}
6.2 通过Model对象

相当与request域

@RequestMapping("/test02")
public String test02(Model model){
    model.addAttribute("model","model数据");
    System.out.println(model.getAttribute("name"));
    return "success";
}
6.3 通过ModelAndView

相当与request域

@RequestMapping("/test03")
public ModelAndView test03(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("success");
    modelAndView.addObject("modelandview","ModelAndView数据...");
    return modelAndView;
}
6.4 通过SessionAttributes

将model中的指定数据保存到Session中.可以实现共享

//将保存在model中属性值,保存到session域中,而且在其他的地方可以通过model可以获取。实现共享
@SessionAttributes({"name","age"}) 
public class TestController {
    //保存数据
    @RequestMapping("/test04")
    public String test04(String name,int age,Model model){
        model.addAttribute("name",name);
        model.addAttribute("age",age);
        return "success";
    }
    
    @RequestMapping("/test02")
    public String test02(Model model){
        System.out.println(model.getAttribute("name"));
        return "success";
    }
}
6.5 JSP页面取值

主要通过EL表达式和JSTL

${requestMsg}-----> ${sessionMsg}-----> ${applicationMsg}
<hr>
${requestScope.model}----->${sessionScope.model}----->${applicationScope.model}
<hr>
${requestScope.modelandview}----->${sessionScope.modelandview}----->${applicationScope.modelandview}
<hr>
${requestScope.name}----->${sessionScope.name}----->${applicationScope.name}

七、Json交互

7.1 导入依赖
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.2</version>
</dependency>
7.2 使用@ResponseBody

@ResponseBody作用:将方法的返回值类型转换成json字符串,返回给前端

可以加在方法上,也可以加在类上

@Controller
@ResponseBody   //所有请求方法的返回值都会转成json返回到前端
public class TestController {
    @RequestMapping("/json1")
    public void json1(HttpServletResponse response){
        try {
            User user = new User("张三",30,1000d);
            ObjectMapper mapper = new ObjectMapper();
            response.setContentType("application/json;charset=utf-8");
            String json = mapper.writeValueAsString(user);
            response.getWriter().write(json);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @RequestMapping("/json2")
    public  User json2(){
        User user = new User("张三1",31,1010d);
        return user;
    }
    @RequestMapping("/json3")
    public List<User> json3(){
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            userList.add(new User("张三"+i,31,1010d));
        }
        return userList;
    }
    @RequestMapping(value = "/json4",produces = "application/json;charset=utf-8")
    public  String json4(){
        return "hello,中文";
    }
}

7.3 使用@RestController

Controller类上加了@RestController注解,等价于在类中的每个方法上都加了@ResponseBody

@RestController = @Controller + @ResponseBody

@RestController  //那么这个Controller中不能使用转发、重定向,不走视图解析器。     纯前后端分离项目使用
public class TestController {
    @RequestMapping("/json2")
    public  User json2(){
        User user = new User("张三1",31,1010d);
        return user;
    }
    @RequestMapping("/json3")
    public List<User> json3(){
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            userList.add(new User("张三"+i,31,1010d));
        }
        return userList;
    }
    @RequestMapping(value = "/json4",produces = "application/json;charset=utf-8")
    public  String json4(){
        return "hello,中文";
    }
}
7.4 使用@RequestBody

@RequestBody作用:将前端传递的Json格式的字符串自动转换为java对象

7.4.1 前端请求

7.4.2 定义Controller
@Controller
public class JsonController {
    @RequestMapping("/sendJson")
    public String sendJson(@RequestBody User user){
        System.out.println(user);
        return "ok";
    }
}

八、异常解析器

8.1 异常解析器,统一处理

Controller中的抛出需要集中处理的异常。

定义一个“异常解析器” 集中捕获处理 所有异常

此种方案,在集中管理异常方面,更有优势!

定义统一异常处理类

@Component //当Controller层抛出异常(没有处理)就执行。
public class ExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o,
                                         Exception e) {
        //根据不同的异常,做出冉的结果
//        if(e instanceof  UsernameException){
//            modelAndView.setViewName("error");
//        }else if(e instanceof  XXXException){
//            modelAndView.setViewName("error");
//        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

九、文件上传

9.1 导入文件上传依赖
<!--   文件操作的依赖  -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
<!--   fileupload 文件上传的依赖  -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
9.2 文件上传表单
<%--
    文件上传的表单要求:
        method:请求方式必须是post
        enctype:multipart/form-data 二进制流的形式
--%>
<form action="${pageContext.request.contextPath}/upload" method="post" 
      enctype="multipart/form-data">
    用户名:<input type="text" name="name"><br>
    文件:<input type="file" name="file"><br>
    <input type="submit" value="上传">
</form>
9.3 配置文件上传解析器
<!-- 配置文件上传解析器   -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--  配置上传文件的总大小       -->
    <property name="maxUploadSize" value="10000000"></property>
    <!--  配置上传文件的单个大小       -->
    <property name="maxUploadSizePerFile" value="2000000"></property>
    <!--  配置文件上传的编码-->
    <property name="defaultEncoding" value="UTF-8"></property>
</bean>
9.4 定义Controller
@Controller
public class UploadController {
    @RequestMapping("/upload")
    public String uploadFile(String name, MultipartFile file, HttpServletRequest request){
        //1、文件名冲突(UUID)
        //2、保存路径(当前项目|本地磁盘)
        //---------------------------------------------
        try {
            //获取上传的文件名称
            String filename = file.getOriginalFilename();
            //获取文件的后缀
            String fileExt = FilenameUtils.getExtension(filename);
            //得到新的文件名称
            String newFileName = UUID.randomUUID().toString().replace("-","")+"."+fileExt;
            //获取当前项目中的upload文件夹的路径
            String realPath = request.getServletContext().getRealPath("/upload");
            //判断文件夹是否存在,不存在则创建
            File f = new File(realPath);
            if(!f.exists()){
                f.mkdirs();
            }
            //得到最终的文件保存路径
            String filePath = realPath + "\\" + newFileName;
            //上传文件
            file.transferTo(new File(filePath));
            return "success";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "fail";
    }
}

十、文件下载

10.1 定义下载链接
<a href="${pageContext.request.contextPath}
         /download?name=7fe28f2ecb07492bb01310f6897bbc25.jpg">点击下载</a>
10.2 定义Controller
@Controller
public class DownloadController {
    @RequestMapping("/download")
    public void download(String name, HttpServletRequest request, HttpServletResponse resp) throws IOException {
        //根据文件名找到对应的文件,然后通过IO流写到客户端(这就是响应)
        String realPath = request.getServletContext().getRealPath("/upload");
        //得到最终的路径
        String filePath =  realPath + "\\" + name;
        //设置响应头,告知浏览器是下载操作。
        resp.setHeader("Content-Disposition","attachment;filename="+name);
        //通过IO流响应给客户端
        IOUtils.copy(new FileInputStream(filePath),resp.getOutputStream());
    }
}

十 一、SSM整合

整合思路:

Spring整合MyBatis,将MyBatis的实例交给Spring进行管理

Spring整合AOP声明式事务管理

Spring整合SpringMVC,无需额外配置操作

启动tomcat,加载Spring的配置文件

11.1 依赖
<!-- mybatis相关   -->
<!-- 导入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>5.1.47</version>
</dependency>
<!-- 引入log4j的日志依赖 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<!-- 引入德鲁伊连接池依赖 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
<!-- 引入分页插件依赖 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

<!-- spring相关   -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<!--Spring整合持久层框架的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<!--MyBatis整合 Spring的依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
</dependency>
<!--  SpringAOP的依赖  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!-- Spring 声明式事务依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!-- Spring Aop 切面织入依赖 -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>
<!-- SpringMVC 相关 -->

<!-- SpringMVC的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<!-- 导入jackson依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.10</version>
</dependency>
<!--   文件操作的依赖  -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

<!--   fileupload 文件上传的依赖  -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- servlet依赖-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<!-- jsp依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
</dependency>
<!-- jstl依赖 -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>jstl-impl</artifactId>
    <version>1.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 测试相关 -->
<!-- 导入junit依赖 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<!-- Spring 整合Junit的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<!-- 导入lombok依赖 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
</dependencies>
11.2 配置文件
11.2.1 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">
    <!-- 配置加载Spring的配置文件-->
    <listener>
        <!--  springmvc提供的监听器,当tomcat容器启动的时候执行      -->
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--  加载指定的配置文件  -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
    </context-param>

    <!-- 配置编码过滤器-->
    <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置前端控制器 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
11.2.2 spring配置
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.qf" use-default-filters="false">
        <!--  扫描com.qf下的所有注解,但是排除Controller上的注解   -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>
11.2.3 spring-mybatis配置
<!-- 导入外部的配置文件  -->
<context:property-placeholder location="classpath:mybatis/db.properties"/>

<!--  配置数据源  -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<!--  配置SqlSessionFactoryBean  -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
</bean>

<!--  配置MapperScannerConfigurer  -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.qf.mapper"/>
</bean>
11.2.4 spring-tx配置
<import resource="classpath:spring/applicationContext-mybatis.xml"></import>
<!--  配置事务管理器  -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置增强类   -->
<tx:advice transaction-manager="transactionManager" id="myAdvice">
    <tx:attributes>
        <tx:method name="select*" propagation="SUPPORTS" read-only="true" isolation="DEFAULT"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true" isolation="DEFAULT"/>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true" isolation="DEFAULT"/>
        <tx:method name="query*" propagation="SUPPORTS" read-only="true" isolation="DEFAULT"/>
        <tx:method name="*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
    </tx:attributes>
</tx:advice>
<!-- 配置事务切面   -->
<aop:config>
    <aop:pointcut id="pc" expression="execution(* com.qf.service..*.*(..))"/>
    <aop:advisor advice-ref="myAdvice" pointcut-ref="pc"></aop:advisor>
</aop:config>
11.2.5 mybatis配置
<!--mybatis的配置信息-->
<configuration>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <!--  取别名:不区分大小的。使用package给整个包取别名 默认的别名就是实体类的名字-->
    <typeAliases>
        <!-- 给整个包下所有的实体类都取了别名   -->
        <package name="com.qf.pojo"/>
    </typeAliases>
    <plugins>
        <!-- com.github.pagehelper为PageHelper类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>
11.2.6 数据源配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///java2008
jdbc.username=root
jdbc.password=123456
11.2.7 日志配置
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
11.3 Mapper层
11.3.1 Mapper接口
public interface BookMapper {
    List<Book> getAll();
}
11.3.2 Mapper映射文件
<mapper namespace="com.qf.mapper.BookMapper">
	<select id="getAll" resultType="book">
        select * from book
    </select>
</mapper>
11.4 Service层
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    BookMapper bookMapper;
    @Override
    public List<Book> getAll() {
        return bookMapper.getAll();
    }
}
11.5 Controller层
@Controller
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    @RequestMapping("/getAll")
    public String getAll(Model model){
        List<Book> bookList = bookService.getAll();
        model.addAttribute("bookList",bookList);
        return "success";
    }
}
11.6 前端JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <table width="80%" border="1px" align="center" 
           cellpadding="10px" cellspacing="0px" bgcolor="#66cdaa">
        <tr>
            <th>编号</th>
            <th>图书图片</th>
            <th>图书名称</th>
            <th>图书作者</th>
            <th>图书价格</th>
            <th>图书销量</th>
            <th>图书状态</th>
            <th>出版时间</th>
        </tr>
        <c:forEach items="${bookList}" var="book">
            <tr>
                <td>${book.bookId}</td>
                <td><img src="${book.image}" width="100px" height="100px"></td>
                <td>${book.name}</td>
                <td>${book.author}</td>
                <td>${book.price}</td>
                <td>${book.total}</td>
                <td>${book.status == 0 ? "不可借" : "可借"}</td>
                <td><fmt:formatDate pattern="yyyy-MM-dd" value="${book.time}">
                    </fmt:formatDate></td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值