一、SSM整合理解 1.1 什么是SSM整合? 微观 :将学习的Spring SpringMVC Mybatis框架应用到项目中!
SpringMVC框架负责控制层
Spring 框架负责整体和业务层的声明式事务管理
MyBatis框架负责数据库访问层
宏观 :Spring接管一切(将框架核心组件交给Spring进行IoC管理),代码更加简洁。
SpringMVC管理表述层、SpringMVC相关组件
Spring管理业务层、持久层、以及数据库相关(DataSource,MyBatis)的组件
使用IoC的方式管理一切所需组件
实施 :通过编写配置文件,实现SpringIoC容器接管一切组件。
1.2 SSM整合核心问题明确 1.2.1 第一问:SSM整合需要几个IoC容器? 两个容器
本质上说,整合就是将三层架构和框架核心API组件交给SpringIoC容器管理!
一个容器可能就够了,但是我们常见的操作是创建两个IoC容器(web容器和root容器),组件分类管理!
这种做法有以下好处和目的:
1.分离关注点:通过初始化两个容器,可以将各个层次的关注点进行分离。这种分离使得各个层次的组件能够更好地聚焦于各自的责任和功能。
2.解耦合:各个层次组件分离装配不同的IoC容器,这样可以进行解耦。这种解耦合使得各个模块可以独立操作和测试,提高了代码的可维护性和可测试性。
3.灵活配置:通过使用两个容器,可以为每个容器提供各自的配置,以满足不同层次和组件的特定需求。每个配置文件也更加清晰和灵活。
总的来说,初始化两个容器在SSM整合中可以实现关注点分离、解耦合、灵活配置等好处。它们各自负责不同的层次和功能,并通过合适的集成方式协同工作,提供一个高效、可维护和可扩展的应用程序架构!
1.2.2 第二问:每个IoC容器对应哪些类型组件? 图解:
总结:
容器名
盛放组件
web容器
web相关组件(controller,springmvc核心组件)
root容器
业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等)
1.2.3 第三问:IoC容器之间关系和调用方向? 情况1:两个无关联IoC容器之间的组件无法注入!
情况2:子IoC容器可以单向的注入父IoC容器的组件!
!
结论:web容器是root容器的子容器,父子容器关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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()); wac.setParent(parent); String configLocation = getContextConfigLocation(); if (configLocation != null ) { wac.setConfigLocation(configLocation); } configureAndRefreshWebApplicationContext(wac); return wac; }
调用流程图解:
1.2.4 第四问:具体多少配置类以及对应容器关系? 配置类的数量不是固定的,但是至少要两个,为了方便编写,我们可以三层架构每层对应一个配置类,分别指定两个容器加载即可!
建议配置文件:
配置名
对应内容
对应容器
WebJavaConfig
controller,springmvc相关
web容器
ServiceJavaConfig
service,aop,tx相关
root容器
MapperJavaConfig
mapper,datasource,mybatis相关
root容器
1.2.5 第五问:IoC初始化方式和配置位置? 在web项目下,我们可以选择web.xml和配置类方式进行ioc配置,推荐配置类。
对于使用基于 web 的 Spring 配置的应用程序,建议这样做,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class <?>[] { ServiceJavaConfig.class,MapperJavaConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class <?>[] { WebJavaConfig.class }; } @Override protected String[] getServletMappings() { return new String [] { "/" }; } }
图解配置类和容器配置:
二、SSM整合配置实战 2.1 依赖整合和添加 1.数据库准备
依然沿用mybatis数据库测试脚本!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 );
2.准备项目
part04-ssm-integration
转成web项目
3.依赖导入
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 <?xml version="1.0" encoding="UTF-8" ?> <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.0</modelVersion > <groupId > com.atguigu</groupId > <artifactId > part04-ssm-integration</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <properties > <spring.version > 6.0.6</spring.version > <jakarta.annotation-api.version > 2.1.1</jakarta.annotation-api.version > <jakarta.jakartaee-web-api.version > 9.1.0</jakarta.jakartaee-web-api.version > <jackson-databind.version > 2.15.0</jackson-databind.version > <hibernate-validator.version > 8.0.0.Final</hibernate-validator.version > <mybatis.version > 3.5.11</mybatis.version > <mysql.version > 8.0.25</mysql.version > <pagehelper.version > 5.1.11</pagehelper.version > <druid.version > 1.2.8</druid.version > <mybatis-spring.version > 3.0.2</mybatis-spring.version > <jakarta.servlet.jsp.jstl-api.version > 3.0.0</jakarta.servlet.jsp.jstl-api.version > <logback.version > 1.2.3</logback.version > <lombok.version > 1.18.26</lombok.version > <maven.compiler.source > 17</maven.compiler.source > <maven.compiler.target > 17</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > </properties > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > jakarta.annotation</groupId > <artifactId > jakarta.annotation-api</artifactId > <version > ${jakarta.annotation-api.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-tx</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > jakarta.platform</groupId > <artifactId > jakarta.jakartaee-web-api</artifactId > <version > ${jakarta.jakartaee-web-api.version}</version > <scope > provided</scope > </dependency > <dependency > <groupId > jakarta.servlet.jsp.jstl</groupId > <artifactId > jakarta.servlet.jsp.jstl-api</artifactId > <version > ${jakarta.servlet.jsp.jstl-api.version}</version > </dependency > <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > ${jackson-databind.version}</version > </dependency > <dependency > <groupId > org.hibernate.validator</groupId > <artifactId > hibernate-validator</artifactId > <version > ${hibernate-validator.version}</version > </dependency > <dependency > <groupId > org.hibernate.validator</groupId > <artifactId > hibernate-validator-annotation-processor</artifactId > <version > ${hibernate-validator.version}</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > ${mybatis.version}</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > ${mysql.version}</version > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > ${pagehelper.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > ${mybatis-spring.version}</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > ${logback.version}</version > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > ${lombok.version}</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > ${druid.version}</version > </dependency > </dependencies > </project >
4.实体类添加
com.atguigu.pojo
1 2 3 4 5 6 7 @Data public class Employee { private Integer empId; private String empName; private Double empSalary; }
5.logback配置
位置:resources/logback.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="UTF-8" ?> <configuration debug ="true" > <appender name ="STDOUT" class ="ch.qos.logback.core.ConsoleAppender" > <encoder > <pattern > [%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern > <charset > UTF-8</charset > </encoder > </appender > <root level ="DEBUG" > <appender-ref ref ="STDOUT" /> </root > <logger name ="com.atguigu.mybatis" level ="DEBUG" /> </configuration >
2.2 控制层配置编写(SpringMVC整合)
主要配置controller,springmvc相关组件配置
位置:WebJavaConfig.java(命名随意)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @EnableWebMvc @Configuration @ComponentScan({"com.torch.controller", "com.torch.exceptionhandler"}) public class WebMvcJavaConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void configureViewResolvers (ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/" , ".jsp" ); } @Override public void addInterceptors (InterceptorRegistry registry) { } }
2.3 业务层配置编写(AOP / TX整合)
主要配置service,注解aop和声明事务相关配置
位置:ServiceJavaConfig.java(命名随意)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @EnableTransactionManagement @EnableAspectJAutoProxy @Configuration @ComponentScan("com.atguigu.service") public class ServiceJavaConfig { @Bean public DataSourceTransactionManager transactionManager (DataSource dataSource) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager (); transactionManager.setDataSource(dataSource); return transactionManager; } }
2.4 持久层配置编写(MyBatis整合)
主要配置mapper代理对象,连接池和mybatis核心组件配置
1.mybatis整合思路
mybatis核心api使用回顾:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 InputStream ips = Resources.getResourceAsStream("mybatis-config.xml" );SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(ips);SqlSession sqlSession = sqlSessionFactory.openSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);int rows = empMapper.deleteEmpById(1 );System.out.println("rows = " + rows); sqlSession.commit(); sqlSession.close();
mybatis核心api介绍回顾:
因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 无需ioc容器管理!
一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,因此 SqlSessionFactory 的最佳作用域是应用作用域。 需要ioc容器管理!
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 无需ioc容器管理!
映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。
从作用域的角度来说,映射器实例不应该交给ioc容器管理!
但是从使用的角度来说,业务类(service)需要注入mapper接口,所以mapper应该交给ioc容器管理!
总结
将SqlSessionFactory实例存储到IoC容器
apper实例存储到IoC容器
mybatis整合思路理解:
mybatis的api实例化需要复杂的过程。
例如,自己实现sqlSessionFactory加入ioc容器:
1 2 3 4 5 6 7 8 9 10 @Bean public SqlSessionFactory sqlSessionFactory () { InputStream ips = Resources.getResourceAsStream("mybatis-config.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(ips); return sqlSessionFactory; }
过程比较繁琐,为了提高整合效率,mybatis提供了提供封装SqlSessionFactory和Mapper实例化的逻辑的FactoryBean组件,我们只需要声明和指定少量的配置即可!
SqlSessionFactoryBean源码展示(mybatis提供):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package org.mybatis.spring;public class SqlSessionFactoryBean implements FactoryBean <SqlSessionFactory>, InitializingBean, ApplicationListener<ContextRefreshedEvent> { public SqlSessionFactory getObject () throws Exception { if (this .sqlSessionFactory == null ) { afterPropertiesSet(); } return this .sqlSessionFactory; } }
mybatis整合思路总结:
需要将SqlSessionFactory和Mapper实例加入到IoC容器
使用mybatis整合包提供的FactoryBean快速整合
2.准备外部配置文件
数据库连接信息
位置:resources/jdbc.properties
1 2 3 4 jdbc.user=root jdbc.password=root jdbc.url=jdbc:mysql:///mybatis-example jdbc.driver=com.mysql.cj.jdbc.Driver
3.整合方式1 (保留mybatis-config.xml)
(1)介绍
依然保留mybatis的外部配置文件(xml), 但是数据库连接信息交给Druid连接池配置!
缺点:依然需要mybatis-config.xml文件,进行xml文件解析,效率偏低!
(2)mybatis配置文件
数据库信息以及mapper扫描包设置使用Java配置类处理!mybatis其他的功能(别名、settings、插件等信息)依然在mybatis-config.xml配置!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?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 > <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 >
(3)mybatis和持久层配置类
持久层Mapper配置、数据库配置、Mybatis配置信息
位置:MapperJavaConfig.java(命名随意)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 @Configuration @PropertySource("classpath:jdbc.properties") public class MapperJavaConfig { @Value("${jdbc.user}") private String user; @Value("${jdbc.password}") private String password; @Value("${jdbc.url}") private String url; @Value("${jdbc.driver}") private String driver; @Bean public DataSource dataSource () { DruidDataSource dataSource = new DruidDataSource (); dataSource.setUsername(user); dataSource.setPassword(password); dataSource.setUrl(url); dataSource.setDriverClassName(driver); return dataSource; } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean (DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dataSource); Resource resource = new ClassPathResource ("mybatis-config.xml" ); sqlSessionFactoryBean.setConfigLocation(resource); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer (); mapperScannerConfigurer.setBasePackage("com.atguigu.mapper" ); return mapperScannerConfigurer; } }
问题:
当你在Spring配置类中添加了sqlSessionFactoryBean
和mapperScannerConfigurer
配置方法时,可能会导致@Value
注解读取不到值为null的问题。这是因为SqlSessionFactoryBean
和MapperScannerConfigurer
是基于MyBatis框架的配置,它们的初始化顺序可能会导致属性注入的问题。
SqlSessionFactoryBean
和MapperScannerConfigurer
在配置类中通常是用来配置MyBatis相关的Bean,例如数据源、事务管理器、Mapper扫描等。这些配置类通常在@Configuration
注解下定义,并且使用@Value
注解来注入属性值。
当配置类被加载时,Spring容器会首先处理Bean的定义和初始化,其中包括sqlSessionFactoryBean
和mapperScannerConfigurer
的初始化。在这个过程中,如果@Value
注解所在的Bean还没有被完全初始化,可能会导致注入的属性值为null。
解决方案:
分成两个配置类独立配置,互不影响,数据库提取一个配置类,mybatis提取一个配置类即可解决!
(4)拆分配置
数据库配置类(DataSourceJavaConfig.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @Configuration @PropertySource("classpath:jdbc.properties") public class DataSourceJavaConfig { @Value("${jdbc.user}") private String user; @Value("${jdbc.password}") private String password; @Value("${jdbc.url}") private String url; @Value("${jdbc.driver}") private String driver; @Bean public DataSource dataSource () { DruidDataSource dataSource = new DruidDataSource (); dataSource.setUsername(user); dataSource.setPassword(password); dataSource.setUrl(url); dataSource.setDriverClassName(driver); return dataSource; } }
mybatis配置类(MapperJavaConfig.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 @Configuration public class MapperJavaConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory (DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dataSource); Resource resource = new ClassPathResource ("mybatis-config.xml" ); sqlSessionFactoryBean.setConfigLocation(resource); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer (); mapperScannerConfigurer.setBasePackage("com.torch.mapper" ); return mapperScannerConfigurer; } }
4.整合方式2(完全配置类 去掉mybatis-config.xml)
(1)介绍
不在保留mybatis的外部配置文件(xml), 所有配置信息(settings、插件、别名等)全部在声明SqlSessionFactoryBean的代码中指定!数据库信息依然使用DruidDataSource实例替代!
优势:全部配置类,避免了XML文件解析效率低问题!
(2)mapper配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 @Configuration public class MapperJavaConfigNew { @Bean public SqlSessionFactoryBean sqlSessionFactory (DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dataSource); org.apache.ibatis.session.Configuration configuration = new org .apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true ); configuration.setLogImpl(Slf4jImpl.class); configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL); sqlSessionFactoryBean.setConfiguration(configuration); sqlSessionFactoryBean.setTypeAliasesPackage("com.torch.pojo" ); PageInterceptor pageInterceptor = new PageInterceptor (); Properties properties = new Properties (); properties.setProperty("helperDialect" , "mysql" ); pageInterceptor.setProperties(properties); sqlSessionFactoryBean.addPlugins(pageInterceptor); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer (); mapperScannerConfigurer.setBasePackage("com.torch.mapper" ); return mapperScannerConfigurer; } }
2.5 容器初始化配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class <?>[] {MapperJavaConfig.class, ServiceJavaConfig.class, DataSourceJavaConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class <?>[] { WebJavaConfig.class }; } @Override protected String[] getServletMappings() { return new String [] { "/" }; } }
2.6 整合测试 1.需求
查询所有员工信息,返回对应json数据!
2.controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Slf4j @RestController @RequestMapping("/emp") public class EmployeeController { @Autowired private EmployeeService employeeService; @GetMapping("find") public List<Employee> find () { List<Employee> all = employeeService.findAll(); return all; } }
3.service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Service public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeMapper employeeMapper; @Override public List<Employee> findAll () { List<Employee> employeeList = employeeMapper.queryList(); return employeeList; } }
4.mapper
mapper接口 包:com.atguigu.mapper
1 2 3 4 public interface EmployeeMapper { List<Employee> queryList () ; }
mapper XML 文件位置: resources/com/atguigu/mappers
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8" ?> <!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 ="queryList" resultType ="employee" > select * from t_emp </select > </mapper >
三、《任务列表案例》前端程序搭建和运行 3.1 整合案例介绍和接口分析 3.1.1 案例功能预览
3.1.2接口分析 1.学习计划分页查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
2.学习计划删除
3.学习计划保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
4.学习计划修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
3.2 前端工程导入 前端环境搭建
Node.js 是前端程序运行的服务器,类似Java程序运行的服务器Tomcat
Npm 是前端依赖包管理工具,类似maven依赖管理工具软件
3.3 启动测试 1 2 npm install npm run dev
四、《任务列表案例》后端程序实现和测试 4.1 准备工作 1.准备数据库脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 );
2.准备pojo
包:com.atguigu.pojo
1 2 3 4 5 6 7 8 9 10 11 12 13 @Data public class Schedule { private Integer id; private String title; private Boolean completed; }
3.准备 R
包:com.atguigu.utils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 ** * projectName: com.atguigu.utils * * description: 返回结果类 */ public class R { private int code = 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; } }
4.准备 PageBean
包:com.atguigu.utils
1 2 3 4 5 6 7 8 9 10 @Data @NoArgsConstructor @AllArgsConstructor public class PageBean <T> { private int currentPage; private int pageSize; private long total; private List<T> data; }
4.2 功能实现 1.分页查询
(1)controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @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); } }
(2)service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Slf4j @Service public class ScheduleServiceImpl implements ScheduleService { @Autowired private ScheduleMapper scheduleMapper; @Override public PageBean<Schedule> findByPage (int pageSize, int currentPage) { PageHelper.startPage(currentPage,pageSize); List<Schedule> list = scheduleMapper.queryPage(); PageInfo<Schedule> pageInfo = new PageInfo <>(list); PageBean<Schedule> pageBean = new PageBean <>(pageInfo.getPageNum(),pageInfo.getPageSize(),pageInfo.getTotal(),pageInfo.getList()); log.info("分页查询结果:{}" ,pageBean); return pageBean; } }
(3)mapper
mapper接口
1 2 3 4 public interface ScheduleMapper { List<Schedule> queryPage () ; }
mapperxml文件
1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" encoding="UTF-8" ?> <!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 >
2.计划添加
(1)controller
1 2 3 4 5 @PostMapping public R saveSchedule (@RequestBody Schedule schedule) { scheduleService.saveSchedule(schedule); return R.ok(null ); }
(2)service
1 2 3 4 5 6 7 8 9 @Override public void saveSchedule (Schedule schedule) { scheduleMapper.insert(schedule); }
(3)mapper
mapper接口
1 void insert (Schedule schedule) ;
mapperxml文件
1 2 3 4 5 <insert id ="insert" > insert into schedule (title, completed) values (#{title}, #{completed}); </insert >
计划删除
(1)controller
1 2 3 4 5 @DeleteMapping("/{id}") public R removeSchedule (@PathVariable Integer id) { scheduleService.removeById(id); return R.ok(null ); }
(2)service
1 2 3 4 5 6 7 8 9 @Override public void removeById (Integer id) { scheduleMapper.delete(id); }
(3)mapper
mapper接口
1 void delete (Integer id) ;
mapperxml文件
1 2 3 <delete id ="delete" > delete from schedule where id = #{id} </delete >
4。计划修改
(1)controller
1 2 3 4 5 @PutMapping public R changeSchedule (@RequestBody Schedule schedule) { scheduleService.updateSchedule(schedule); return R.ok(null ); }
(2)service
1 2 3 4 5 6 7 8 9 @Override public void updateSchedule (Schedule schedule) { scheduleMapper.update(schedule); }
(3)mapper
mapper接口
1 void update (Schedule schedule) ;
mapperxml文件
1 2 3 4 <update id ="update" > update schedule set title = #{title} , completed = #{completed} where id = #{id} </update >
4.3 前后联调
后台项目根路径设计
启动测试即可
跨域访问(解决跨域访问的注解@CrossOrigin)