一、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>