01-SpringBoot基础


参考资料

SpringBoot2.4.3 官方文档

学习 SpringBoot 最权威的资料当然还是官方文档了:Spring Boot Reference Documentation
The reference documentation consists of the following sections(参考文档由如下部分组成):

Legal Legal information.
Documentation Overview About the Documentation, Getting Help, First Steps, and more.
Getting Started Introducing Spring Boot, System Requirements, Servlet Containers, Installing Spring Boot, Developing Your First Spring Boot Application
Using Spring Boot Build Systems, Structuring Your Code, Configuration, Spring Beans and Dependency Injection, DevTools, and more.
创建系统/工程,构建代码,配置,Spring Beans 和依赖注入,开发工具等等
Spring Boot Features Profiles 配置, Logging 日志, Security 安全, Caching 缓存, Spring Integration 集成, Testing 测试, and more.
Spring Boot Actuator Monitoring, Metrics, Auditing, and more.
Deploying Spring Boot Applications Deploying to the Cloud, Installing as a Unix application.
Spring Boot CLI Installing the CLI, Using the CLI, Configuring the CLI, and more.
Build Tool Plugins Maven Plugin, Gradle Plugin, Antlib, and more.
“How-to” Guides Application Development, Configuration, Embedded Servers, Data Access, and many more.

The reference documentation has the following appendices:

Application Properties Common application properties that can be used to configure your application.
Configuration Metadata Metadata used to describe configuration properties.
Auto-configuration Classes Auto-configuration classes provided by Spring Boot.
Test Auto-configuration Annotations Test-autoconfiguration annotations used to test slices of your application.
Executable Jars Spring Boot’s executable jars, their launchers, and their format.
Dependency Versions Details of the dependencies that are managed by Spring Boot.

【江南一点雨】

Bilibili 教程:https://space.bilibili.com/49484631/

SpringBoot 教程-案例代码

| code-samples | 对应的文章 |
| ————————– | ———————————————————————————————————————— | ——————————————————————————————– |
| spring-boot-starter-custom | 徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法! |
| api.js | Spring Boot + Vue 前后端分离开发,前端网络请求封装与配置 |
| javassm | 这一次,我连 web.xml 都不要了,纯 Java 搭建 SSM 环境 |
| properties | 是时候彻底搞清楚 Spring Boot 的配置文件 application.properties 了! |
| redis | Spring Boot 操作 Redis,三种方案全解析! |
| sessionshare | Spring Boot 一个依赖搞定 session 共享,没有比这更简单的方案了! |
| restful | Spring Boot 中 10 行代码构建 RESTful 风格应用 |
| shiro | Spring Boot 整合 Shiro ,两种方式全总结! |
| quartz | Spring Boot 中实现定时任务的两种方式! |
| ehcache | 另一种缓存,Spring Boot 整合 Ehcache |
| thymeleaf | 极简 Spring Boot 整合 Thymeleaf 页面模板 |
| exception | Spring Boot 中关于自定义异常处理的套路! |
| jdbctemplate | Spring Boot 数据持久化之 JdbcTemplate |
| jdbcmulti | Spring Boot 多数据源配置之 JdbcTemplate |
| mybatis | 最简单的 SpringBoot 整合 MyBatis 教程 |
| mybatismulti | 极简 Spring Boot 整合 MyBatis 多数据源 |
| jpa | 是时候了解下 Spring Boot 整合 Jpa 啦 |
| jpamulti | Spring Boot 整合 Jpa 多数据源 |
| jwt | 干货 | 一个案例学会 Spring Security 中使用 JWT! |
| security_json | SpringSecurity 登录使用 JSON 格式数据 |
| swagger2 | SpringBoot 整合 Swagger2,再也不用维护接口文档了! |
| cors | Spring Boot 中通过 CORS 解决跨域问题 |
| freemarker | Spring Boot 整合 Freemarker,50 多行配置是怎么省略掉的? |
| mail | Spring Boot 邮件发送的 5 种姿势! |
| docker | 一键部署 Spring Boot 到远程 Docker 容器,就是这么秀! |
| https | Spring Boot 支持 Https 有那么难吗? |
| jwt-demo | Spring Security 结合 Jwt 实现无状态登录 |
| docker-jib | 别用 Dockerfile 部署 Spring Boot 啦!松哥教你两步搞定! |

SpringBoot 四大核心

  • 自动配置
  • 起步依赖
  • Actuator
  • 命令行界面

【遇见狂神说】

Bilibili 教程:https://space.bilibili.com/95256449

KuangStudy:https://www.kuangstudy.com/course

博客园:https://www.cnblogs.com/hellokuangshen/tag/SpringBoot 系列/

【编程不良人】

学习资料下载:https://www.baizhiedu.xin/

Bilibili 教程:https://space.bilibili.com/352224540

【动力节点 PowerNode】

Bilibili 教程:https://space.bilibili.com/76542346

官网资料:http://www.bjpowernode.com/tutorial/

【Springmeng&王汉远】

Bilibili 教程-springmeng:https://space.bilibili.com/395452961/

Bilibili 教程-王汗远:https://space.bilibili.com/431642687/

【尚学堂】

Bilibili 教程:https://space.bilibili.com/392179313/

【扣丁狼】

Bilibili 教程:https://space.bilibili.com/320032672/

【C 语言中文网】

参考:http://c.biancheng.net/spring_boot/

SpringBoot 的前世今生

1、Spring 能做什么

1.1、Spring 的能力

image.png

1.2、Spring 的生态

https://spring.io/projects/spring-boot
覆盖了:

  • web 开发
  • 数据访问
  • 安全控制
  • 分布式
  • 消息服务
  • 移动开发
  • 批处理
  • ……

1.3、Spring5 重大升级

1.3.1、响应式编程
image.png
1.3.2、内部源码设计
基于 Java8 的一些新特性,如:接口默认实现。重新设计源码架构。

2、为什么用 SpringBoot

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
能快速创建出生产级别的 Spring 应用(简化开发)

2.1、SpringBoot 优点

  • Create stand-alone Spring applications
    • 创建独立 Spring 应用
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
    • 内嵌 web 服务器
  • Provide opinionated ‘starter’ dependencies to simplify your build configuration
    • 自动 starter 依赖,简化构建配置
  • Automatically configure Spring and 3rd party libraries whenever possible
    • 自动配置 Spring 以及第三方功能
  • Provide production-ready features such as metrics, health checks, and externalized configuration
    • 提供生产级别的监控、健康检查及外部化配置
  • Absolutely no code generation and no requirement for XML configuration
    • 无代码生成、无需编写 XML

      SpringBoot 是整合 Spring 技术栈的一站式框架
      SpringBoot 是简化 Spring 技术栈的快速开发脚手架

2.2、SpringBoot 缺点

  • 人称版本帝,迭代快,需要时刻关注变化
  • 封装太深,内部原理复杂,不容易精通

3、时代背景

3.1、微服务

James Lewis and Martin Fowler (2014) 提出微服务完整概念。https://martinfowler.com/microservices/

In short, the** microservice architectural style** is an approach to developing a single application as a suite of small services, each running in its own process and communicating with **lightweight **mechanisms, often an **HTTP **resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.– James Lewis and Martin Fowler (2014)

  • 微服务是一种架构风格
  • 一个应用拆分为一组小型服务
  • 每个服务运行在自己的进程内,也就是可独立部署和升级
  • 服务之间使用轻量级 HTTP 交互
  • 服务围绕业务功能拆分
  • 可以由全自动部署机制独立部署
  • 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术

3.2、分布式


分布式的困难

  • 远程调用
  • 服务发现
  • 负载均衡
  • 服务容错
  • 配置管理
  • 服务监控
  • 链路追踪

日志管理

  • 任务调度
  • ……

分布式的解决

  • SpringBoot + SpringCloud

3.3、云原生

原生应用如何上云。 Cloud Native

上云的困难

  • 服务自愈
  • 弹性伸缩
  • 服务隔离
  • 自动化部署
  • 灰度发布
  • 流量治理
  • ……

上云的解决

4、如何学习 SpringBoot

4.1、官网文档架构

image.png

image.png

查看版本新特性;
https://github.com/spring-projects/spring-boot/wiki#release-notes
image.png

前后端分离数据交互

Java 后端和 Vue 前端数据交互一般采用 JSON 格式

基本方式

封装 RespBean 类

package com.xjt.blog.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RespBean {
    private Integer status = 0;
    private String msg;
    private Object obj;

    public static RespBean build(){
        return new RespBean();
    }

    public static RespBean ok(String msg){
        return new RespBean(200,msg,null);
    }

    public static RespBean ok(String msg, Object obj){
        return new RespBean(200,msg,obj);
    }

    public static RespBean error(String msg){
        return new RespBean(500,msg,null);
    }

    public static RespBean error(String msg, Object obj){
        return new RespBean(500,msg,obj);
    }
}

使用示例:

@RequestMapping("/get")
public Result get(){
    HashMap map = new HashMap();
    map.put("username","admin");
    map.put("password","123456");
    Result r = new Result();
    r.code(Result.SUCCESS).message("成功访问").data(map);
    return r;
}

高级用法

参考 RuoYi 项目

pom.xml

pom.xml 文件标签

<?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>
  <!--继承 SpringBoot 框架的一个父项目,所有自己开发的 Spring Boot 都必须的继承-->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <!--当前项目的 GAV 坐标-->
  <groupId>com.bjpowernode.springboot</groupId>
  <artifactId>002-springboot-springmvc</artifactId>
  <version>1.0.0</version>

  <!--maven 项目名称,可以删除-->
  <name>002-springboot-springmvc</name>
  <!--maven 项目描述,可以删除-->
  <description>Demo project for Spring Boot</description>

  <!--maven 属性配置,可以在其它地方通过${}方式进行引用-->
  <properties>
  	<java.version>1.8</java.version>
  </properties>

  <!--maven依赖-->
  <dependencies>

  </dependencies>

  <build>
    <plugins>
      <!--SpringBoot 提供的打包编译等插件-->
      <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

  <!--保留src/main/java 路径下的xml数据库映射文件-->
  <resources>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>

    <resource>
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>
  </resources>
</project>

常用的 Maven 依赖

<!--springboot的web服务starter-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--springboot测试starter-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!--热部署-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <scope>runtime</scope>
  <optional>true</optional>
</dependency>

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

<!--mysql数据库连接驱动-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.25</version>
</dependency>
<!--mybatis-plus-->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.4.2</version>
</dependency>

<!--集成thymeleaf模板-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!--集成redis数据库-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--集成javax.mail邮件-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>2.4.1</version>
</dependency>

<!--集成springsecurity安全框架-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>	<!--springsecurity测试(可选)-->
    <scope>test</scope>
</dependency>

<!--导入shiro-redis的starter包-->
<dependency>
  <groupId>org.crazycake</groupId>
  <artifactId>shiro-redis-spring-boot-starter</artifactId>
  <version>3.3.1</version>
</dependency>

<!-- hutool工具类-->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.1.4</version>
</dependency>

<!--jwt-->
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

<!--集成druid数据库连接池 springboot2.x以上默认使用com.zaxxer.hikari.HikariDataSource 数据源-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.24</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>		<!--druid连接池需要log4j日志框架-->
    <version>1.2.17</version>
</dependency>

配置 Annotation Processor
可以帮助我们生成自定义配置的元数据信息,让配置文件和 Java 代码之间的对应参数可以自动定位,方
便开发。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

maven 离线安装 jar

##1、首先到mvnrepository下载jar包
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <version>9.0.40</version>
</dependency>

##2、安装命令
mvn install:install-file -Dfile=tomcat-embed-jasper.jar -DgroupId=org.apache.tomcat.embed -DartifactId=tomcat-embed-jasper -Dversion=9.0.40 -Dpackaging=jar

核心配置文件

配置文件可以存放在四个不同位置,对应的优先级也不同
image.png

application.properties

server.port=8181
server.servlet.context-path=/shiro
spring.application.name=shiro-jsp

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/my-shiro-jsp?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

mybatis.mapper-locations=classpath*:mapper/*.xml
mybatis.type-aliases-package=com.xjt.entity
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

application.yaml

fdfs:
  soTimeout: 1500
  connectTimeout: 600
  thumbImage:
    width: 150
    height: 150
  trackerList:
    - 192.168.157.129:22122

spring:
  datasource:
    driver-class-name: MySQL
    url: MySQL
    username: root
    password: root
    type:
      com.alibaba.druid.pool.DruidDataSource

  profiles:
    active: dev			#2.4以上版本不同

  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 1000MB

  # 配置 redis
  redis:
  	port: 6379
  	host: 127.0.0.1
  	database: 0
  	timeout: 3000

  mvc:
    view:
      prefix: /
      suffix: .html

server:
  port: 8080
  servlet:
    context-path: /

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    cache-enabled: true
  mapper-locations: classpath:/mapper/*.xml
  type-aliases-package: com.xjt.shiro.domain

自定义配置

在 SpringBoot 的核心配置文件中,除了使用内置的配置项之外,我们还可以在自定义配置,然后采用注解去读取配置
的属性值。有两种方式的自定义配置项,一是将所有配置项都放在 application.properties,二是拆分出其他配置文件
1、在核心配置文件 applicatin.properties 中,添加两个自定义配置项
在 IDEA 中可以看到这两个属性不能被 SpringBoot 识别,背景是桔色的
image.png

@Value("${xjt.name}")
private String name;

2、自定义配置文件,通过注解初始化@PropertySource @Value @ConfigurationProperties
image.png
@PropertySource 和 @Value

@Component
@PropertySource(value = {"classpath:props/person.properties"})
public class MyPeople {
    @Value("${person.name}")
    private String name;

    @Value("${person.sex}")
    private Integer sex;

    @Value("${person.age}")
    private Integer age;

    @Value("${person.city}")
    private String city;

    @Value("${person.school}")
    private String school;
}

@PropertySource 和 @ConfigurationProperties

@Component
@PropertySource(value = {"classpath:props/datasource.properties"})
@ConfigurationProperties(prefix = "xxxmysql.datasource")
@Data
public class MyJDBC {
    private String driver;
    private String url;
    private String username;
    private String password;
}

注意:xxxmysql.datasource 前缀的属性 必须和 MyJDBC 对应是字段名称一致

IDEA 相关

mvn 下载框架的 java 源码

如 springboot 项目无法查看源码用 bash 切换到项目的 目录 有 pom.xml 的地方在终端中输入

mvn dependency:resolve -Dclassifier=sources

项目打包&部署

1、打包并运行 jar

在命令行中运行某个 jar 包

java -jar xxx.jar
java -jar xxx.jar --server.port=8181		#指定端口

Maven

<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>		<!--父依赖版本号-->
        <relativePath/> 	<!-- lookup parent from repository -->
    </parent>

	<groupId>org.example</groupId>
	<artifactId>springboot_thymeleaf_shiro</artifactId>
	<version>1.0-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>
</project>

2、打成 war 包

SpringBoot 解决跨域问题跨域

目前大型项目一般采用的是前后端分离,当使用前端 vue + axios 发送跨域请求时会报错,如下
image.png
有如下解决方式:

全局配置

config/MyWebMvcConfig.java

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
/**
     * 就是注册的过程,注册Cors协议的内容。
     * 如: Cors协议支持哪些请求URL,支持哪些请求类型,请求时处理的超时时长是什么等。
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")	// 所有的当前站点的请求地址,都支持跨域访问。
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 当前站点支持的跨域请求类型
                .allowCredentials(true) 	// 是否支持跨域用户凭证
                .allowedOrigins("*") 	// 所有的外部域都可跨域访问。 如果是localhost则很难配置,因为在跨域请求的时候,外部域的解析可能是localhost、127.0.0.1、主机名
                .maxAge(60); // 超时时长设置为1小时。 时间单位是秒。
    }
}

单个接口使用注解@CrossOrigin

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@CrossOrigin(origins = "*",maxAge = 3600)
public class UserController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/getOne/{id}")
    public User getOne(@PathVariable("id") Integer id) {
        return userMapper.getById(id);
    }
}

/user/** 开头的请求可以跨域,其他请求 如 /book/** 就不行了

自定义跨域过滤器

1、编写过滤器

public class CrosFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        HttpServletRequest req = (HttpServletRequest) request;

        String origin = req.getHeader("Origin");

        if (!org.springframework.util.StringUtils.isEmpty(origin)) {
            //带cookie的时候,origin必须是全匹配,不能使用*
            res.addHeader("Access-Control-Allow-Origin", origin);
        }

        res.addHeader("Access-Control-Allow-Methods", "*");

        String headers = req.getHeader("Access-Control-Request-Headers");

        // 支持所有自定义头
        if (!org.springframework.util.StringUtils.isEmpty(headers)) {
            res.addHeader("Access-Control-Allow-Headers", headers);
        }

        res.addHeader("Access-Control-Max-Age", "3600");

        // enable cookie
        res.addHeader("Access-Control-Allow-Credentials", "true");

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

2、注册过滤器

@Bean
public FilterRegistrationBean registerFilter(){
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.addUrlPatterns("/*");
    bean.setFilter(new CrosFilter());
    return bean;
}

使用 nginx 反向代理服务器解决跨域问题

1、在 nginx 的 conf 目录下,创建 vhosts 文件夹
2、在 nginx.conf 文件中添加 include vhosts/*.conf
image.png
3、vhost 目录下创建 abc.conf 文件
image.png

thymeleaf

基础

th:src th:href 路径

image.png
image.png

WebMvcConfigurer 配置

addResourceHandlers 资源处理器

image.png
案例:上传文件保存到项目根路径,想要直接通过 http://127.0.0.1:8888/img/singerPic/123.jpg 访问,需要我们配置 addResourceHandlers 资源处理器

@Configuration
public class FileConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        //歌手头像地址
        registry.addResourceHandler("/img/singerPic/**").addResourceLocations(
                "file:"+System.getProperty("user.dir")+System.getProperty("file.separator")+"img"
                +System.getProperty("file.separator")+"singerPic"+System.getProperty("file.separator")
        );
    }
}

说一下 file:///D:/ 是什么呢??
这是 UNC 定义的一种本地绝对路径的表示方式,可以在浏览器中直接这样访问
image.png
来看看这些吧:

String path = "file:" + System.getProperty("user.dir")
    + System.getProperty("file.separator") + "img"
    + System.getProperty("file.separator") + "songListPic"
    + System.getProperty("file.separator");

//项目的绝对路径
System.out.println(System.getProperty("user.dir"));     //D:\CodeLearning\JavaLearning\JavaProjects\github_master\王汉远-springboot+vue音乐网站\分章节源码\music142 程序完成\music-server
//系统文件分隔符
System.out.println(System.getProperty("file.separator"));       // \  (windows系统是\  Linux系统是 /)

System.out.println(path);       //file:D:\CodeLearning\JavaLearning\JavaProjects\github_master\王汉远-springboot+vue音乐网站\分章节源码\music142 程序完成\music-server\img\songListPic\

Lombok

https://www.jianshu.com/p/2543c71a8e45
Lombok 有啥牛皮的?SpringBoot 和 IDEA 官方都要支持它!
最近IDEA 2020 最后一个版本发布了,已经内置了 Lombok 插件,SpringBoot 2.1.x 之后的版本也在 Starter 中内置了 Lombok 依赖。

为什么他们都要支持 Lombok 呢?

以前的 Java 项目中,充斥着太多不友好的代码:

  • POJO 的 getter/setter/toString;
  • 异常处理;
  • I/O 流的关闭操作等等

这些样板代码既没有技术含量,又影响着代码的美观,Lombok 应运而生。

添加 IDEA 工具对 Lombok 的支持
点击 File– Settings 设置界面,安装 Lombok 插件:
image.png
引入 jar 包

<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.16</version>
 </dependency>

Lombok 常用注解

@Data
作用在类上,生成所有成员变量的 getter/setter 方法和类的 toString 方法,最常用
是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter

@Getter、@Setter
作用类上,生成所有成员变量的 getter/setter 方法;
作用于成员变量上,生成该成员变量的 getter/setter 方法。可以设定访问权限及是否懒加载等。

@ToString
作用于类,覆盖默认的 toString()方法,可以通过 of 属性限定显示某些字段,通过 exclude 属性排除某些字段。
image.png
@EqualsAndHashCode
作用于类,覆盖默认的 equals 和 hashCode

@NonNull
主要作用于成员变量和参数中,标识不能为空,否则抛出空指针异常。
image.png
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
作用于类上,用于生成构造函数。有 staticName、access 等属性。
staticName 属性一旦设定,将采用静态方法的方式生成实例,access 属性可以限定访问权限。
@NoArgsConstructor:生成无参构造器;
@RequiredArgsConstructor:生成包含 final 和@NonNull 注解的成员变量的构造器;
@AllArgsConstructor:生成全参构造器
image.png
@Builder
作用于类上,将类转变为建造者模式

@Log
作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解:

Swagger2

官网:https://swagger.io/
https://zhuanlan.zhihu.com/p/98075551

快速上手

  • pom 引入依赖
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
  • 项目中新建 SwaggerConfig.java 配置

@Configuration
@EnableSwagger2        //开启swagger2
public class SwaggerConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 解决静态资源无法访问
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");

        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(xiaomingApiInfo())
                .groupName("xiaoxiong")
                .select()
                //为任何请求处理生成API文档
                .apis(RequestHandlerSelectors.any())
                //过滤路径
                .paths(PathSelectors.any())
                .build();
        //添加登录认证
            /*.securitySchemes(securitySchemes())
            .securityContexts(securityContexts());*/
    }

    private ApiInfo xiaomingApiInfo() {
        //作者联系方式
        Contact contact = new Contact("xiaoxiong", "https://github.com/BFD2018", "1351655382@qq.com");
        return new ApiInfoBuilder()
                .title("SwaggerUI演示")
                .description("接口文档,描述词省略200字")
                .contact(contact)
                .version("v1.0")
                .build();
    }
}

swagger-ui.html 静态资源存放位置:

  • com.xjt.controller.SwaggerController.java


可以配置多个 Docket,协同开发 ,谁干了哪些活 很清晰

配置

Docket Bean 配置项

@Bean
public Docket createRestApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(xiaomingApiInfo())
        .groupName("小明")
        .select()
        //1、为com.xjt.controller包下Controller生成API文档
        //.apis(RequestHandlerSelectors.basePackage("com.xjt.controller"))
        //2、为有@Api注解的Controller生成API文档
        //.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
        //3、扫描类上有@RestController注解
        //.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
        //为有@ApiOperation注解的方法生成API文档
        //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
        //扫描方法上有@GetMapping注解
        //.apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
        //为任何接口生成API文档

        .apis(RequestHandlerSelectors.any())

        //过滤路径
        .paths(PathSelectors.any())
        .build();

        //添加登录认证
        /*.securitySchemes(securitySchemes())
            .securityContexts(securityContexts());*/
}
private ApiInfo xiaomingApiInfo() {
    //作者联系方式
    Contact contact = new Contact("kuangshenshuo", "http://kuangstudy.com", "1351655382@qq.com");
    return new ApiInfoBuilder()
        .title("SwaggerUI演示")
        .description("接口文档,描述词省略200字")
        .contact(contact)
        .version("v1.0")
        .build();
}

注解配置

@Api(tags = "用户相关模块")		//Controller类注解
@Controller
@RequestMapping(value = "/api/")
public class SwaggerController {
    @ApiOperation(value = "查找用户")		//方法注解
    @GetMapping("/user")
    @ResponseBody
    private String getUser(){
        return "hello-world!";
    }

    @ApiOperation(value = "注册用户")
    @PostMapping("/register")
    @ResponseBody
    private User registerUser(String name,Integer age){
        User user = new User();
        user.setName(name);
        user.setAge(age);
        return user;
    }
}

swagger-ui 上显示:

@ApiModel(value = "User-model")
@Data
public class User {
    @ApiModelProperty("User-name")
    private String name;
    @ApiModelProperty("User-age")
    private Integer age;
    private String phone;
}

swagger-ui 上显示:(注意:只有 Controller 方法中返回 Model 才能显示)

@ApiOperation(value = "注册用户")
@PostMapping("/register")
@ResponseBody
private User registerUser(@ApiParam(value = "用户名") String name, @ApiParam(value = "用户年龄") Integer age){
    User user = new User();
    user.setName(name);
    user.setAge(age);
    return user;
}

swagger-ui 上显示:

生产环境去掉 Swagger

com.xjt.config.SwaggerConfig.java

@Bean
public Docket docket2(Environment environment) {
    //设置要显示的swagger环境
    Profiles profiles = Profiles.of("dev", "test");
    //通过environment.acceptsProfiles() 判断是否处于dev 或test环境
    boolean flag = environment.acceptsProfiles(profiles);
    return new Docket(DocumentationType.SWAGGER_2)
        .groupName("小刚")
        .apiInfo(xiaogangApiInfo())
        .enable(flag)		//开启swagger2
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.xjt.controller"))
        .build();
}

springboot 配置文件

显示出来了

日志配置

背景:我们都知道 springboot 默认日志是打印在控制台中的,不会以文件的形式进行保存。那么日后系统上线肯定是有需要对日志进行定位分析问题的,那么如何实现将控制台输出的日志保存起来?
话不多说,实际效果如下,如果是你预期的那样,咱们接着往下看。

如下是集成,按步骤来:
1、在项目的 resources 目录下创建一个名为 logback-spring.xml 的日志配置文件,配置文件名最好跟我一样;
image.png
2、编写 xml 文件内容:
code 中每句都给出了注释,方便你们理解。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- 引入默认得配置文件 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <!-- 模块名标识日志名称 -->
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- info日志单文件大小限制 -->
    <springProperty scope="context" name="logback.fileInfoLog.maxFileSize" source="logback.fileInfoLog.maxFileSize" defaultValue="200MB" />
    <!-- info日志最大保留时长单位天 -->
    <springProperty scope="context" name="logback.fileInfoLog.maxHistory" source="logback.fileInfoLog.maxHistory" defaultValue="15" />
    <!-- info日志文件总大小,超过该大小,旧得即将删除 -->
    <springProperty scope="context" name="logback.fileInfoLog.totalSizeCap" source="logback.fileInfoLog.totalSizeCap" defaultValue="100GB" />

    <!-- error日志单文件大小限制 -->
    <springProperty scope="context" name="logback.fileErrorLog.maxFileSize" source="logback.fileErrorLog.maxFileSize" defaultValue="200MB" />
    <!-- error日志最大保留时长单位天 -->
    <springProperty scope="context" name="logback.fileErrorLog.maxHistory" source="logback.fileErrorLog.maxHistory" defaultValue="15" />
    <!-- error日志文件总大小,超过该大小,旧得即将删除 -->
    <springProperty scope="context" name="logback.fileErrorLog.totalSizeCap" source="logback.fileErrorLog.totalSizeCap" defaultValue="100GB" />

    <!-- http日志单文件大小限制 -->
    <springProperty scope="context" name="logback.fileHttpLog.maxFileSize" source="logback.fileHttpLog.maxFileSize" defaultValue="200MB" />
    <!-- http日志最大保留时长单位天 -->
    <springProperty scope="context" name="logback.fileHttpLog.maxHistory" source="logback.fileHttpLog.maxHistory" defaultValue="15" />
    <!-- http日志文件总大小,超过该大小,旧得即将删除 -->
    <springProperty scope="context" name="logback.fileHttpLog.totalSizeCap" source="logback.fileHttpLog.totalSizeCap" defaultValue="100GB" />
    <!-- 日志目录 -->
    <springProperty scope="context" name="logback.rootDir" source="logback.rootDir" defaultValue="logs"/>
    <!-- 控制台输出得日志格式 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <!-- 日志文件输出得日志格式 -->
    <property name="FILE_LOG_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %t [%c:%L]-%m%n"/>
    <!-- 控制台输出 -->
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </layout>
    </appender>
    <!-- info日志得设定 -->
    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${logback.rootDir}/${springAppName}.log</file>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" >
            <!--路径-->
            <fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
            <maxFileSize>${logback.fileInfoLog.maxFileSize}</maxFileSize>
            <maxHistory>${logback.fileInfoLog.maxHistory}</maxHistory>
            <totalSizeCap>${logback.fileInfoLog.totalSizeCap}</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>

    <!-- 错误日志 -->
    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${logback.rootDir}/${springAppName}-error.log</file>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" >
            <!--路径-->
            <fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-error-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
            <maxFileSize>${logback.fileErrorLog.maxFileSize}</maxFileSize>
            <maxHistory>${logback.fileErrorLog.maxHistory}</maxHistory>
            <totalSizeCap>${logback.fileErrorLog.totalSizeCap}</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>

    <!-- http日志 -->
    <appender name="httpInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %m%n</pattern>
        </encoder>
        <file>${logback.rootDir}/${springAppName}-http.log</file>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--路径-->
            <fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-http-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
            <maxFileSize>${logback.fileHttpLog.maxFileSize}</maxFileSize>
            <maxHistory>${logback.fileHttpLog.maxHistory}</maxHistory>
            <totalSizeCap>${logback.fileHttpLog.totalSizeCap}</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>

    <appender name="ASYNC_consoleLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="consoleLog"/>
    </appender>
    <appender name="ASYNC_fileInfoLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="fileInfoLog"/>
    </appender>
    <appender name="ASYNC_fileErrorLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="fileErrorLog"/>
    </appender>
    <appender name="ASYNC_httpInfoLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="httpInfoLog"/>
    </appender>

    <root level="info">
        <appender-ref ref="ASYNC_consoleLog" />
        <appender-ref ref="ASYNC_fileInfoLog" />
        <appender-ref ref="ASYNC_fileErrorLog" />
    </root>
    <logger name="log_http" additivity="false" level="INFO">
        <appender-ref ref="ASYNC_httpInfoLog"/>
    </logger>

</configuration>

3、配置日志配置中所提到的 springAppName;
image.png
4、使用这个默认不用配置 pom 依赖,最新的 spring-boot-starter-web 中已经集成了。如下,重启下项目就能自动生成日志文件了,而且是实时写入的,控制台输出什么,立马就更新进到该 xxx.log 里头。
image.png
记得,配置日志完后,记得刷新下 maven 或者关闭下项目重新打开,以免误导大家以为日志配置没用。

原文链接:https://blog.csdn.net/weixin_43970743/article/details/115767763

另外:
想要在控制台打印 sql,如下:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台打印sql执行语句
    cache-enabled: true
  mapper-locations: classpath:/mapper/*.xml #映射XXXmapper.xml文件路径
  type-aliases-package: com.xjt.travel.domain #包名


文章作者: CoderXiong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 CoderXiong !
  目录