1. 基础了解
1.1 mvc
MVC三层架构
spring:ioc 和 aop
springmvc:springmvc的执行流程
springmvc:ssm框架整合
mvc
mvc是一种软件设计规范, 将业务的逻辑,数据,显示分离的方式来组织代码
- 模型(dao,service)
- 视图(jsp)
- 控制器(servlet)
mvc框架做哪些事情?
- 将url映射到java类或java类的方法
- 封装用户提交的数据
- 处理请求-调用相关的业务处理-封装响应数据
- 将相应的数据进行渲染,jsp/html 等表示层数据
1.2 springmvc
我们为什么要学习springmvc
- 轻量级,简单易学
- 高效,基于请求响应的mvc框架
- 与spring兼容性好,无缝结合
- 约定大于配置
- 功能强大:RESTful,数据验证,格式化,本地化,主题等
- 简洁灵活
- 使用的人多,使用的公司多
dispatcherservlet继承关系
springmvc执行流程
2.入门sprigmvc
2.1 hello springmvc
- 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">
<!---->
<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:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<!--/:匹配所有请求,不包括jsp-->
<!--/*:匹配所有请求,包括jsp-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--handler-->
<bean id="/hello" class="edu.controller.HelloController"></bean>
</beans>
特别说明:如果aop没有定义切入点等,就不要使用aop相关约束
- servlet
package edu.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "hello springmvc!");
modelAndView.setViewName("hello");
return modelAndView;
}
}
- jsp 文件放在web-inf文件夹下,客户端不能直接访问,保护视图安全
<%--
Created by IntelliJ IDEA.
User: root
Date: 2021/10/1
Time: 11:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>${
msg}</h1>
</body>
</html>
有时候我们会发现代码没问题但是访问404,这个时候我们就要查看project struct然后查看artifacts结构下,看看项目的web-inf目录下是否有相应的jar包,因为tomcat运行需要相应的jar包依赖,如果没有,就在web-inf下新建一个lib包,然后把所有的maven依赖加入其中,然后重启tomcat即可
- 效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hd1gInjs-1633245411551)(狂神说springmvc.assets/image-20211001141137950.png)]
其中实线部分是springmvc做的,虚线是程序员做的
2.2 注解开发
- 配置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">
<!--配置DispatcherServlet: 这个是springmvc的核心:请求分发器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispatcherServlet要绑定springmvc的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别:1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/:匹配所有请求,不包括jsp-->
<!--/*:匹配所有请求,包括jsp-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 配置springmvc-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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<!--扫描包-->
<context:component-scan base-package="edu.controller"></context:component-scan>
<!--让springmvc不处理静态资源-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--自动配置映射器和适配器-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--配置视图解析器 *模板引擎 Thymeleaf freemarker*
1.获取ModelAndView的数据
2.解析ModelAndView的视图名字
3.拼接视图名字,找到对应的视图
4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--BeanNameUrlHandlerMapping:bean handler-->
</beans>
- 书写controller
package edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/*
* 如果类上也加入了RequestMapping注解,那么访问路径就要加上这一部分内容,相当于加了一个分级
* */
@Controller
@RequestMapping("HelloController")
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
// 封装数据
model.addAttribute("msg", "hello,springmvc!");
return "hello"; // 会被视图解析器处理,这里就写视图的名称
}
}
- 结果
3.springmvc再了解
3.1 controller and restful风格
控制器controller
- 控制器负责提供访问应用程序的行为,通常通过接口定义或注解定义两种方式实现
- 控制器负责解析用户的请求并将其转换为一个模型
- 在springmvc中一个控制类可以包含多个方法
- 在springmvc中,controller的配置方式有很多种
controller实现
- 实现接口Controller,同时将实现类注入spring容器中
- 实现Controller接口定义控制器是比较老的办法,不推荐使用
- 一个控制器中只能有一个方法,多个方法需要定义多个controller,不方便
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.servlet.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;
@FunctionalInterface
public interface Controller {
@Nullable
ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
- 使用@Controller注解
- 注解的类中的所有方法,如果返回值是string并且有具体的页面可以跳转,就会被视图解析器解析
- 可以定义多个方法
- 方法中可以定义多种模型和视图类
- 多个方法可以对应一个视图,但是其中的数据是不一样的
restful风格
restful是一种资源定位以及操作的风格.不是标准也不是协议,只是一种风格.基于这个风格设计的软件可以更简洁,更有层次,更容易实现缓存等机制.
- 以前的方式:http://localhost:8080/add?a=1&b=2
- 现在的方式:http://localhost:8080/add/1/2
传参的时候,只需要在处理方法上对应的变量位置加上@PathVariable注释,就可以使用restful风格的url了
- 样例
package edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RestfulController {
/*
* 原来的风格:http://localhost:8080/add?a=1&b=2
* restful风格:http://localhost:8080/add/a/b
* */
@RequestMapping("/add/{a}/{b}")
public String test01(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg", "res:" + res);
return "hello";
}
}
restful同时也具有更多的请求方式
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.bind.annotation;
public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
private RequestMethod() {
}
}
同时可以在请求的时候指定请求的方式(例如使用get方式请求)
package edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class RestfulController {
@RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
public String test01(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg", "res:" + res);
return "hello";
}
}
所有的地址栏请求默认都是GET方式
方法级别的注解变体有如下几个
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
- 可以同时用不同的请求方式请求相同的路径,我们可以在这上面做不同的处理
例子
package edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class RestfulController {
@RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
public String test01(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg", "res:" + res);
return "hello";
}
@PostMapping("/add/{a}/{b}")
public String test02(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg", "second res:" + res);
return "hello";
}
}
使用路径变量的好处
- 使路径变的更加简洁
- 获得参数更加方便,框架会自动进行类型转换
- 通过路径变量的类型可以约束访问的参数,如果类型不一样,则访问的不到对应的请求方法.
- 更加安全
3.2 @RequestMapping注解
@RequestMapping("/xxx")
-
@RequestMapping注解用于映射url到控制器类或一个特定处理程序的方法.可用于类或方法上.用于类上,表示类中所有相应请求的方法都是以该地址作为父路径
-
只注解在方法上
http:locahost:8080/项目名/方法上的注解内容
-
注解在类和方法上
http:locahost:8080/项目名/类上的注解内容/方法上的注解内容
3.3 springmvc结果跳转方式
3.3.1 ModelAndView
设置ModelAndView对象,根据view的名称和视图解析器跳转到指定的页面
页面:{视图解析器前缀}+viewName+{视图解析器后缀}
视图解析器
<!--配置视图解析器 *模板引擎 Thymeleaf freemarker*
1.获取ModelAndView的数据
2.解析ModelAndView的视图名字
3.拼接视图名字,找到对应的视图
4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
类
package edu.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// ModelAndView 模型和视图
ModelAndView modelAndView = new ModelAndView();
// 封装对象
modelAndView.addObject("msg", "hello springmvc!");
// 封装要跳转的视图,放在ModelAndView中
modelAndView.setViewName("hello");
return modelAndView;
}
}
3.3.2 ServletAPI
通过设置ServletAPI来进行页面跳转,不需要视图解析器:
- 通过HttpServletResponse进行输出
- 通过HttpServletResponse实现重定向
- 通过HttpServletRequest实现请求转发
为什么可以直接用?
因为controller本身就是一个servlet
3.3.3 通过springmvc
通过springmvc来实现,无需视图解析器
package edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class springmvcController {
@GetMapping("/t1")
public String test01(Model model){
model.addAttribute("msg", "转发1");
return "/WEB-INF/jsp/hello.jsp";
}
@GetMapping("/t2")
public String test02(Model model){
model.addAttribute("msg", "转发2");
return "forward:/WEB-INF/jsp/hello.jsp";
}
@RequestMapping("/t3")
public String test03(Model model){
model.addAttribute("msg", "重定向");
return "redirect:/index.jsp";
}
}
3.4 接受请求参数以及回显
-
提交的域名称和处理方法的参数名一致就可以直接接收
-
提交的域名称和处理方法的参数名不一致
- 可以在参数前加@RequestParam(“xxx”)优化,变成和域名称一致
- 无论一样不一样,只要是接收前端数据的,都要写上
-
提交的是一个对象,要求提交的表单域和对象的属性名一致,参数使用对象即可(对象需要又set方法)
测试
package edu.controller;
import edu.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/user")
public class UserController {
/*
* 提交的域名称和处理方法的参数名一致就可以直接接收
* */
@RequestMapping("/t1")
public String test01(String name, Model model){
model.addAttribute("msg", name);
return "hello";
}
/*
* 提交的域名称和处理方法的参数名不一致
* */
@RequestMapping("/t2")
public String test02(@RequestParam("names") String name, Model model){
model.addAttribute("msg", name);
return "hello";
}
/*
* 前端提交了一个对象
* 传递的是个对象,匹配user中的字段名,名字一致就可以
* */
@RequestMapping("/t3")
public String test02(User user, Model model){
model.addAttribute("msg", user.toString());
return "hello";
}
}
3.4.1 数据回显到前端
- 通过ModelAndView (显示实现controller接口时常用)
- 通过Model (使用controller注解时常见)
- 通过ModelMap (继承了LinkedHashMap)
3.5 乱码问题
springmvc给我们提供了一个解决乱码的过滤器,直接在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>
3.6 JSON
什么是JSON
- json(js对象标记)是一种轻量级的数据交换格式,目前使用的特别广泛
- 采用完全独立于编程语言的文本格式来存储和表示数据
- 简洁和清晰的层次结构使得json成为理想的数据交换语言
- 易于阅读和编写,同时也易于机器解析和生成,并有效的提高网络传输速率
前后端分离
- 后端部署后端,提供接口,提供数据
- 前端独立部署,负责渲染后端的数据
- json作为前后端数据交换的格式
在js语言中,一切都是对象.因此,任何js支持的类型都可以通过json来表示,例如字符串,数字,对象,数组等.看看他的要求和语法格式.
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
{"name", "kuquan"}
{"age", "18"}
{"sex", "man"}
json和js对象可以很容易的相互转化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
// 编写js对象
var user = {
name: "kuquan",
age: "3",
sex: "man"
};
// 将js对象转换为json对象
var json = JSON.stringify(user);
// 将json对象转换成一个字符串
var obj = JSON.parse(json);
console.log(json)
console.log(obj)
</script>
</head>
<body>
</body>
</html>
- 效果
3.7 Controller返回json对象
- jackson应该是目前比较好的json解析工具了
- 当然工具不止一个,比如还有阿里巴巴的fastjson等等
- 我们使用jackson需要导入jar包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
jackson
- 测试.
objectMapper
将字符串封装成json格式
package edu.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
/*@ResponseBody
* 加上这就,就不会走视图解析器,直接返回字符串
* */
@ResponseBody
@RequestMapping("/json1")
public String json1() throws JsonProcessingException {
User user = new User("余生", 18, "man");
// jackson objectMapper
ObjectMapper objectMapper = new ObjectMapper();
String value = objectMapper.writeValueAsString(user);
return value;
}
}
- 结果
此时格式正确了,但是出现了乱码
解决方案
- 修改requestmapper为
@RequestMapping(value = "/json1", produces = "application/json;charset=utf-8")
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-paxB3AYH-1633245411554)(狂神说springmvc.assets/image-20211002111750760.png)]
- springmvc提供了统一的乱码解决方案
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
3.7.1**@RestController** and @ResponseBody
- @RestController类上如果加这样的标签,则都不会调用视图解析器,只会返回一个字符串
- @ResponseBody方法加上这就,就不会走视图解析器,直接返回字符串
3.7.2 返回多个对象时
@ResponseBody
@RequestMapping("/json2")
public String json2() throws JsonProcessingException {
User user1 = new User("余生", 18, "man");
User user2 = new User("苦泉", 18, "man");
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
return new ObjectMapper().writeValueAsString(list);
}
结果
objectmapper解析时间后的默认格式为timestamp(从1901-1-1到现在的毫秒数)
如何转化为可视化的时间?
- 使用simpledateformat格式化时间然后再传给objectmapper
3.7.3 封装一个json工具类
package edu.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
public static String getJson(Object o) throws JsonProcessingException {
return getJson(o, "yyyy-MM-dd");
}
public static String getJson(Object o, String format) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
/*
* 关闭默认使用时间戳
* */
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
/*
* 格式化
* */
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
objectMapper.setDateFormat(simpleDateFormat);
return objectMapper.writeValueAsString(o);
}
}
3.7.4 FastJson
阿里巴巴开发的专门用于java开发的包,方便实现json对象与json的转换.
4.整合ssm
- idea 2021.1.1
- mysql 5.5
- tomcat 9.0.19
- maven 3.6.3
4.1 搭建环境
- 建库建表
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
CREATE TABLE `books`(
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID`(`bookID`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`) VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');
- 导入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!--数据库连接池:c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
- maven资源导出问题
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 配置db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=xxx
jdbc.password=xxx
- 配置mybatis核心配置文件
<?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>
<settings>
<!--日志-->
<!--日志同一时间只能使用一个-->
<!--标准日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--LOG4J日志-->
<!--<setting name="logImpl" value="LOG4J"/>-->
<!--将经典数据库命名转化为驼峰命名-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启全局缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<!--另一种方式-->
<!--<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>-->
<!--可以给实体类写别名-->
<typeAliases>
<!--给具体的类起别名-->
<!--<typeAlias alias="User" type="bean.User"/>-->
<!--如果有bean类使用@Alias()注释,需要将相应的包在这里导入-->
<package name="edu.pojo"/>
</typeAliases>
<!--绑定接口-->
<mappers>
<!--接口需要和配置文件(xml)同名-->
<!--class注册方式:mapper文件需要放在resources/dao文件夹下-->
<!--<mapper class="dao.UserDao"></mapper>-->
<!--rsource注册方式:xml文件需要放在resources/dao文件夹下 or mapper.xml文件和mapper处在同一个包下-->
<!--<mapper resource="dao/UserMapper.xml"></mapper>-->
<!--<mapper resource="dao/BlogMapper.xml"></mapper>-->
<mapper class="edu.mapper.BookMapper"></mapper>
</mappers>
</configuration>
数据源委托给了spring来管理,mybatis主要用来配置<settings>
and<mappers>
and<typeAliases>
- spring-dao层
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<!--关联数据库配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--DataSource:数据源 c3p0 dbcp druid hikari-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<!--c3p0的私有属性-->
<property name="maxPoolSize" value="30"></property>
<property name="minPoolSize" value="10"></property>
<!--关闭连接后不自动提交-->
<property name="autoCommitOnClose" value="false"></property>
<!--获取连接的超时时间-->
<property name="checkoutTimeout" value="10000"></property>
<!--获取连接失败的重试次数-->
<property name="acquireRetryAttempts" value="3"></property>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!--配置dao接口扫描包,动态实现dao接口可以注入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactoryBeanName-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!--扫描的包-->
<property name="basePackage" value="edu.mapper"></property>
</bean>
<!--SqlSessionTemplate:就是我们使用的sqlSession-->
<!--<bean id="selSession" class="org.mybatis.spring.SqlSessionTemplate">
<!–只能使用构造器注入sqlSessionFactory,因为没有set方法–>
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>-->
</beans>
- spring-service
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<!--扫描service下的包-->
<context:component-scan base-package="edu.service"></context:component-scan>
<!--将所有业务类注入到spring容器中-->
<!--使用注解-->
<!--声明式事务-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--AOP事务支持-->
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>
<!--结合AOP实现事务织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性 propagation-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txpointcut" expression="execution(* edu.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txpointcut"></aop:advisor>
</aop:config>
</beans>
- spring-web
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">
<!--dispatcherservlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispatcherServlet要绑定springmvc的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</init-param>
<!--启动级别:1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/:匹配所有请求,不包括jsp-->
<!--/*:匹配所有请求,包括jsp-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--乱码过滤-->
<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>
<!--默认sessoin过期时间-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
spring-web.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<!--扫描包-->
<context:component-scan base-package="edu.controller"></context:component-scan>
<!--让springmvc不处理静态资源-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--自动配置映射器和适配器-->
<mvc:annotation-driven>
<!--json乱码问题解决-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--配置视图解析器 *模板引擎 Thymeleaf freemarker*
1.获取ModelAndView的数据
2.解析ModelAndView的视图名字
3.拼接视图名字,找到对应的视图
4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--BeanNameUrlHandlerMapping:bean handler-->
</beans>
至此,环境配置基本结束
4.2 业务代码
pojo包
Books
package edu.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("books")
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
mapper
bookmapper
package edu.mapper;
import edu.pojo.Books;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
public interface BookMapper {
/*
* 增加一本书
* */
@Insert("insert into books values(null,#{bookName},#{bookCounts},#{detail})")
public int addOneBook(Books books);
/*
* 删除一本书
* */
@Delete("delete from books where bookID=#{id}")
public int delBookByID(@Param("id") int id);
/*
* 更新一本书
* */
public int updateBook(Books books);
/*
* 根据id查询一本书
* */
@Select("select * from books where bookID=#{id}")
public Books queryByID(@Param("id") int id);
/*
* 查询所有书籍
* */
@Select("select * from books")
public List<Books> queryAllBooks();
/*
* 根据书名关键字查询书籍
* */
@Select("select * from books where bookName like #{key}")
public List<Books> queryBookLike(@Param("key") String key);
}
bookmapper.xml
<?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">
<!--xxx:接口的全路径-->
<mapper namespace="edu.mapper.BookMapper">
<!--在当前xml中使用二级缓存-->
<cache></cache>
<update id="updateBook" parameterType="books">
update books set bookName=#{bookName},bookCounts=#{bookCounts},detai=#{detail} where bookID=#{bookID}
</update>
</mapper>
service
userservice
package edu.service;
import edu.pojo.Books;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface BookService {
/*
* 增加一本书
* */
public int addOneBook(Books books);
/*
* 删除一本书
* */
public int delBookByID(int id);
/*
* 更新一本书
* */
public int updateBook(Books books);
/*
* 根据id查询一本书
* */
public Books queryByID(int id);
/*
* 查询所有书籍
* */
public List<Books> queryAllBooks();
/*
* 根据书名关键字查询书籍
* */
public List<Books> queryBookLike(@Param("key") String key);
}
userserviceimpl
package edu.service;
import edu.mapper.BookMapper;
import edu.pojo.Books;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService{
/*
* service调用dao层
* */
@Autowired
@Qualifier("bookMapper")
private BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
@Override
public int addOneBook(Books books) {
return bookMapper.addOneBook(books);
}
@Override
public int delBookByID(int id) {
return bookMapper.delBookByID(id);
}
@Override
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
@Override
public Books queryByID(int id) {
return bookMapper.queryByID(id);
}
@Override
public List<Books> queryAllBooks() {
return bookMapper.queryAllBooks();
}
@Override
public List<Books> queryBookLike(String key) {
return bookMapper.queryBookLike(key);
}
}
controller
usercontroller
package edu.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import edu.pojo.Books;
import edu.service.BookService;
import edu.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
@Qualifier("bookServiceImpl")
private BookService bookService;
public void setBookService(BookService bookService) {
this.bookService = bookService;
}
@ResponseBody
@RequestMapping("/allbooks")
public String getAllBooks() throws JsonProcessingException {
List<Books> booksList = bookService.queryAllBooks();
return JsonUtils.getJson(booksList);
}
@ResponseBody
@RequestMapping("/getbook/{id}")
public String getBooksByID(@PathVariable int id) throws JsonProcessingException {
Books books = bookService.queryByID(id);
return JsonUtils.getJson(books);
}
@ResponseBody
@RequestMapping("/addbook/{bookName}/{bookCounts}/{detail}")
public String insertBook(Books books) throws JsonProcessingException {
int i = bookService.addOneBook(books);
System.out.println(i);
return JsonUtils.getJson(books);
}
@ResponseBody
@RequestMapping("/delbook/{id}")
public String delBook(@PathVariable int id) throws JsonProcessingException {
int i = bookService.delBookByID(id);
System.out.println(i);
return JsonUtils.getJson(id);
}
@ResponseBody
@RequestMapping("/querybook/{str}")
public String queryBook(@PathVariable String str) throws JsonProcessingException {
List<Books> booksList = bookService.queryBookLike("%" + str + "%");
return JsonUtils.getJson(booksList);
}
}
url采用restful格式
4.3 测试
- querybook
-
allbooks
-
/getbook/{id}
5.springmvc拦截器
springmvc的拦截器自带静态资源过滤,只拦截controller
过滤器与拦截器的区别: 拦截器是AOP思想的具体应用
- 过滤器是servlet规范的一部分,任何javaweb工程都可以使用
- 在url-pattern中配置/*后,可以对所有要访问的资源进行拦截
- 拦截器是springmvc框架自己的,只有使用了sprinmvc框架的工程才能用
- 拦截器只会拦截访问的控制器方法,如果访问的jsp/html等静态资源是不会拦截的
5.1 如何自定义拦截器
想要自定义拦截器必须要实现HandlerInterceptor
接口
一个自定义拦截器
package edu.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
/*
* 过滤的执行函数
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("before interceptor");
// true:放行 false:不放行
return true;
}
/*
* 做日志操作
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("after interceptor");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("clear interceptor");
}
}
在配置文件中添加配置
<!--拦截器配置组-->
<mvc:interceptors>
<!--**代表所有的内容-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="edu.config.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>