1、快速生成mapper和service
(1)(自动生成简单的单表sql)
(2)快速生成多表(自动生成常量)
2、springboot配置swagger(路径不用加/api)
(1)主pom导包(子pom要引用,可选依赖)
<!-- swagger3用-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
(2)配置swagger和mvc
server:
port: 8081
spring:
# swagger使用
mvc:
path-match:
matching-strategy: ant_path_matcher
datasource:
# 指定连接池的类型
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: "jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai"
username: "root"
password: "lht660036"
max-active: 20
# ???
# wall ??druid ???
# stat ??druid?????
filters: "wall,slf4j,stat"
web-stat-filter:
enabled: true
url-pattern: /*
# ??????????
exclusions: "/druid,*.png"
# ???????
stat-view-servlet:
enabled: true
url-pattern: "/druid/*"
reset-enable: true
login-username: admin
login-password: admin
mybatis:
# ??mapper.xml
mapper-locations: "classpath*:mapper/**/*.xml"
# ???
type-aliases-package: "com.lht.project.data.mybatis.entity"
swagger:
base-package: "com.lht.project.data.mybatis.controller"
title: "京东商城在线Api文档"
group-name: "订单商城"
description: "出现bug,请熟读该文档"
name: "lht帅哥"
url: "https://www.baidu.com"
email: "11111@163.com"
version: "1.0.0"
(3)定义swaggerProperties
package com.lht.project.data.mybatis.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("swagger")
@Data
public class SwaggerProperties {
private String title;
private String basePackage;
private String groupName;
private String description;
private String name;
private String url;
private String email;
private String version;
}
(4)定义swaggerConfig
package com.lht.project.data.mybatis.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.annotation.Resource;
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Resource
private SwaggerProperties swaggerProperties;
@Bean
public Docket docket(ApiInfo apiInfo){
return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo)
.groupName(swaggerProperties.getGroupName())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(PathSelectors.any())
.build();
}
@Bean
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.version(swaggerProperties.getVersion())
.contact(new Contact(swaggerProperties.getName(), swaggerProperties.getUrl(), swaggerProperties.getEmail()))
.build();
}
}
(5)controller调用
3、配置junit5、日志(springboot自带)
4、日志的级别
info(正常信息)、debug、error(异常信息)
5、mybatisplus用了之后mybatis取别名就用不了了
6、目前导包都是写在父工程dependencyManagement里面,然后子类去调用的
7、springboot整合mybatisplus(自动有很多sql单表)
(1)父pom导入依赖(子也要引用)
<!-- mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
(2)mapper里面继承basemapper
public interface BrandMapper extends BaseMapper<Brand> {
}
(3)在实体类上映射好数据库表名与类名、属性名和字段名
package com.lht.project.data.mybatis.entity;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
@TableName("sys_brand")
public class Brand {
/**
* 主键
*/
@TableId(value = "brand_id",type = IdType.ASSIGN_ID)
private Integer brandId;
/**
* 中文名
*/
@TableField("chinese_name")
private String chineseName;
/**
* 英文名
*/
@TableField("english_name")
private String englishName;
/**
* 产地id
*/
@TableField("producer_id")
private Integer producerId;
/**
* 备注
*/
@TableField("notes")
private String notes;
/**
* 图案(string)代替
*/
@TableField("logo")
@TableLogic(value = "1",delval = "0")
private String logo;
/**
* 创建时间
*/
@TableField("create_date")
private Date createDate;
//动态select去除列用
public static final String COL_CHINESE_NAME="chinese_name";
public static final String COL_STATUS="status";
}
8、分页查询
9、 QueryWrapper条件构造器
QueryWrapper<Brand> queryWrapper = new QueryWrapper<>();
queryWrapper.select().eq().gt()
queryWrapper相当于where
select() | 过滤列 |
eq() | = |
ne() | != |
allEq() | 检查所有参数是否相等 |
gt() | > |
ge() | >= |
lt | < |
le | <= |
between() | 范围 |
notBetween() | 非范围 |
like | 模糊查询 |
notLike | 不进行模糊匹配查询的条件 |
likeLeft | %k |
likeRight | k% |
in | 多条件 |
(1)用法
1)实体类写固定值
2)写构造器
package com.lht.project.data.mybatis.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lht.project.data.mybatis.entity.Brand;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@Slf4j
public class BrandMapperTest {
@Resource
private BrandMapper brandMapper;
@Test
void selectOne() {
//条件构造器
QueryWrapper<Object> qw = new QueryWrapper<>();
qw.eq(Brand.COL_CHINESE_NAME,"张三").or().eq(Brand.COL_STATUS,"1");
}
}
12、选中之后control+shirt+U强转为大写
13、like索引必失效
14、创建全文索引(索引就不会失效了)
CREATE FULLTEXT INDEX idx_product_name 0N pms_product (product_name);
15、数据库表,主表增删改,用InnoDB(有事务,查询慢所以不用),从表查询,用MyISAM(不支持事务,查询效率高)
16、排序,分组,过滤列
17、条件函数一般与groupBy配合使用
18、测试list里面存放map
@Test
void selectMaps() {
QueryWrapper<Brand> qw = new QueryWrapper<>();
qw.select("COUNT(*) product_count","AVG(product_price) product_avg")
.groupBy("producer_id");
List<Map<String, Object>> maps = brandMapper.selectMaps(qw);
log.info("测试分组函数");
}
19、封装分页(mybatisplus)
(1)添加配置类
package com.lht.project.data.mybatis.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//注册所有的mapper接口
@MapperScan("com.lht.**.mapper")
public class MybatisPlusConfig {
/**
* 乐观锁
* @param paginationInnerInterceptor
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(PaginationInnerInterceptor paginationInnerInterceptor){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
/**
* 分页插件注册
* @return
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor(){
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
return paginationInnerInterceptor;
}
}
(2)调用执行
void selectPage(){
Page<Brand> brandPage = brandMapper.selectPage(new Page<>(1, 10), null);
log.info("总页数===>{}: 测试占位符{}",brandPage.getPages(),"1111");
log.info("核心数据{}",brandPage.getRecords());
log.info("总条数{}",brandPage.getTotal());
}
20、" "那里如果反方向的话就会判断多次
21、typeId的类型
22、配置全局雪花id+逻辑删除
(1)全局(不推荐)
(2)局部
23、配置逻辑删除(都要加注解)
(1)全局
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为0)
(2)局部 (就是写value)
(3)作用:自动加状态码(都要查的时候不适用)
24、乐观锁与悲观锁
1.悲观锁是当线程拿到资源时,就对资源上锁,并在提交后,才释放锁资源,其他线程才能使用资源。
2.乐观锁是当线程拿到资源时,上乐观锁,在提交之前,其他的锁也可以操作这个资源,当有冲突的时候,并发机制会保留前一个提交,打回后一个提交,让后一个线程重新获取资源后,再操作,然后提交。和git上传代码一样,两个线程都不是直接获取资源本身,而是先获取资源的两个copy版本,然后在这两个copy版本上修改。
3.悲观锁和乐观锁在并发量低的时候,性能差不多,但是在并发量高的时候,乐观锁的性能远远优于悲观锁
全文们常用的synchronized是悲观锁,lock是乐观锁
25、配置乐观锁
(1)配置类
package com.lht.project.data.mybatis.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//注册所有的mapper接口
@MapperScan("com.lht.**.mapper")
public class MybatisPlusConfig {
/**
* 乐观锁
* @param paginationInnerInterceptor
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(PaginationInnerInterceptor paginationInnerInterceptor){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
/**
* 分页插件注册
* @return
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor(){
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
return paginationInnerInterceptor;
}
}
(2)在实体类的字段上加上@Version
注解(只能是时间和数字)
26、配置validaton参数校验流程
(1)导包
<!-- 参数校验依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
(2)配置类(一次只能拿到一个属性的信息)
package com.lht.project.web.validation.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
@Configuration
public class ValidationConfig {
@Bean
public Validator validator(){
return Validation
.byProvider(HibernateValidator.class)
.configure()
// 快速校验
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}
(3)调用
package com.lht.project.web.validation.controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@PostMapping("/info")
public String getUserInfo(@Min(value = 1,message = "用户的id过小") @Max(value = 1000,message = "用户的id过大")@RequestBody Integer userId){
return "";
}
}
27、validation参数
@Max | 指定一个数值的最大值 |
@Min | 指定一个数值的最小值 |
@NotNull | |
@Null | |
@Size | 指定一个字符串的长度范围(@Size(min=5, max=10)) |
@Pattern | 匹配指定的正则表达式 |
@Future | 指定一个日期必须是未来日期 |
@Past | 指定一个日期必须是过去日期 |
@DecimalMax | 指定十进制数的最大值 |
@DecimalMin | 指定十进制数的最小值 |
28、validation校验分类
(1)普通参数
(2)QO对象/DTO校验(必须两边都写)
(3)分组校验(形参必须使用@Validated)
(4)关联校验
嵌套里面的属性不用管,只负责外面Valid的notNull就好了
28、shirft+F6快速更改类名
29、json必须传递对象
30、validaton注解使用区别
既可以使用@Validated注解,也可用使用@Valid注解,的话形参那边只能用@Validated,用@Valid
@Valid | @Validated |
普通参数、嵌套校验 | 普通参数、分组形参 |
31、validation报错分类(对应不同的捕获异常处理)
(1)普通参数:ConstraintViolationException
(2)普通对象 :BindException
(3)json对象 :MethodArgumentNotValidException(BindException的子类)
32、得到类上的所有的信息
33、参数处理完后配置全局异常流程(只要写参数校验)
(1)定义异常信息封装类
package com.lht.project.web.validation.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 获取异常信息类
* @author liuhuitang
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ArgsErrorInfo {
private String errorMessage;
private String fileName;
}
(2)封装信息、状态码
package com.lht.project.web.validation.result;
import lombok.Data;
/**
* 状态的跟信息
*
* @param <T>
*/
@Data
public class ResponseResult<T> {
private int code;
private String msg;
private T data;
public static <T> ResponseResult<T> success(T data) {
return success(ResultStatus.SUCCESS,data);
}
public static <T> ResponseResult<T> success(ResultStatus resultStatus, T data) {
return common(resultStatus, data);
}
public static <T> ResponseResult<T> error(ResultStatus resultStatus) {
return common(resultStatus, null);
}
// 传递错误信息到前端
public static <T> ResponseResult<T> error(ResultStatus resultStatus,T errorData){
return common(resultStatus, errorData);
}
public static <T> ResponseResult<T> error() {
return error(ResultStatus.SYS_ERROR);
}
private static <T> ResponseResult<T> common(ResultStatus resultStatus, T data) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(resultStatus.getCode());
result.setMsg(resultStatus.getMsg());
result.setData(data);
return result;
}
}
package com.lht.project.web.validation.result;
import lombok.Getter;
@Getter
@SuppressWarnings("all")
public enum ResultStatus {
SUCCESS(20000, "成功"),
SYS_ERROR(40000, "系统错误"),
USER_PARAM_ERROR(40001, "用户名格式不正确"),
USER_NO_EXIST(40002, "用户名不存在"),
USER_PASSWORD_ERROR(40003, "密码错误"),
USER_LOGIN_ERROR (40004, "用户名或者密码错误"),
USER_ACCOUNT_ERROR (40005, "账号被禁用"),
PICTURE_UPLOAD_ERROR (40006, "图片上传异常"),
PICTURE_DOWNLOAD_ERROR (40007, "图片下载异常"),
ARGS_VALID_ERROR (40008, "参数校验失败");
final int code;
final String msg;
ResultStatus(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
(3)取消快速校验
package com.lht.project.web.validation.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
@Configuration
public class ValidationConfig {
// @Bean
// public Validator validator(){
// return Validation
// .byProvider(HibernateValidator.class)
// .configure()
快速校验
// .failFast(true)
// .buildValidatorFactory()
// .getValidator();
// }
}
(4)配置全局异常
package com.smart.community.common.base.handler;
import cn.hutool.core.util.ReflectUtil;
import com.smart.community.common.base.dto.ArgsErrorInfo;
import com.smart.community.common.base.ex.BaseException;
import com.smart.community.common.base.result.ResponseResult;
import com.smart.community.common.base.result.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.List;
import java.util.stream.Collectors;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseResult<Object> handlerException(Exception ex) {
ex.printStackTrace();
log.error("错误的信息:{}", ex.getMessage());
return ResponseResult.error();
}
/**
* 处理BaseException类型的异常
* @param ex
* @return
*/
@ExceptionHandler(BaseException.class)
public ResponseResult<Object> handlerBaseException(BaseException ex) {
ex.printStackTrace();
// 返回一个ResponseResult对象,
// 该对象的状态是“错误”。
// 它使用异常的getResultStatus()方法返回的状态作为其错误状态
return ResponseResult.error(ex.getResultStatus());
}
/**
* 单参数校验
* 属性名 错误信息
*
* @param ex
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public ResponseResult<List<ArgsErrorInfo>> handlerException(ConstraintViolationException ex) {
ex.printStackTrace();
return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getConstraintViolations().stream()
.map(violation -> {
List<Path.Node> nodeList = (List<Path.Node>) ReflectUtil.getFieldValue(violation.getPropertyPath(), "nodeList");
return ArgsErrorInfo.builder().fileName(nodeList.get(nodeList.size() - 1).getName())
.errorMessage(violation.getMessage())
.build();
}
).collect(Collectors.toList()));
}
/**
* 对象校验
*
* @param ex
* @return
*/
@ExceptionHandler(BindException.class)
public ResponseResult<List<ArgsErrorInfo>> handlerException(BindException ex) {
ex.printStackTrace();
return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getBindingResult().getFieldErrors().stream()
.map(fieldError -> ArgsErrorInfo.builder()
.fileName(fieldError.getField()).errorMessage(fieldError.getDefaultMessage())
.build()).collect(Collectors.toList()));
}
}
34、版本号的声明
<properties>
<java.version>1.8</java.version>
<!-- <mybatis.starter.version>2.3.1</mybatis.starter.version>-->
<druid.starter.version>1.2.6</druid.starter.version>
<mybatisplus.starter.version>3.5.2</mybatisplus.starter.version>
</properties>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.starter.version}</version>
</dependency>
35、扫描其他包的时候,就是yml那边引用了,
(1)注解方式注入方式一:主配置类那里要写公共的东西
(2)方式二自动装配:
36、建立数据库的参数
37、数据库的left join和inner join的区别
- 返回结果:INNER JOIN只返回两个表中联结字段相等的行。而LEFT JOIN会返回包括左表中的所有记录和右表中联结字段相等的记录。
- 数量:INNER JOIN的数量小于等于左表和右表中的记录数量。而LEFT JOIN的数量以左表中的记录数量相同。
- 记录属性:INNER JOIN不足的记录属性会被直接舍弃。而LEFT JOIN不足的记录属性用NULL填充。
- 查询效率:INNER JOIN在一般情况下查询效率明显高于LEFT JOIN,因为它只返回两个表中的共同记录,减少了结果集的大小。而LEFT JOIN需要返回左表的全部记录,可能会导致结果集较大。
- 使用场景:INNER JOIN适用于查找两个表中满足连接条件的共同记录,并且通常用于关联查询。而LEFT JOIN适用于需保留左表中的全部记录,而右表中的匹配记录不是必需的情况,通常用于包含空值或未关联数据的查询。
55、初始的pom
<?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 https://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.7.14</version>
<relativePath/>
</parent>
<groupId>com.smart.community</groupId>
<artifactId>smart-community-master</artifactId>
<version>1.0.0</version>
<name>smart-community-master</name>
<description>springboot基础</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
56、完整springboot框架流程
(1)项目搭建
(2)修改主父pom文件parent版本及jdk版本(导包导依赖)
<?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 https://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.7.14</version>
<relativePath/>
</parent>
<groupId>com.smart.community</groupId>
<artifactId>smart-community-master</artifactId>
<version>1.0.0</version>
<name>smart-community-master</name>
<description>springboot基础</description>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<mybatis.starter.version>2.3.1</mybatis.starter.version>
<mybatisplus.starter.version>3.5.2</mybatisplus.starter.version>
<druid.starter.version>1.2.6</druid.starter.version>
<hutool.version>5.8.24</hutool.version>
<springfox.starter.version>3.0.0</springfox.starter.version>
<knife4j.starter.version>3.0.3</knife4j.starter.version>
<pagehelper.starter.version>1.4.6</pagehelper.starter.version>
</properties>
<modules>
<module>smart-community-admin</module>
<module>smart-community-common</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.starter.version}</version>
</dependency>
<!-- mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.starter.version}</version>
</dependency>
<!-- 数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version> ${druid.starter.version}</version>
</dependency>
<!-- hutool工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- swagger3用-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.starter.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.starter.version}</version>
</dependency>
<!-- 自定义公共starter-->
<!-- 数据库子项目-->
<dependency>
<groupId>com.smart.community.common.db</groupId>
<artifactId>db-community-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 基础子项目-->
<dependency>
<groupId>com.smart.community.common.base</groupId>
<artifactId>base-community-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- swagger子项目-->
<dependency>
<groupId>com.smart.community.common.swagger</groupId>
<artifactId>swagger-community-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- pagehelper分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.starter.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--hutool核心类型-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
(3)创建子项目
1)模块一:smart-community-common子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.master</groupId>
<artifactId>smart-community-master</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.common</groupId>
<artifactId>smart-community-common</artifactId>
<version>1.0.0</version>
<name>smart-community-common</name>
<description>springboot练习</description>
<properties>
<java.version>1.8</java.version>
</properties>
<packaging>pom</packaging>
<modules>
<module>base-common-boot-starter</module>
<module>db-common-boot-starter</module>
<module>swagger-common-boot-starter</module>
</modules>
</project>
2)db-common-boot-starter子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.community.common</groupId>
<artifactId>smart-community-common</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.common.db</groupId>
<artifactId>db-common-boot-starter</artifactId>
<version>1.0.0</version>
<name>db-common-boot-starter</name>
<description>springboot练习</description>
<dependencies>
<!-- 数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- 驱动:内置包含了 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
3)base-common-boot-starter子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.community.common</groupId>
<artifactId>smart-community-common</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.common.base</groupId>
<artifactId>base-community-boot-starter</artifactId>
<version>1.0.0</version>
<name>base-community-boot-starter</name>
<description>springboot基础</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- pagehelper分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
</dependencies>
</project>
4)swagger-common-boot-starter子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.community.common</groupId>
<artifactId>smart-community-common</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.common.swagger</groupId>
<artifactId>swagger-community-boot-starter</artifactId>
<version>1.0.0</version>
<name>swagger-community-boot-starter</name>
<description>springboot基础</description>
<dependencies>
<!-- swagger3用-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
5)模块二:smart-community-admin子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.master</groupId>
<artifactId>smart-community-master</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.admin</groupId>
<artifactId>smart-community-admin</artifactId>
<version>1.0.0</version>
<name>smart-community-admin</name>
<description>springboot练习</description>
<properties>
<java.version>1.8</java.version>
</properties>
<packaging>pom</packaging>
<modules>
<module>admin-user-center</module>
</modules>
</project>
6)admin-user-center子项目
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.community.admin</groupId>
<artifactId>smart-community-admin</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.smart.community.admin.user</groupId>
<artifactId>admin-user-center</artifactId>
<version>1.0.0</version>
<name>admin-user-center</name>
<description>springboot基础</description>
<properties>
<java.version>1.8</java.version>
</properties>
<!-- 导入2个自定义的工具包-->
<!-- 数据库子项目-->
<dependencies>
<dependency>
<groupId>com.smart.community.common.db</groupId>
<artifactId>db-community-boot-starter</artifactId>
</dependency>
<!-- 基础子项目-->
<dependency>
<groupId>com.smart.community.common.base</groupId>
<artifactId>base-community-boot-starter</artifactId>
</dependency>
<!-- swagger子项目-->
<dependency>
<groupId>com.smart.community.common.swagger</groupId>
<artifactId>swagger-community-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
(4)base-common-boot-starter配置共有类
1)GlobalExceptionHandler全局异常类
package com.smart.community.common.base.handler;
import cn.hutool.core.util.ReflectUtil;
import com.smart.community.common.base.dto.ArgsErrorInfo;
import com.smart.community.common.base.ex.BaseException;
import com.smart.community.common.base.result.ResponseResult;
import com.smart.community.common.base.result.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.List;
import java.util.stream.Collectors;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseResult<Object> handlerException(Exception ex) {
ex.printStackTrace();
log.error("错误的信息:{}", ex.getMessage());
return ResponseResult.error();
}
/**
* 处理BaseException类型的异常
* @param ex
* @return
*/
@ExceptionHandler(BaseException.class)
public ResponseResult<Object> handlerBaseException(BaseException ex) {
ex.printStackTrace();
// 返回一个ResponseResult对象,
// 该对象的状态是“错误”。
// 它使用异常的getResultStatus()方法返回的状态作为其错误状态
return ResponseResult.error(ex.getResultStatus());
}
/**
* 单参数校验
* 属性名 错误信息
*
* @param ex
* @return
*/
//todo 作用?
@ExceptionHandler(ConstraintViolationException.class)
public ResponseResult<List<ArgsErrorInfo>> handlerException(ConstraintViolationException ex) {
ex.printStackTrace();
return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getConstraintViolations().stream()
.map(violation -> {
List<Path.Node> nodeList = (List<Path.Node>) ReflectUtil.getFieldValue(violation.getPropertyPath(), "nodeList");
return ArgsErrorInfo.builder().fileName(nodeList.get(nodeList.size() - 1).getName())
.errorMessage(violation.getMessage())
.build();
}
).collect(Collectors.toList()));
}
/**
* 对象校验
*
* @param ex
* @return
*/
//todo 作用?
@ExceptionHandler(BindException.class)
public ResponseResult<List<ArgsErrorInfo>> handlerException(BindException ex) {
ex.printStackTrace();
return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getBindingResult().getFieldErrors().stream()
.map(fieldError -> ArgsErrorInfo.builder()
.fileName(fieldError.getField()).errorMessage(fieldError.getDefaultMessage())
.build()).collect(Collectors.toList()));
}
}
2)ArgsErrorInfo获取异常信息类
package com.smart.community.common.base.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 获取异常信息类
* @author liuhuitang
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ArgsErrorInfo {
private String errorMessage;
private String fileName;
}
3)BaseException、ControllerException、ServiceException基本异常类
package com.smart.community.common.base.ex;
import com.smart.community.common.base.result.ResultStatus;
import lombok.Getter;
@Getter
//getter是因为要返回给前端resultStatus结果集对象,所以要给个getter
public class BaseException extends RuntimeException{
private final ResultStatus resultStatus;
public BaseException(ResultStatus resultStatus) {
//为了让他在控制台打印错误信息
super(resultStatus.getMsg());
this.resultStatus = resultStatus;
}
}
package com.smart.community.common.base.ex;
import com.smart.community.common.base.result.ResultStatus;
/**
* @author liuhuitang
*/
public class ControllerException extends BaseException{
public ControllerException(ResultStatus resultStatus) {
super(resultStatus);
}
}
package com.smart.community.common.base.ex;
import com.smart.community.common.base.result.ResultStatus;
public class ServiceException extends BaseException{
public ServiceException(ResultStatus resultStatus) {
super(resultStatus);
}
}
4)ResponseResult、ResultStatus结果集
package com.smart.community.common.base.result;
import lombok.Data;
/**
* 状态的跟信息
*
* @param <T>
*/
@Data
public class ResponseResult<T> {
private int code;
private String msg;
private T data;
public static <T> ResponseResult<T> success(T data) {
return success(ResultStatus.SUCCESS,data);
}
public static <T> ResponseResult<T> success(ResultStatus resultStatus, T data) {
return common(resultStatus, data);
}
public static <T> ResponseResult<T> error(ResultStatus resultStatus) {
return common(resultStatus, null);
}
// 传递错误信息到前端
public static <T> ResponseResult<T> error(ResultStatus resultStatus,T errorData){
return common(resultStatus, errorData);
}
public static <T> ResponseResult<T> error() {
return error(ResultStatus.SYS_ERROR);
}
private static <T> ResponseResult<T> common(ResultStatus resultStatus, T data) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(resultStatus.getCode());
result.setMsg(resultStatus.getMsg());
result.setData(data);
return result;
}
}
package com.smart.community.common.base.result;
import lombok.Getter;
@Getter
@SuppressWarnings("all")
public enum ResultStatus {
SUCCESS(20000, "成功"),
SYS_ERROR(40000, "系统错误"),
USER_PARAM_ERROR(40001, "用户名格式不正确"),
USER_NO_EXIST(40002, "用户名不存在"),
USER_PASSWORD_ERROR(40003, "密码错误"),
USER_LOGIN_ERROR (40004, "用户名或者密码错误"),
USER_ACCOUNT_ERROR (40005, "账号被禁用"),
PICTURE_UPLOAD_ERROR (40006, "图片上传异常"),
PICTURE_DOWNLOAD_ERROR (40007, "图片下载异常"),
ARGS_VALID_ERROR (40008, "参数校验失败");
final int code;
final String msg;
ResultStatus(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
5)CommonBeanUtils属性转换工具类
package com.smart.community.common.base.utils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class CommonBeanUtils extends BeanUtils {
/**
* 将A对象的属性赋值给B对象
* @param source
* @param targetSupplier
* @return
* @param <S>
* @param <T>
*/
public static <S,T> T convertTo(S source, Supplier<T> targetSupplier){
// 这里的ObjectUtils.isEmpty(targetSupplier)是为了方式下面的get出现空指针异常
if (ObjectUtils.isEmpty(source) || ObjectUtils.isEmpty(targetSupplier)){
return null;
}
T t = targetSupplier.get();
copyProperties(source,t);
return t;
}
/**
* 调用convertTo(s, targetSupplier)方法来生成一个新的T类型对象。
* 然后使用collect(Collectors.toList())将所有这些新生成的T类型对象收集到一个新的列表中
* @param sources
* @param targetSupplier
* @return
* @param <S>
* @param <T>
*/
public static <S,T> List<T> convertListTo(List<S> sources,Supplier<T> targetSupplier){
if (ObjectUtils.isEmpty(sources) || ObjectUtils.isEmpty(targetSupplier)){
return null;
}
//把每个对象赋值属性然后用collect转为集合
return sources.stream().map(s -> convertTo(s,targetSupplier)).collect(Collectors.toList());
}
/**
* 处理分页查询时,当你想要将一个分页查询的结果转换为另一种类型的分页查询结果时。
* 例如,你可能有一个基于User的分页查询,并且想要将其转换为基于Employee的分页查询
* @param source
* @param target
* @param targetSupplier
* @return
* @param <S>
* @param <T>
*/
// public static <S,T> PageInfo<T> convertPageInfo(PageInfo<S> source,PageInfo<T> target,Supplier<T> targetSupplier){
// //属性复制
// copyProperties(source,target);
// //将source对象的列表转换为target对象的列表。
// // source.getList()返回source对象的列表,
// // 而targetSupplier是一个函数式接口,用于生成新的目标对象实例。
// target.setList(convertListTo(source.getList(),targetSupplier));
// return target;
// }
}
6)ValidationConfig参数校验配置类
package com.smart.community.common.base.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
/**
* 参数校验配置类
* @author liuhuitang
*/
@Configuration
public class ValidationConfig {
@Bean
public Validator validator(){
return Validation
.byProvider(HibernateValidator.class)
.configure()
// 快速校验
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}
(5)db-common-boot-starter配置共有类
1)MybatisPlusConfiguration分页配置类
package com.smart.community.common.db.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatisplus配置分页
*/
@Configuration
//注册所有的mapper接口
@MapperScan("com.smart.community.**.mapper")
//定义必须要有这个类
@ConditionalOnClass(MybatisPlusInterceptor.class)
public class MybatisPlusConfiguration {
/**
* 乐观锁
* @param paginationInnerInterceptor
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(PaginationInnerInterceptor paginationInnerInterceptor){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//用于处理分页相关的逻辑。
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
//用于乐观锁插件,通常用于处理版本控制的数据库操作。
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//用于防止全表扫描和删除插件,它可以防止恶意用户的攻击,如全表扫描或大量删除操作
mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
/**
* 分页插件注册
* @return
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor(){
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
//设置分页拦截器的溢出属性为true。
// 当查询的数据量超过每页的最大限制时,会抛出一个异常
paginationInnerInterceptor.setOverflow(true);
//设置分页拦截器的最大限制为500,每页最多返回500条数据。
paginationInnerInterceptor.setMaxLimit(500L);
return paginationInnerInterceptor;
}
}
2)application-db.yml 公共连接池数据
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 最大连接池数量
max-active: 20
# 初始化连接池的数量
initial-size: 5
# 最小连接池 数量
min-idle: 2
# 这里建议配置为TRUE,防止取到的连接不可用
test-on-borrow: true
test-on-return: false
# 验证连接有效与否的SQL,不同的数据配置不同
validation-query: select
#通过别名的方式配置扩展插件,常用的插件有:
#监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
filters: "stat,slf4j,wall"
# 配置获取连接等待超时的时间 单位毫秒
max-wait: 6000
#配置监控页
stat-view-servlet:
enabled: true
reset-enable: false
login-username: admin
login-password: admin
web-stat-filter:
enabled: true
url-pattern: /druid/*
exclusions: '*.js,*.jpg,*.png,*.gif,*.css,*.ico,/druid/*'
filter:
stat:
log-slow-sql: true
enabled: true
slow-sql-millis: 1000
(6)swagger-common-boot-starter配置共有类
1)SwaggerConfig :swagger工具类
package com.smart.community.common.swagger.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.annotation.Resource;
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Resource
private SwaggerProperties swaggerProperties;
@Bean
public Docket docket(ApiInfo apiInfo){
return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo)
.groupName(swaggerProperties.getGroupName())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(PathSelectors.any())
.build();
}
@Bean
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.version(swaggerProperties.getVersion())
.contact(new Contact(swaggerProperties.getName(), swaggerProperties.getUrl(), swaggerProperties.getEmail()))
.build();
}
}
2)SwaggerProperties swagger参数类
package com.smart.community.common.swagger.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author liuhuitang
*/
@Component
@ConfigurationProperties("swagger")
@Data
public class SwaggerProperties {
private String title;
private String basePackage;
private String groupName;
private String description;
private String name;
private String url;
private String email;
private String version;
}
3)application-swagger.yml 配置swagger
spring:
# swagger使用
mvc:
# 配置Spring MVC如何匹配URL路径
path-match:
# 基于Ant风格的路径模式匹配
matching-strategy: ant_path_matcher
(7)admin-user-center主类(整合)
1)主类的扫描包范围重写(多)
2)自动注入
(8)admin-user-center主类配置
1)application.yml(主配置)
server:
port: 8081
spring:
profiles:
active: "db,dev,swagger"
2)application-dev.yml(代码环境)
spring:
datasource:
druid:
url: "jdbc:mysql://localhost:3306/smart_community?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai"
username: "root"
password: "root"
3)application-prod.yml(生成环境)
spring:
datasource:
druid:
url: ""
username: ""
password: ""
4)UserCenterApplication主配置类
package com.smart.community.admin.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author liuhuitang
*/
@SpringBootApplication(scanBasePackages = "com.smart.community")
public class UserCenterApplication {
public static void main(String[] args) {
SpringApplication.run(UserCenterApplication.class,args);
}
}
56、左连接和内连接
(1)左连接查左表所有数据,没数据的就为null(可以查出脏数据)