本质:Spring接管一切(将框架核心组件交给Spring进行IoC管理),代码更加简洁。
我们提到过SpringMVC/DispatcherServlet 加载 spring-mvc.xml,此时整个 Web 应用中只创建一个 IoC 容器。如果将Mybatis、配置声明式事务,全部在 spring-mvc.xml 配置文件中配置也是可以的。可是这样会导致配置文件太长,不容易维护。
通常情况下,SSM整合我们会创建两个IoC容器,分开管理SSM下的核心组件!
容器名 | 创建类 | 盛放组件 |
---|---|---|
web容器 | DispatcherServlet | web相关组件(controller,springmvc核心组件) |
root容器 | ContextLoaderListener | 业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等) |
结论:两个组件分别创建的 IOC 容器是父子关系。
源码部分:
ContextLoaderListener将实例化root容器,存储到ServletContext:
/**
* Initialize Spring's web application context for the given servlet context,
* using the application context provided at construction time, or creating a new one
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
* @param servletContext current servlet context
* @return the new WebApplicationContext
* @see #ContextLoader(WebApplicationContext)
* @see #CONTEXT_CLASS_PARAM
* @see #CONFIG_LOCATION_PARAM
*/
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
servletContext.log("Initializing Spring root WebApplicationContext");
Log logger = LogFactory.getLog(ContextLoader.class);
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext cwac && !cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
//将root容器存储到servletContext中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
}
return this.context;
}
catch (RuntimeException | Error ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
}
DispatcherServlet读取root容器,并且设置为web容器的父容器:
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
Class<?> contextClass = getContextClass();
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException(
"Fatal initialization error in servlet with name '" + getServletName() +
"': custom WebApplicationContext class [" + contextClass.getName() +
"] is not of type ConfigurableWebApplicationContext");
}
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(getEnvironment());
//将root容器取出,并设置为父容器
wac.setParent(parent);
String configLocation = getContextConfigLocation();
if (configLocation != null) {
wac.setConfigLocation(configLocation);
}
configureAndRefreshWebApplicationContext(wac);
return wac;
}
容器访问流程:
文件的数量不是固定的,但是至少要两个,为了方便编写,我们可以三层架构每层对应一个配置文件,分别指定两个容器加载即可!
建议配置文件:
配置名 | 对应内容 | 对应容器 |
---|---|---|
spring-mvc.xml | controller,springmvc相关 | web容器 |
spring-service.xml | service,aop,tx相关 | root容器 |
spring-mapper.xml | mapper,datasource,mybatis相关 | root容器 |
在一个 Web 应用中就会出现两个 IOC 容器
配置方式:
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-service.xml,classpath:spring-mapper.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
数据库准备
依然沿用mybatis数据库测试脚本!
CREATE DATABASE `mybatis-example`;
USE `mybatis-example`;
CREATE TABLE `t_emp`(
emp_id INT AUTO_INCREMENT,
emp_name CHAR(100),
emp_salary DOUBLE(10,5),
PRIMARY KEY(emp_id)
);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("tom",200.33);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("jerry",666.66);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("andy",777.77);
准备项目
part04-ssm-integration
转成web项目
依赖导入
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.atguigugroupId>
<artifactId>part04-ssm-integrationartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<spring.version>6.0.6spring.version>
<jakarta.annotation-api.version>2.1.1jakarta.annotation-api.version>
<jakarta.jakartaee-web-api.version>9.1.0jakarta.jakartaee-web-api.version>
<jackson-databind.version>2.15.0jackson-databind.version>
<hibernate-validator.version>8.0.0.Finalhibernate-validator.version>
<commons-fileupload.version>1.3.1commons-fileupload.version>
<mybatis.version>3.5.11mybatis.version>
<mysql.version>8.0.25mysql.version>
<pagehelper.version>5.1.11pagehelper.version>
<druid.version>1.2.8druid.version>
<mybatis-spring.version>3.0.2mybatis-spring.version>
<jakarta.servlet.jsp.jstl-api.version>3.0.0jakarta.servlet.jsp.jstl-api.version>
<logback.version>1.2.3logback.version>
<lombok.version>1.18.26lombok.version>
<maven.compiler.source>17maven.compiler.source>
<maven.compiler.target>17maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>jakarta.annotationgroupId>
<artifactId>jakarta.annotation-apiartifactId>
<version>${jakarta.annotation-api.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>jakarta.platformgroupId>
<artifactId>jakarta.jakartaee-web-apiartifactId>
<version>${jakarta.jakartaee-web-api.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstlgroupId>
<artifactId>jakarta.servlet.jsp.jstl-apiartifactId>
<version>${jakarta.servlet.jsp.jstl-api.version}version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>${commons-fileupload.version}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>${jackson-databind.version}version>
dependency>
<dependency>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validatorartifactId>
<version>${hibernate-validator.version}version>
dependency>
<dependency>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validator-annotation-processorartifactId>
<version>${hibernate-validator.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis-spring.version}version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>${logback.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
dependencies>
project>
实体类添加
com.atguigu.pojo
@Data
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
}
logback配置
位置:resources/logback.xml
<configuration debug="true">
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%npattern>
<charset>UTF-8charset>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
root>
<logger name="com.atguigu.mybatis" level="DEBUG" />
configuration>
主要配置controller,springmvc相关! 本次先不配置文件上传!
位置:resources/spring-mvc.xml(命名随意)
<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/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:component-scan base-package="com.atguigu.controller" />
<mvc:annotation-driven />
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
bean>
beans>
主要配置service,注解aop和声明事务相关!
位置:resources/spring-service.xml(命名随意)
<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" xmlns:tx="http://www.springframework.org/schema/tx"
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 http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.atguigu.service,com.atguigu.advice,com.atguigu.pointcut" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource" />
bean>
<tx:annotation-driven transaction-manager="transactionManager" />
beans>
jdbc外部配置
位置:resources/jdbc.properties
jdbc.user=root
jdbc.password=root
jdbc.url=jdbc:mysql:///mybatis-example
jdbc.driver=com.mysql.cj.jdbc.Driver
持久层配置
位置:resources/spring-mapper.xml(命名随意)
<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:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
bean>
beans>
配置mybatis方式1:保留mybaits全局配置
准备mybatis-config.xml文件:去掉数据库信息,去掉mapper包映射(xml中配置)
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="SLF4J"/>
<setting name="autoMappingBehavior" value="FULL"/>
settings>
<typeAliases>
<package name="com.atguigu.pojo"/>
typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
plugin>
plugins>
configuration>
修改spring-mapper.xml
<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:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<property name="dataSource" ref="dataSource"/>
bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.atguigu.mapper"/>
bean>
beans>
配置mybatis方式2:完全配置文件实现
修改spring-mapper.xml
<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:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true"/>
bean>
property>
<property name="typeAliasesPackage" value="com.atguigu.pojo"/>
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="reasonable">trueprop>
<prop key="pageHelperDialect">mysqlprop>
props>
property>
bean>
array>
property>
bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.atguigu.mapper"/>
bean>
<mybatis-spring:scan base-package="com.atguigu.mapper"/>
beans>
<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">
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-service.xml,classpath:spring-mapper.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
需求
查询所有员工信息,返回对应json数据!
controller
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("list")
public List<Employee> retList(){
List<Employee> employees = employeeService.findAll();
log.info("员工数据:{}",employees);
return employees;
}
}
service
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
/**
* 查询所有员工信息
*/
@Override
public List<Employee> findAll() {
List<Employee> employeeList = employeeMapper.queryAll();
return employeeList;
}
}
mapper
mapper接口 包:com.atguigu.mapper
public interface EmployeeMapper {
List<Employee> queryAll();
}
mapper XML 文件位置: resources/mappers
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.EmployeeMapper">
<select id="queryAll" resultType="employee">
select emp_id empId,emp_name empName, emp_salary empSalary from t_emp
select>
mapper>
/*
需求说明
查询全部数据页数据
请求uri
schedule/{pageSize}/{currentPage}
请求方式
get
响应的json
{
"code":200,
"flag":true,
"data":{
//本页数据
data:
[
{id:1,title:'学习java',completed:true},
{id:2,title:'学习html',completed:true},
{id:3,title:'学习css',completed:true},
{id:4,title:'学习js',completed:true},
{id:5,title:'学习vue',completed:true}
],
//分页参数
pageSize:5, // 每页数据条数 页大小
total:0 , // 总记录数
currentPage:1 // 当前页码
}
}
*/
/*
需求说明
根据id删除日程
请求uri
schedule/{id}
请求方式
delete
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/
/*
需求说明
增加日程
请求uri
schedule
请求方式
post
请求体中的JSON
{
title: '',
completed: false
}
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/
/*
需求说明
根据id修改数据
请求uri
schedule
请求方式
put
请求体中的JSON
{
id: 1,
title: '',
completed: false
}
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/
npm i //安装依赖
npm run dev //运行测试
准备数据库脚本
CREATE TABLE schedule (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
completed BOOLEAN NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO schedule (title, completed)
VALUES
('学习java', true),
('学习Python', false),
('学习C++', true),
('学习JavaScript', false),
('学习HTML5', true),
('学习CSS3', false),
('学习Vue.js', true),
('学习React', false),
('学习Angular', true),
('学习Node.js', false),
('学习Express', true),
('学习Koa', false),
('学习MongoDB', true),
('学习MySQL', false),
('学习Redis', true),
('学习Git', false),
('学习Docker', true),
('学习Kubernetes', false),
('学习AWS', true),
('学习Azure', false);
准备pojo
包:com.atguigu.pojo
/**
* projectName: com.atguigu.pojo
*
* description: 任务实体类
*/
@Data
public class Schedule {
private Integer id;
private String title;
private Boolean completed;
}
准备 R
包:com.atguigu.utils
**
* projectName: com.atguigu.utils
*
* description: 返回结果类
*/
public class R {
private int code = 200; //200成功状态码
private boolean flag = true; //返回状态
private Object data; //返回具体数据
public static R ok(Object data){
R r = new R();
r.data = data;
return r;
}
public static R fail(Object data){
R r = new R();
r.code = 500; //错误码
r.flag = false; //错误状态
r.data = data;
return r;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
准备 PageBean
包:com.atguigu.utils
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean<T> {
private int currentPage; // 当前页码
private int pageSize; // 每页显示的数据量
private long total; // 总数据条数
private List<T> data; // 当前页的数据集合
}
controller
/*
@CrossOrigin 注释在带注释的控制器方法上启用跨源请求
*/
@CrossOrigin
@RequestMapping("schedule")
@RestController
public class ScheduleController
{
@Autowired
private ScheduleService scheduleService;
@GetMapping("/{pageSize}/{currentPage}")
public R showList(@PathVariable(name = "pageSize") int pageSize, @PathVariable(name = "currentPage") int currentPage){
PageBean<Schedule> pageBean = scheduleService.findByPage(pageSize,currentPage);
return R.ok(pageBean);
}
}
service
@Slf4j
@Service
public class ScheduleServiceImpl implements ScheduleService {
@Autowired
private ScheduleMapper scheduleMapper;
/**
* 分页数据查询,返回分页pageBean
*
* @param pageSize
* @param currentPage
* @return
*/
@Override
public PageBean<Schedule> findByPage(int pageSize, int currentPage) {
//1.设置分页参数
PageHelper.startPage(currentPage,pageSize);
//2.数据库查询
List<Schedule> list = scheduleMapper.queryPage();
//3.结果获取
PageInfo<Schedule> pageInfo = new PageInfo<>(list);
//4.pageBean封装
PageBean<Schedule> pageBean = new PageBean<>(pageInfo.getPageNum(),pageInfo.getPageSize(),pageInfo.getTotal(),pageInfo.getList());
log.info("分页查询结果:{}",pageBean);
return pageBean;
}
}
mapper
mapper接口
public interface ScheduleMapper {
List<Schedule> queryPage();
}
mapperxml文件
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.ScheduleMapper">
<select id="queryPage" resultType="schedule">
select * from schedule
select>
mapper>
controller
@PostMapping
public R saveSchedule(@RequestBody Schedule schedule){
scheduleService.saveSchedule(schedule);
return R.ok(null);
}
service
/**
* 保存学习计划
*
* @param schedule
*/
@Override
public void saveSchedule(Schedule schedule) {
scheduleMapper.insert(schedule);
}
mapper
mapper接口
void insert(Schedule schedule);
mapperxml文件
<insert id="insert">
insert into schedule (title, completed)
values
(#{title}, #{completed});
insert>
@DeleteMapping("/{id}")
public R removeSchedule(@PathVariable Integer id){
scheduleService.removeById(id);
return R.ok(null);
}
/**
* 移除学习计划
*
* @param id
*/
@Override
public void removeById(Integer id) {
scheduleMapper.delete(id);
}
void delete(Integer id);
mapperxml文件<delete id="delete">
delete from schedule where id = #{id}
delete>
@PutMapping
public R changeSchedule(@RequestBody Schedule schedule){
scheduleService.updateSchedule(schedule);
return R.ok(null);
}
/**
* 更新学习计划
*
* @param schedule
*/
@Override
public void updateSchedule(Schedule schedule) {
scheduleMapper.update(schedule);
}
void update(Schedule schedule);
mapperxml文件<update id="update">
update schedule set title = #{title} , completed = #{completed}
where id = #{id}
update>
xml
<bean id="petStore" class="org.springframework.samples.
jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
bean>
注解
注解 | 说明 |
---|---|
@Component | 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。 |
@Repository | 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Service | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Controller | 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
<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.atguigu.components"/>
beans>
配置类
//标注当前类是配置类,替代application.xml
@Configuration
//引入jdbc.properties文件
@PropertySource({"classpath:application.properties","classpath:jdbc.properties"})
@ComponentScan(basePackages = {"com.atguigu.components"})
@Import(其他的配置类.class)
public class MyConfiguration {
//如果第三方类进行IoC管理,无法直接使用@Component相关注解
//解决方案: xml方式可以使用
//解决方案: 配置类方式,可以使用方法返回值+@Bean注解
@Bean
public DataSource createDataSource(@Value("${jdbc.user:default}") String username,
@Value("${jdbc.password}")String password,
@Value("${jdbc.url}")String url,
@Value("${jdbc.driver}")String driverClassName){
//使用Java代码实例化
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClassName);
//返回结果即可
return dataSource;
}
@Bean
public XxxMapper createMapper(DataSource createDataSource){
}
}
<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 http://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:component-scan base-package="com.atguigu" />
<aop:aspectj-autoproxy />
beans>
@Aspect
@Order 值越小优先级越高
@Before
@After
@AfterReturning
@AfterThrowing
@Around
@Pointcut
<bean id="calculatorPure" class="com.atguigu.aop.imp.CalculatorPureImpl"/>
<bean id="logAspect" class="com.atguigu.aop.aspect.LogAspect"/>
<aop:config>
<aop:pointcut id="logPointCut" expression="execution(* *..*.*(..))"/>
<aop:aspect ref="logAspect">
<aop:before method="printLogBeforeCore" pointcut-ref="logPointCut"/>
<aop:after-returning
method="printLogAfterCoreSuccess"
pointcut-ref="logPointCut"
returning="targetMethodReturnValue"/>
<aop:after-throwing
method="printLogAfterCoreException"
pointcut-ref="logPointCut"
throwing="targetMethodException"/>
<aop:after method="printLogCoreFinallyEnd" pointcut-ref="logPointCut"/>
aop:aspect>
aop:config>
注解
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional
xml(了解)
<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 http://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 http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.atguigu" />
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${atguigu.url}"/>
<property name="driverClassName" value="${atguigu.driver}"/>
<property name="username" value="${atguigu.username}"/>
<property name="password" value="${atguigu.password}"/>
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"/>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"/>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="save*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="update*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="delete*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="*" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txPoincut" expression="execution(* *..*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoincut"/>
aop:config>
beans>
ioc/di注解:
@Autowired:自动装配 Bean,可用于构造方法、属性和方法上,配合 @Qualifier
使用实现按名称注入。
@Qualifier:指定需要注入的 Bean 的名称,通常和 @Autowired
一起使用。
@Resource:和 @Autowired
类似,可以实现按名称注入,不过是 JSR-250 规范的注解。
@Value:注入 properties 文件中的属性值,还可以注入 SpEL 表达式的值。
@Component:通用的组件注解,通常用于标记 Spring 管理的 Bean。
@Controller:标记 Spring MVC 控制器,也是 @Component
的一种。
@Service:标记 Service 层组件,也是 @Component
的一种。
@Repository:标记数据访问层组件,是 @Component
的一种。
aop注解:
@Aspect:声明一个切面类。
@Pointcut:定义切入点表达式。
@Before:前置通知,在目标方法执行之前执行。
@AfterReturning:后置通知,在目标方法执行之后执行,返回结果时执行。
@AfterThrowing:异常通知,在目标方法抛出异常时执行。
@After:最终通知,在目标方法执行之后执行,无论是否发生异常都执行。
@Around:环绕通知,在目标方法执行前后执行,可以控制目标方法的执行。
tx注解:
@Transactional:声明一个事务方法,可以配置事务的属性,如传播行为、隔离级别、超时时间等。
简化参数接收
接收param / json / 文件 / 原生api / 共享域
简化数据响应
响应 页面 / 转发和重定向 / json / 文件
<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/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:component-scan base-package="com.atguigu.controller" />
<mvc:annotation-driven />
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
bean>
beans>
控制器相关
@Controller
:用于定义控制器类;
@RestController
:与 @Controller
类似,但返回值都会被转换为 JSON 格式;
@RequestMapping
:用于定义请求 URI 与控制器方法的映射关系;
@CrossOrigin
:用于标注在 Controller 类或处理请求的方法上,表示允许跨域请求;
接收参数相关
@RequestParam
:用于获取请求参数的值;
@RequestBody
:用于获取 POST 请求的请求体(Request Body);
@RequestHeader
:用于获取请求头信息;
@CookieValue
:用于获取 Cookie 中的值。
@PathVariable
:用于获取 URI 中的参数值;
响应数据相关
@ResponseBody
:用于将 Controller 中方法返回的对象转换成指定格式(通常是 JSON 或 XML)的对象,并将其作为响应正文返回;
校验注解相关
@Validate
:用于开启对象的数据校验;
@NotNull
:用于检验是否为 null;
@NotBlank
:用于检验是否为 null 或空字符串;
@Size
:用于检验字符串、数组、集合的长度范围;
@Min
:用于检验数字的最小值;
@Max
:用于检验数字的最大值;
@DecimalMin
:用于检验 BigDecimal 和 BigInteger 的最小值;
@DecimalMax
:用于检验 BigDecimal 和 BigInteger 的最大值;
@Pattern
:用于检验正则表达式。
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。
如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器) String [] , varchar()
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
@Param
:在 MyBatis 中,@Param 注解主要用于解决在调用映射器方法时传递多个参数的问题。当你在映射器接口中定义的方法有多个参数时,你需要使用 @Param 注解来明确指出每个参数的名称,以便在 SQL 映射文件中引用它们。
例如,假设你有以下映射器接口方法:
void updateUser(@Param("id") int id, @Param("name") String name, @Param("age") int age);
在这个例子中,你定义了一个名为 updateUser 的方法,它接受三个参数:id、name 和 age。每个参数都使用了 @Param 注解,并给出了一个名称。
然后,在相应的 SQL 映射文件中,你可以使用这些名称来引用这些参数。例如:
<update id="updateUser">
UPDATE user
SET name = #{name}, age = #{age}
WHERE id = #{id}
update>
在这个例子中,#{name}、#{age} 和 #{id} 分别引用了传递给 updateUser 方法的 name、age 和 id 参数。
总的来说,@Param 注解在 MyBatis 中用于明确指出方法的参数名称,以便在 SQL 映射文件中引用它们。