image.png

Author:Eric

Version:9.0.0

一、引言


1.1 初始化配置

为了使用SSM框架去开发,准备SSM框架的模板配置。

1.2 整合第三方框架

为了Spring整合第三方框架,单独的去编写xml文件。

1.3 后期维护

后期SSM项目后期xml文件特别多,维护xml文件的成本是很高的

1.4 部署工程

SSM工程部署也是很麻烦,依赖第三方的容器

1.5 敏捷式开发

基于Java的SSM开发方式是很笨重,而现在的python,php,NodeJS的敏捷式开发已经盖过Java一头

二、SpringBoot介绍


SpringBoot是由Pivotal团队研发的,SpringBoot并不是一门新技术,只是将之前常用的Spring,SpringMVC,data-jpa等常用的框架封装到了一起,帮助你隐藏这些框架的整合细节,实现敏捷开发。

SpringBoot就是一个工具集,springboot生态。

LOGO
image.png

SpringBoot特点:

  • SpringBoot项目不需要模板化的配置。
  • SpringBoot中整合第三方框架时,只需要导入相应的starter依赖包,就自动整合了。
  • SpringBoot默认只有一个.properties的配置文件,不推荐使用xml,后期会采用.java的文件去编写配置信息。
  • SpringBoot工程在部署时,采用的是jar包的方式,内部自动依赖Tomcat容器,提供了多环境的配置。
  • 后期要学习的微服务框架SpringCloud需要建立在SpringBoot的基础上。

三、SpringBoot快速入门【重点


3.1 快速构建SpringBoot

3.1.1 选择构建项目的类型
选择构建项目的类型
image.png

3.1.2 项目的描述
项目的描述
image.png

3.1.3 指定SpringBoot版本和需要的依赖
指定SpringBoot版本和需要的依赖
image.png

3.1.4 导入依赖
  1. <parent>
  2. <artifactId>spring-boot-starter-parent</artifactId>
  3. <groupId>org.springframework.boot</groupId>
  4. <version>2.3.12.RELEASE</version>
  5. </parent>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter</artifactId>
  9. </dependency>
  10. <!-- 将上述内容修改为下面的效果 -->
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-web</artifactId>
  14. </dependency>

3.1.5 编写了Controller
  1. @RestController
  2. public class TestController {
  3. @GetMapping("/test")
  4. public String test(){
  5. return "Hello SpringBoot!";
  6. }
  7. }

3.1.6 测试
效果
image.png

3.2 SpringBoot的目录结构

3.2.1 pom.xml文件
  • 指定了一个父工程: 指定当前工程为SpringBoot,帮助我们声明了starter依赖的版本。
  • 项目的元数据:包名,项目名,版本号。
  • 指定了properties信息:指定了java的版本为1.8
  • 导入依赖:默认情况导入spring-boot-starter,spring-boot-starter-test
  • 插件:spring-boot-maven-plugin

3.2.2 .gitignore文件

默认帮我们忽略了一些文件和目录,避免提交到Git仓库中

3.2.3 src目录
  1. -src
  2. -main
  3. -java
  4. -包名
  5. 启动类.java # 需要将controller类,放在启动类的子包中或者同级包下
  6. -resources
  7. -static # 存放静态资源的
  8. -templates # 存储模板页面的
  9. application.properties # SpringBoot提供的唯一的配置文件
  10. -test # 只是为了测试用的

3.3 SpringBoot三种启动方式

3.3.1 运行启动类的main方法

运行main方法即可

3.3.2 maven命令
  1. mvn spring-boot:run

3.3.3 采用jar包的方式运行

将当前项目打包成一个jar文件,并通过java -jar jar文件

四、SpringBoot常用注解【重点


4.1 @Configuration和@Bean

  • 之前使用SSM去开发时,在xml文件中编写bean标签,但是SpringBoot不推荐使用xml文件。
  • @Configuration注解相当于beans标签
  • @Bean注解相当于bean标签
  • id=“方法名 | 注解中的name属性(优先级更高)”
  • class=“方法的返回结果”
  1. @Configuration // 代表当前类是一个配置类
  2. public class UserConfig {
  3. @Bean(name = "user1") // 构建一个实例,放到spring容器中
  4. public User user(){
  5. User user = new User();
  6. user.setId(1);
  7. user.setName("张三");
  8. return user;
  9. }
  10. /*
  11. <beans ....> @Configuration
  12. <bean id="user1" class="com.qf.firstspringboot.entity.User" />
  13. </beans>
  14. */
  15. }
  1. @Autowired bytype @Qualifier(value = "user1") 另外取名
  2. @Resource byname

1、如果是当前对象没有发生冲突注入,采用@Autowired @Resource ;@Qualifier(备注:写与不写都可以) 随便那种都可以;
2、如果发生对象冲突:Autowired和Resource 就必须配合Qualifier 联合使用;
image.png

@Service @component 用法一样

image.png

  1. @MapperScan("com.qf.demo.dao") 启动类
  2. @MapperScan 扫描 我们的mybatis 接口 接口
  3. @Configuration @Bean 自定义一个创建注入容器
  4. @controller @restcontroller 用在表示层
  5. @service 用在逻辑层 业务层
  6. @MapperScan @Mapper @Repostory 用在持久层
  7. @Component 这个用其他地方(工具类...)

4.2 @SpringBootApplication(重点)

@SpringBootApplication就是一个组合注解:

  • @SpringBootConfiguration就是@Configuration注解,代表启动类就是一个配置类。
  • @EnableAutoConfiguration帮你实现自动装配的,SpringBoot工程启动时,运行一个SpringFactoriesLoader的类,加载META-INF/spring.factories配置类(已经开启的),通过SpringFactoriesLoader中的load方法,以for循环的方式,一个一个加载。
    • 好处:无需编写大量的整合配置信息,只需要按照SpringBoot提供好了约定去整合即可。
    • 坏处:如果说你导入了一个starter依赖,那么你就需要填写他必要的配置信息。
    • 手动关闭自动装配指定内容:@SpringBootApplication(exclude = QuartzAutoConfiguration.class)
  • @ComponentScan就相当于,帮助扫描注解的。

五、SpringBoot常用配置【重点


5.1 SpringBoot的配置文件格式

SpringBoot的配置文件支持properties和yml,甚至他还支持json。

更推荐使用yml文件格式:

  1. yml文件,会根据换行和缩进帮助咱们管理配置文件所在位置
  2. yml文件,相比properties更轻量级一些

yml文件的劣势:

  1. 严格遵循换行和缩进
  2. 在填写value时,一定要在: 后面跟上空格

默认加载properties

5.2 多环境配置(重点)

在application.yml文件中添加一个配置项:

  1. spring:
  2. profiles:
  3. active: 环境名

在resource目录下,创建多个application-环境名.yml文件即可

在部署工程时,通过 java -jar jar文件 —spring.profiles.active=环境

5.3 引入外部配置文件信息(了解)

和传统的SSM方式一样,通过@Value的注解去获取properties/yml文件中的内容。

如果在yml文件中需要编写大量的自定义配置,并且具有统一的前缀时,采用如下方式

  1. // Java程序
  2. @ConfigurationProperties(prefix = "aliyun")
  3. @Component
  4. @Data
  5. public class AliyunProperties {
  6. private String xxxx;
  7. private ... ...;
  8. }
  9. // 配置文件
  10. aliyun:
  11. xxxx: xxxxxxxxx
  12. ...

5.4 热加载(了解)

5.4.1 导入依赖
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-devtools</artifactId>
  4. <optional>true</optional>
  5. </dependency>

5.4.2 settings配置
修改settings中的配置
image.png

5.4.3 重新构建工程
build
image.png

补充 如果没有效果:请按:ctrl+shift+alt+/ 选择:
image.png

如果:还是不行,请放弃

可以安装:Jrebel插件

六、SpringBoot整合Mybatis【重点


6.1 xml方式整合Mybatis

xml方式在编写复杂SQL时,更适合

1、导入我的需要依赖包
2、配置我们的application.yml
3、编写我们的实体类
4、编写我们的mapper接口, 在我们的接口头部需要加入一个@Mapper 或者启动类的上面在一个@MaperScan(包路径)
5、编写mapper.xml 或者 注解开发

6.1.1 导入依赖。
  1. <!-- mysql驱动-->
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. </dependency>
  6. <!-- druid连接-->
  7. <dependency>
  8. <groupId>com.alibaba</groupId>
  9. <artifactId>druid-spring-boot-starter</artifactId>
  10. <version>1.1.10</version>
  11. </dependency>
  12. <!-- mybatis-->
  13. <dependency>
  14. <groupId>org.mybatis.spring.boot</groupId>
  15. <artifactId>mybatis-spring-boot-starter</artifactId>
  16. <version>1.3.2</version>
  17. </dependency>

6.1.2 编写配置文件
  1. // 准备实体类
  2. @Data
  3. public class Air implements Serializable {
  4. private Integer id;
  5. private Integer districtId;
  6. private java.util.Date monitorTime;
  7. private Integer pm10;
  8. private Integer pm25;
  9. private String monitoringStation;
  10. private java.util.Date lastModifyTime;
  11. }
  12. // ================================================
  13. @Data
  14. public class District implements Serializable {
  15. private Integer id;
  16. private String name;
  17. }

6.1.3 准备Mybatis
  1. // 1. 接口
  2. public interface AirMapper {
  3. List<Air> findAll();
  4. }
  5. // 2. 在启动类中添加直接,扫描Mapper接口所在的包
  6. @MapperScan(basePackages = "com.qf.firstspringboot.mapper")
  7. // 3. 准备映射文件
  8. <?xml version="1.0" encoding="UTF-8" ?>
  9. <!DOCTYPE mapper
  10. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  11. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  12. <mapper namespace="com.qf.firstspringboot.mapper.AirMapper">
  13. <!-- List<Air> findAll();-->
  14. <select id="findAll" resultType="Air">
  15. select * from air
  16. </select>
  17. </mapper>
  18. //4. yml文件
  19. <!-- 添加yml文件配置信息 -->
  20. # mybatis配置
  21. mybatis:
  22. # 扫描映射文件
  23. mapper-locations: classpath:mapper/*.xml
  24. # 配置别名扫描的包
  25. type-aliases-package: com.qf.firstspringboot.entity
  26. configuration:
  27. # 开启驼峰映射配置
  28. map-underscore-to-camel-case: true
  29. # 连接数据库的信息
  30. spring:
  31. datasource:
  32. driver-class-name: com.mysql.cj.jdbc.Driver
  33. url: jdbc:mysql:///air?serverTimezone=UTC
  34. username: root
  35. password: root
  36. type: com.alibaba.druid.pool.DruidDataSource

6.1.4 测试。
  1. class AirMapperTest extends FirstSpringbootApplicationTests {
  2. @Autowired
  3. private AirMapper airMapper;
  4. @Test
  5. void findAll() {
  6. List<Air> list = airMapper.findAll();
  7. for (Air air : list) {
  8. System.out.println(air);
  9. }
  10. }
  11. }

6.2 注解方式整合Mybatis(了解)

注解方式在编写配置简单,简单SQL推荐使用

6.2.1 创建District的Mapper接口
  1. public interface DistrictMapper {
  2. List<District> findAll();
  3. }

6.2.2 添加Mybatis注解

针对增删改查:@Insert,@Delete,@Update,@Select

还是需要在启动类中添加@MapperScan注解

  1. @Select("select * from district")
  2. List<District> findAll();
  3. @Select("select * from district where id = #{id}")
  4. District findOneById(@Param("id") Integer id);

6.2.3 添加配置
  1. // yml文件
  2. logging:
  3. level:
  4. com.qf.firstspringboot.mapper: DEBUG

6.2.4 测试,查看日志
  1. class DistrictMapperTest extends FirstSpringbootApplicationTests {
  2. @Autowired
  3. private DistrictMapper mapper;
  4. @Test
  5. void findAll() {
  6. List<District> list = mapper.findAll();
  7. for (District district : list) {
  8. System.out.println(district);
  9. }
  10. }
  11. @Test
  12. void findOneById() {
  13. District district = mapper.findOneById(5);
  14. System.out.println(district);
  15. }
  16. }

6.3 SpringBoot整合分页助手

6.3.1 导入依赖
  1. <!-- pageHelper依赖-->
  2. <dependency>
  3. <groupId>com.github.pagehelper</groupId>
  4. <artifactId>pagehelper-spring-boot-starter</artifactId>
  5. <version>1.2.5</version>
  6. </dependency>

6.3.2 测试使用
  1. @Test
  2. public void findByPage(){
  3. //1. 执行分页
  4. PageHelper.startPage(1,5);
  5. //2. 执行查询
  6. List<Air> list = airMapper.findAll();
  7. //3. 封装PageInfo对象
  8. PageInfo<Air> pageInfo = new PageInfo<>(list);
  9. //4. 输出
  10. for (Air air : pageInfo.getList()) {
  11. System.out.println(air);
  12. }
  13. }

七、SpringBoot整合thymeleaf


7.1 整合thymeleaf

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  4. </dependency>

7.2 添加配置

  1. spring:
  2. thymeleaf:
  3. enabled: true #开启thymeleaf视图解析
  4. encoding: utf-8 #编码
  5. prefix: classpath:/templates/ #前缀 当然默认也是这个,可以不配置
  6. cache: false #是否使用缓存
  7. mode: HTML #严格的HTML语法模式
  8. suffix: .html #后缀名

thymeleaf 语法:http://c.biancheng.net/spring_boot/thymeleaf-import.html

八、SpringBoot练习


页面查询客户信息从ES中查询

完成客户模块的增删改,并且同步到ES中。

练习业务图
image.png

九、事务和AOP

1、声明式事务

//类中的每个方法都切入事务(有自己的事务控制的方法除外)
@Transactional(isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class,timeout = -1)

2、aop

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

@Aspect // 声明此类是一个切面类:会包含切入点(pointcut)和通知(advice)
@Component //声明组件,进入工厂
public class MyAspect {
// 定义切入点
@Pointcut(“execution( com.qf.service.UserService.())”)
public void pc(){}

  1. @Before("pc()") // 前置通知
  2. public void mybefore(JoinPoint a) {
  3. System.out.println("target:"+a.getTarget());
  4. System.out.println("args:"+a.getArgs());
  5. System.out.println("method's name:"+a.getSignature().getName());
  6. System.out.println("before~~~~");
  7. }
  8. @AfterReturning(value="pc()",returning="ret") // 后置通知
  9. public void myAfterReturning(JoinPoint a,Object ret){
  10. System.out.println("after~~~~:"+ret);
  11. }
  12. @Around("pc()") // 环绕通知
  13. public Object myInterceptor(ProceedingJoinPoint p) throws Throwable {
  14. System.out.println("interceptor1~~~~");
  15. Object ret = p.proceed();
  16. System.out.println("interceptor2~~~~");
  17. return ret;
  18. }
  19. @AfterThrowing(value="pc()",throwing="ex") // 异常通知
  20. public void myThrows(JoinPoint jp,Exception ex){
  21. System.out.println("throws");
  22. System.out.println("===="+ex.getMessage());
  23. }

}

十、mybatis 多表查询

//一对一查询

  1. @Select("select * from student where id = #{id}")
  2. @Results(id = "studentMap", value = {
  3. @Result(column = "id", property = "id", id = true),
  4. @Result(column= "name", property="name"),
  5. @Result(column = "clazz_id", property="clazz",one=@One(select = "cn.sunxyz.mapper.ClazzMapper.findById"))
  6. })
  7. Student findById(@Param("id")String id);

//多对多查询

  1. @Select("select * from student where id = #{id}")
  2. @Results(id = "studentMap", value = {
  3. @Result(column = "id", property = "id", id = true),
  4. @Result(column= "name", property="name"),
  5. @Result(column = "clazz_id", property="clazz",many= @Many(select = "cn.sunxyz.mapper.ClazzMapper.findById"))
  6. })
  7. Student findById(@Param("id")String id);

动态sql

  1. public String findAll(User user){
  2. return new SQL(){
  3. {
  4. SELECT("*");
  5. FROM("t_users");
  6. if(user.getId()>0){
  7. WHERE("id="+user.getId());
  8. }
  9. if(StringUtils.isNotBlank(user.getName())){
  10. WHERE("name="+user.getName());
  11. }
  12. }
  13. }.toString();
  14. }
  15. public String findByConditions(User user){
  16. String sql = "select * from t_users where 1=1 ";
  17. if(user.getId() > 0){
  18. sql+= " and id="+user.getId();
  19. }
  20. if(StringUtils.isNotBlank(user.getName())){
  21. sql+=" and name='"+user.getName()+"'";
  22. }
  23. return sql;
  24. }

十一 整合mybatisplus

  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus-boot-starter</artifactId>
  4. <version>3.3.2</version>
  5. </dependency>
  1. mybatis-plus.configuration.map-underscore-to-camel-case=true
  2. mybatis-plus.configuration.auto-mapping-behavior=full
  3. mybatis-plus.configuration.mapper-locations=classpath*:mapper/*.xml

分页

@Configuration //就相当spring beans
public class MyBatiesPlusConfig implements MetaObjectHandler {

  1. @Bean //就相当于bean
  2. public PaginationInterceptor paginationInterceptor() {
  3. return new PaginationInterceptor();
  4. }
  5. @Override
  6. public void updateFill(MetaObject metaObject) {
  7. this.setFieldValByName("updateTime", new Date(), metaObject);
  8. }
  9. @Override
  10. public void insertFill(MetaObject metaObject) {
  11. this.setFieldValByName("createTime", new Date(), metaObject);
  12. this.setFieldValByName("updateTime", new Date(), metaObject);
  13. }

}

全局异常处理

@ControllerAdvice
@ResponseBody
public class GlobalExceptions {

  1. @ExceptionHandler
  2. public String otherExcepitom(Exception e){
  3. return Result.fail(ConstentUtil.FAIL_CODE,ConstentUtil.FAIL_MSG,e.getMessage());
  4. }

}

跨域处理

@Configuration
public class CrossOriginConfig {

  1. private CorsConfiguration builConfig(){
  2. CorsConfiguration corsConfiguration = new CorsConfiguration();
  3. corsConfiguration.addAllowedHeader("*");
  4. corsConfiguration.addAllowedMethod("*");
  5. corsConfiguration.addAllowedOriginPattern("*");
  6. // corsConfiguration.addAllowedOrigin("*");
  7. corsConfiguration.setAllowCredentials(true);
  8. return corsConfiguration;
  9. }
  10. @Bean
  11. public CorsFilter corsFilter(){
  12. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  13. source.registerCorsConfiguration("/**",builConfig());
  14. return new CorsFilter(source);
  15. }

}