• 创建SpringBoot项目


    学习sb

    目录

    一、创建项目

    1.项目启动报错:

    2.方式一:

    3.方式二

    二、修改properties为yml配置

    三、application.yml与bootstrap.yml的区别

    四、SpringBoot+mybatis-plus

    1.pom文件

    2.application.yml文件配置

    3.application-dev.yml配置

    4.mybatis-plus自动生成

    5.分页插件

    6.自动填充类

    五、SpringBoot+Swagger

    1.pom文件

    2.swagger配置类

    总结




    一、创建项目

     

    修改使用版本

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.1.7.RELEASE</version>
    5. <relativePath/><!--lookupparentfromrepository-->
    6. </parent>

    二、启动项目

    1.项目启动报错:

     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )

      '  |____| .__|_| |_|_| |_\__, | / / / /

     =========|_|==============|___/=/_/_/_/

     :: Spring Boot ::                (v2.7.3)

    2022-09-02 14:30:34.633  INFO 21044 --- [           main] c.l.demo.SpringLoggingDemoApplication    : Starting SpringLoggingDemoApplication using Java 1.8.0_192 on LAPTOP-EPEBDNL1 with PID 21044 (D:\IDEAWorkSpace\2022_process\spring-logging-demo\target\classes started by xhm in D:\IDEAWorkSpace\2022_process)

    2022-09-02 14:30:34.635  INFO 21044 --- [           main] c.l.demo.SpringLoggingDemoApplication    : No active profile set, falling back to 1 default profile: "default"

    2022-09-02 14:30:34.985  INFO 21044 --- [           main] c.l.demo.SpringLoggingDemoApplication    : Started SpringLoggingDemoApplication in 0.6 seconds (JVM running for 1.482)

    Disconnected from the target VM, address: '127.0.0.1:63428', transport: 'socket'

    2.方式一:

    将生成的spring-boot-starter修改为spring-boot-starter-web

    org.springframework.boot

    spring-boot-starter

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

    3.方式二

    修改依赖之后依然不生效,重新配置maven,sync项目,重新启动成功

    二、修改properties为yml配置

    删除原有properties,创建yml文件

    application.yml与bootstrap.yml的区别

    1. bootstrap.yml 用来程序引导时执行,应用于更加早期配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
    2. application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等
    3. 若application.yml 和 bootstrap.yml 在同一目录下:bootstrap.yml 先加载,application.yml 后加载
    4. bootstrap.yml 用于application上下文的引导阶段。bootstrap.yml 由父Spring ApplicationContext加载
    5. 但是若 application.yml 与 bootstrap 存在相同的配置项,还是会覆盖 bootstrap,而 application.yml 里面的内容可以动态替换。
    6. bootstrap.yml典型的应用场景
    7. 当使用 Spring Cloud Config Server (或者Spring Cloud Alibaba Nacos)配置中心时,这时必须将 spring.application.name 和 spring.cloud.config.server.git.uri(或者spring.cloud.nacos.config)配置在 bootstrap.yml 配置文件中,添加连接到配置中心的配置属性来加载外部配置中心的配置信息
      1. 一些固定不变的属性
      2. 一些加密/解密的场景

    ————————————————
    版权声明:本文为CSDN博主「qq_三哥啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_27579471/article/details/123440601
     

    四、SpringBoot+mybatis-plus

    1.pom文件

    1. <dependency>
    2. <groupId>mysqlgroupId>
    3. <artifactId>mysql-connector-javaartifactId>
    4. <version>8.0.28version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.baomidougroupId>
    8. <artifactId>mybatis-plus-boot-starterartifactId>
    9. <version>3.3.1version>
    10. dependency>
    11. <dependency>
    12. <groupId>com.baomidougroupId>
    13. <artifactId>mybatis-plus-generatorartifactId>
    14. <version>3.3.1version>
    15. dependency>
    16. <dependency>
    17. <groupId>com.alibabagroupId>
    18. <artifactId>druid-spring-boot-starterartifactId>
    19. <version>1.1.10version>
    20. dependency>
    21. <dependency>
    22. <groupId>org.apache.velocitygroupId>
    23. <artifactId>velocity-engine-coreartifactId>
    24. <version>2.3version>
    25. dependency>

    2.application.yml文件配置

    1. #application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。如果搭配 spring-cloud-config 使用, application.yml里面定义的文件可以实现动态替换。
    2. spring:
    3. profiles:
    4. active: dev
    5. # mybatis- plus配置
    6. mybatis-plus:
    7. # xml扫描,多个目录用逗号或者分号隔开隔开
    8. mapper-locations: classpath:mapper/*.xml
    9. # 以下配置均有默认值,可以不设置
    10. global-config:
    11. db-config:
    12. #主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
    13. id-type: auto
    14. configuration:
    15. # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    16. map-underscore-to-camel-case: true
    17. # 返回map时true:当查询数据为空时字段返回为null,false:不加这个查询数据为空时,字段将被隐藏
    18. call-setters-on-nulls: true
    19. # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    20. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    3.application-dev.yml配置

    1. spring:
    2. datasource:
    3. druid:
    4. url: jdbc:mysql://127.0.0.1:3306/db_ceshi?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
    5. # url: jdbc:mysql://192.168.0.136:3306/csg_cloud_system?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
    6. username: root
    7. password: 123456
    8. driver-class-name: com.mysql.cj.jdbc.Driver
    9. initial-size: 10
    10. max-active: 100
    11. min-idle: 10
    12. max-wait: 60000
    13. pool-prepared-statements: true
    14. max-pool-prepared-statement-per-connection-size: 20
    15. time-between-eviction-runs-millis: 60000
    16. min-evictable-idle-time-millis: 300000
    17. test-while-idle: true
    18. test-on-borrow: false
    19. test-on-return: false
    20. stat-view-servlet:
    21. enabled: true
    22. url-pattern: /druid/*
    23. filter:
    24. stat:
    25. log-slow-sql: true
    26. slow-sql-millis: 1000
    27. merge-sql: false
    28. wall:
    29. config:
    30. multi-statement-allow: true

    4.mybatis-plus自动生成

    1. package com.logging.demo.configuration;
    2. import com.baomidou.mybatisplus.core.toolkit.StringPool;
    3. import com.baomidou.mybatisplus.generator.AutoGenerator;
    4. import com.baomidou.mybatisplus.generator.InjectionConfig;
    5. import com.baomidou.mybatisplus.generator.config.*;
    6. import com.baomidou.mybatisplus.generator.config.po.TableInfo;
    7. import com.baomidou.mybatisplus.generator.config.rules.DateType;
    8. import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    9. import org.springframework.beans.factory.annotation.Value;
    10. import org.springframework.stereotype.Component;
    11. import java.util.ArrayList;
    12. import java.util.List;
    13. /**
    14. * @author :Sur chemin
    15. * @date : 2022/9/2
    16. */
    17. @Component
    18. public class CodeGenerator {
    19. String author;
    20. String moduleName;
    21. String parentPackage;
    22. String tableNames;
    23. String tablePrefix;
    24. @Value("${spring.datasource.druid.url}")
    25. String url;
    26. @Value("${spring.datasource.druid.driver-class-name}")
    27. String driverName;
    28. @Value("${spring.datasource.druid.username}")
    29. String username;
    30. @Value("${spring.datasource.druid.password}")
    31. String password;
    32. // entiry 的父类
    33. private final String superEntity = "com.logging.demo.entity.SuperEntity";
    34. public void execute(){
    35. // 代码生成器
    36. AutoGenerator mpg = new AutoGenerator();
    37. // 全局配置
    38. GlobalConfig gc = new GlobalConfig();
    39. String projectPath = System.getProperty("user.dir");
    40. gc.setOutputDir(projectPath + "/src/main/java");
    41. gc.setAuthor(author);
    42. gc.setOpen(false);
    43. gc.setSwagger2(true);
    44. gc.setDateType(DateType.ONLY_DATE);
    45. mpg.setGlobalConfig(gc);
    46. // 数据源配置
    47. DataSourceConfig dc = new DataSourceConfig();
    48. dc.setUrl(url);
    49. dc.setDriverName(driverName);
    50. dc.setPassword(password);
    51. dc.setUsername(username);
    52. mpg.setDataSource(dc);
    53. // 包配置
    54. PackageConfig pc = new PackageConfig();
    55. pc.setModuleName(moduleName);
    56. pc.setParent(parentPackage);
    57. mpg.setPackageInfo(pc);
    58. // 自定义配置
    59. // 添加自定义配置 使得数据表映射已存在的情况下 更新entity
    60. InjectionConfig cfg = new InjectionConfig() {
    61. @Override
    62. public void initMap() {
    63. // to do nothing
    64. }
    65. };
    66. // 如果模板引擎是freemarker
    67. // String templatePath = "templates/mapper.xml.ftl";
    68. // 如果模板引擎是velocity
    69. String templatePath = "/templates/mapper.xml.vm";
    70. // 自定义输出配置
    71. List focList = new ArrayList<>();
    72. // 自定义配置会被优先输出
    73. focList.add(new FileOutConfig(templatePath) {
    74. @Override
    75. public String outputFile(TableInfo tableInfo) {
    76. // 自定义输出文件名,如果Entity设置了前后缀、此处主要xml的名称会跟着发生变化
    77. String s = projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
    78. + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
    79. return s;
    80. }
    81. });
    82. /*ic.setFileCreate(new IFileCreate() {
    83. @Override
    84. public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
    85. // 判断自定义文件夹是否需要创建
    86. checkDir("调用默认方法创建的目录,自定义目录用");
    87. if (fileType == FileType.MAPPER) {
    88. // 已经生成 mapper文件判断存在,不想重新生成返回 false
    89. return !new File(filePath).exists();
    90. }
    91. // 允许生成模板文件
    92. return true;
    93. }
    94. });*/
    95. /*cfg.setFileCreate((configBuilder, fileType, filePath) -> {
    96. //如果是Entity则直接返回true表示写文件
    97. if (fileType == FileType.ENTITY) {
    98. return true;
    99. }
    100. //否则先判断文件是否存在
    101. File file = new File(filePath);
    102. boolean exist = file.exists();
    103. if (!exist) {
    104. file.getParentFile().mkdirs();
    105. }
    106. //文件不存在或者全局配置的fileOverride为true才写文件
    107. return !exist || configBuilder.getGlobalConfig().isFileOverride();
    108. });*/
    109. cfg.setFileOutConfigList(focList);
    110. mpg.setCfg(cfg);
    111. // 配置模板
    112. TemplateConfig templateConfig = new TemplateConfig();
    113. // 配置自定义输出模板
    114. // 指定自定义模板路径,主要不用带上.ftl/.vm,会根据使用的模板引擎自动识别
    115. // templateConfig.setEntity("templates/entity2.java");
    116. // templateConfig.setService();
    117. // templateConfig.setController();
    118. templateConfig.setXml(null);
    119. mpg.setTemplate(templateConfig);
    120. // 策略配置
    121. StrategyConfig strategy = new StrategyConfig();
    122. strategy.setNaming(NamingStrategy.underline_to_camel);
    123. strategy.setColumnNaming(NamingStrategy.underline_to_camel);
    124. strategy.setSuperEntityClass(superEntity);
    125. strategy.setEntityLombokModel(true);
    126. strategy.setRestControllerStyle(true);
    127. // 公共父类
    128. // strategy.setSuperControllerClass(superController);
    129. // 写于父类中的公共字段
    130. strategy.setSuperEntityColumns("id", "ID");
    131. strategy.setInclude(tableNames.split(","));
    132. strategy.setControllerMappingHyphenStyle(true);
    133. strategy.setTablePrefix(tablePrefix);
    134. mpg.setStrategy(strategy);
    135. // Velocity是默认模板引擎,不需要配置
    136. // mpg.setTemplateEngine(new FreemarkerTemplateEngine());
    137. mpg.execute();
    138. }
    139. public CodeGenerator setAuthor(String author) {
    140. this.author = author;
    141. return this;
    142. }
    143. public CodeGenerator setModuleName(String moduleName) {
    144. this.moduleName = moduleName;
    145. return this;
    146. }
    147. public CodeGenerator setParentPackage(String parentPackage) {
    148. this.parentPackage = parentPackage;
    149. return this;
    150. }
    151. public CodeGenerator setTableNames(String tableNames) {
    152. this.tableNames = tableNames;
    153. return this;
    154. }
    155. public CodeGenerator setTablePrefix(String tablePrefix) {
    156. this.tablePrefix = tablePrefix;
    157. return this;
    158. }
    159. }

    测试类

    1. package com.logging.demo;
    2. import com.logging.demo.configuration.CodeGenerator;
    3. import org.junit.Test;
    4. import org.junit.runner.RunWith;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.boot.test.context.SpringBootTest;
    7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    8. import java.util.Arrays;
    9. import java.util.List;
    10. /**
    11. * @author :Sur chemin
    12. * @date : 2022/9/2
    13. */
    14. @RunWith(SpringJUnit4ClassRunner.class)
    15. @SpringBootTest(classes = SpringLoggingDemoApplication.class)
    16. public class GenertorTest {
    17. @Autowired
    18. private CodeGenerator codeGenerator;
    19. @Test
    20. public void test() {
    21. List asList = Arrays.asList(new String[]{"pro_change_order"});
    22. asList.forEach(e -> {
    23. codeGenerator.setAuthor("Sur chemin");
    24. codeGenerator.setModuleName("");
    25. codeGenerator.setParentPackage("com.logging.demo.project");
    26. codeGenerator.setTableNames(e);
    27. codeGenerator.setTablePrefix("pro_");
    28. codeGenerator.execute();
    29. });
    30. }
    31. }

    5.分页插件

    1. package com.logging.demo.configuration;
    2. import com.baomidou.mybatisplus.core.parser.ISqlParser;
    3. import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser;
    4. import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    5. import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
    6. import com.google.common.collect.Lists;
    7. import org.mybatis.spring.annotation.MapperScan;
    8. import org.springframework.context.annotation.Bean;
    9. import org.springframework.context.annotation.Configuration;
    10. import org.springframework.context.annotation.Primary;
    11. import org.springframework.core.annotation.Order;
    12. import java.util.List;
    13. /**
    14. * @author :Sur chemin
    15. * @date : 2022/9/2
    16. */
    17. @Configuration
    18. //@MapperScan(basePackageClasses = Mc.class)
    19. @MapperScan("com.logging.demo")
    20. public class MybatisPlusConfig {
    21. /**
    22. * 分页插件
    23. * @return
    24. */
    25. @Bean
    26. @Order(2)
    27. public PaginationInterceptor paginationInterceptor(){
    28. PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    29. List sqlParserList = Lists.newArrayList();
    30. // 攻击 SQL阻断解析器、加入解析链
    31. sqlParserList.add(new BlockAttackSqlParser());
    32. paginationInterceptor.setSqlParserList(sqlParserList);
    33. // 单页限制500条,小于0 如-1不受限制
    34. paginationInterceptor.setLimit(-1);
    35. paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
    36. // 设置方言
    37. paginationInterceptor.setDialectType("sqlite");
    38. return paginationInterceptor;
    39. }
    40. @Bean
    41. @Primary
    42. public CommonMetaObjectHandler commonMetaObjectHandler(){
    43. return new CommonMetaObjectHandler();
    44. }
    45. }

    6.自动填充类

    1. package com.logging.demo.configuration;
    2. import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    3. import org.apache.ibatis.reflection.MetaObject;
    4. import java.util.Date;
    5. /**
    6. * 通用填充类 适用于mybatis plus
    7. * @author :Sur chemin
    8. * @date : 2022/9/2
    9. */
    10. public class CommonMetaObjectHandler implements MetaObjectHandler {
    11. /**
    12. * 创建人
    13. */
    14. private final String createBy = "createBy";
    15. /**
    16. * 更新人
    17. */
    18. private final String updateBy = "updateBy";
    19. /**
    20. * 创建时间
    21. */
    22. private final String createDate = "createDate";
    23. /**
    24. * 更新时间
    25. */
    26. private final String updateDate = "updateDate";
    27. private final String delteFlag = "delteFlag";
    28. /**
    29. * 3.0.x新版自动填充api 判断实体类字段是否为null
    30. * 为null,才执行自动填充
    31. * 所以改回旧版过时api
    32. * @param metaObject
    33. */
    34. @Override
    35. public void insertFill(MetaObject metaObject) {
    36. setInsertFieldValByName(delteFlag, 0, metaObject);
    37. setInsertFieldValByName(createDate,new Date(System.currentTimeMillis()), metaObject);
    38. // 其他需要自动填充的字段在这里补充
    39. }
    40. @Override
    41. public void updateFill(MetaObject metaObject) {
    42. setInsertFieldValByName(delteFlag, 0, metaObject);
    43. setInsertFieldValByName(createDate,new Date(System.currentTimeMillis()), metaObject);
    44. }
    45. }

    五、SpringBoot+Swagger

    1.pom文件

    1. <dependency>
    2. <groupId>io.springfoxgroupId>
    3. <artifactId>springfox-swagger2artifactId>
    4. <version>2.9.2version>
    5. dependency>
    6. <dependency>
    7. <groupId>io.springfoxgroupId>
    8. <artifactId>springfox-swagger-uiartifactId>
    9. <version>2.9.2version>
    10. dependency>

    2.swagger配置类

    1. package com.logging.demo.configuration;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import springfox.documentation.builders.ApiInfoBuilder;
    5. import springfox.documentation.builders.PathSelectors;
    6. import springfox.documentation.builders.RequestHandlerSelectors;
    7. import springfox.documentation.service.ApiInfo;
    8. import springfox.documentation.service.ApiKey;
    9. import springfox.documentation.service.AuthorizationScope;
    10. import springfox.documentation.service.SecurityReference;
    11. import springfox.documentation.spi.DocumentationType;
    12. import springfox.documentation.spi.service.contexts.SecurityContext;
    13. import springfox.documentation.spring.web.plugins.Docket;
    14. import springfox.documentation.swagger2.annotations.EnableSwagger2;
    15. import java.util.ArrayList;
    16. import java.util.List;
    17. @Configuration
    18. @EnableSwagger2
    19. public class Swagger2Config {
    20. private Boolean enabled = true;
    21. @Bean
    22. public Docket createRestApi(){
    23. return new Docket(DocumentationType.SWAGGER_2)
    24. .enable(enabled)
    25. .apiInfo(apiInfo())
    26. .select()
    27. .apis(RequestHandlerSelectors.basePackage("com.logging.demo.controller"))
    28. .paths(PathSelectors.any())
    29. .build();
    30. // .securitySchemes(securitySchemes())
    31. // .securityContexts(securityContexts());
    32. }
    33. private ApiInfo apiInfo() {
    34. return new ApiInfoBuilder()
    35. .title("管理模块")
    36. .description("管理模块")
    37. .contact("")
    38. .version("1.0")
    39. .build();
    40. }
    41. private List securitySchemes() {
    42. //设置请求头信息
    43. List result = new ArrayList<>();
    44. ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
    45. result.add(apiKey);
    46. return result;
    47. }
    48. private List securityContexts() {
    49. //设置需要登录认证的路径
    50. List result = new ArrayList<>();
    51. //result.add(getContextByPath("/brand/.*"));
    52. return result;
    53. }
    54. private SecurityContext getContextByPath(String pathRegex){
    55. return SecurityContext.builder()
    56. .securityReferences(defaultAuth())
    57. .forPaths(PathSelectors.regex(pathRegex))
    58. .build();
    59. }
    60. private List defaultAuth() {
    61. List result = new ArrayList<>();
    62. AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
    63. AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
    64. authorizationScopes[0] = authorizationScope;
    65. result.add(new SecurityReference("Authorization", authorizationScopes));
    66. return result;
    67. }
    68. }

    controller测试类

    1. package com.logging.demo.controller;
    2. import io.swagger.annotations.Api;
    3. import org.springframework.web.bind.annotation.RequestMapping;
    4. import org.springframework.web.bind.annotation.RestController;
    5. /**
    6. *

    7. * 项目变更工单表 前端控制器
    8. *

    9. *
    10. * @author Sur chemin
    11. * @since 2022-09-02
    12. */
    13. @RestController
    14. @Api(tags = "test")
    15. @RequestMapping("/test")
    16. public class TestController {
    17. }

     测试,不显示controller,原因没有在测试类中写接口方法,GET/POST

    修改

    1. package com.logging.demo.controller;
    2. import io.swagger.annotations.Api;
    3. import io.swagger.annotations.ApiOperation;
    4. import org.springframework.web.bind.annotation.GetMapping;
    5. import org.springframework.web.bind.annotation.RequestMapping;
    6. import org.springframework.web.bind.annotation.RestController;
    7. /**
    8. *

    9. * 项目变更工单表 前端控制器
    10. *

    11. *
    12. * @author Sur chemin
    13. * @since 2022-09-02
    14. */
    15. @RestController
    16. @Api(tags = "test")
    17. @RequestMapping("/test")
    18. public class TestController {
    19. @ApiOperation(value = "查询")
    20. @GetMapping("/test")
    21. public String test(){
    22. return "1";
    23. }
    24. }

    六、 SpringBoot+logback

    七、SpringBoot+SpringSecurity

    学习参考文章连接:https://blog.csdn.net/LC_Liangchao/article/details/123425625

    Spring Security提供有若干个过滤器,它们能够拦截Servlet请求,并将这些请求转给认证和访问决策管理器处理,从而增强安全性。根据自己的需要,可以使用适当的过滤器来保护自己的应用程序

    1.认证

    2.授权

    1.pom依赖

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

    2.编写UserDetailsService的实现类

    AuthenticationManager进行权限认证(最终走自定义的UserDetailsService的实现类的loadUserByUsername接口根据用户名查询数据库验证用户是否存在)

    1. package com.logging.demo.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.logging.demo.auth.AdminUserDetails;
    4. import com.logging.demo.entity.SysUser;
    5. import com.logging.demo.mapper.SysUserMapper;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.security.core.userdetails.UserDetails;
    8. import org.springframework.security.core.userdetails.UserDetailsService;
    9. import org.springframework.security.core.userdetails.UsernameNotFoundException;
    10. import org.springframework.stereotype.Service;
    11. /**
    12. * @author :Sur chemin
    13. * @date : 2022/9/6
    14. */
    15. /**
    16. * 加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法
    17. */
    18. /**
    19. * 实际开发中会把5.1这一步查询数据来判断用户名密码是否正确,所以我们需要改变的地方是:写一个UserDetailsService的实现类,
    20. * 让DaoAuthenticationProvider去调用这个实现类。
    21. * 自定义userDetailsService的实现类;查询数据库
    22. */
    23. @Service("userDetailsService")
    24. public class UserDetailsServiceImpl implements UserDetailsService{
    25. @Autowired
    26. private SysUserMapper sysUserMapper;
    27. /**
    28. * 登录请求 :1.查询根据用户名数据库用户是否存在
    29. *
    30. * @param username
    31. * @return
    32. * @throws UsernameNotFoundException
    33. */
    34. @Override
    35. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    36. // 校验用户名和密码
    37. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    38. queryWrapper.eq(SysUser::getUserName, username);
    39. SysUser sysUser = sysUserMapper.selectOne(queryWrapper);
    40. if(sysUser==null){
    41. throw new RuntimeException("用户名或密码不正确");
    42. }
    43. // TODO 2. 存储用户信息进入SecurityContextHolder(包括权限信息)
    44. return new AdminUserDetails(sysUser);
    45. }
    46. }

    3.登录接口

    1. package com.logging.demo.controller;
    2. import com.logging.demo.common.CommonResult;
    3. import com.logging.demo.entity.vo.SysUserReqVO;
    4. import com.logging.demo.service.ISysUserService;
    5. import io.swagger.annotations.ApiOperation;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.*;
    8. import java.util.Map;
    9. /**
    10. *

    11. * 前端控制器
    12. *

    13. *
    14. * @author Sur chemin
    15. * @since 2022-09-06
    16. */
    17. @RestController
    18. @RequestMapping("/sys-user")
    19. public class SysUserController {
    20. @Autowired
    21. ISysUserService sysUserService;
    22. @ApiOperation("用户注册")
    23. @PostMapping("addUser")
    24. public CommonResult addUser(@RequestBody SysUserReqVO sysUserReqVO){
    25. return sysUserService.addUser(sysUserReqVO);
    26. }
    27. @ApiOperation("用户登录")
    28. @PostMapping("login")
    29. public Map login(@RequestParam String username,
    30. @RequestParam String password){
    31. return sysUserService.login(username, password);
    32. }
    33. /**
    34. * 根据手机号注册,手机号唯一
    35. * @param mobile
    36. * @param password
    37. * @return
    38. */
    39. @ApiOperation("修改/重置密码")
    40. @PostMapping("reset")
    41. public CommonResult reset(@RequestParam String mobile,
    42. @RequestParam(required = false) String password){
    43. return sysUserService.reset(mobile, password);
    44. }
    45. }

    4.定义SpringSecurity配置类

    我们一般使用springsecurity为我们提供的BCryptPasswordEncoder(内部会生成一个随机的盐,保证每次加密的结果都不一样)

    1. package com.logging.demo.auth;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.context.annotation.Configuration;
    6. import org.springframework.http.HttpMethod;
    7. import org.springframework.security.authentication.AuthenticationManager;
    8. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    9. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    11. import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    12. import org.springframework.security.config.http.SessionCreationPolicy;
    13. import org.springframework.security.core.userdetails.UserDetailsService;
    14. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    15. import org.springframework.security.crypto.password.PasswordEncoder;
    16. import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
    17. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    18. /**
    19. * @author :Sur chemin
    20. * @date : 2022/9/6
    21. */
    22. @Configuration
    23. public class SecurityConfig extends WebSecurityConfigurerAdapter {
    24. @Autowired(required = false)
    25. private DynamicSecurityService dynamicSecurityService;
    26. /**
    27. * 在SecurityConfig里面配置认证的配置
    28. *
    29. * @param httpSecurity
    30. * @throws Exception
    31. */
    32. @Autowired
    33. UserDetailsService userDetailsService;
    34. @Override
    35. protected void configure(HttpSecurity httpSecurity) throws Exception {
    36. /*// 所有请求必须认证通过
    37. httpSecurity
    38. .csrf().disable()
    39. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    40. .and()
    41. .authorizeRequests()
    42. //下边的路径放行
    43. .antMatchers("/sys-user/login","/v2/api-docs", "/swagger-resources/configuration/ui",
    44. "/swagger-resources","/swagger-resources/configuration/security",
    45. "/swagger-ui.html","/webjars/**","/sys-user/addUser").permitAll()
    46. .anyRequest().authenticated();*/
    47. // 不拦截任何请求
    48. /* httpSecurity
    49. .authorizeRequests().anyRequest().permitAll();*/
    50. /**
    51. * 配置 参考文章
    52. * https://blog.csdn.net/m0_56368068/article/details/125614281
    53. */
    54. ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
    55. //不需要保护的资源路径允许访问
    56. for (String url : ignoreUrlsConfig().getUrls()) {
    57. registry.antMatchers(url).permitAll();
    58. }
    59. //允许跨域请求的OPTIONS请求
    60. registry.antMatchers(HttpMethod.OPTIONS).permitAll();
    61. // 任何请求需要身份认证
    62. registry.and().authorizeRequests()//对url访问控制授权
    63. .antMatchers("/actuator", "/actuator/*").authenticated()//需要进行认证
    64. .antMatchers("/*").permitAll()// 在实际项目中经常需要放行所有静态资源,需要放行的url。
    65. .anyRequest().authenticated()//anyRequest匹配所有请求,全部内容都需要认证
    66. // 关闭跨站请求防护及不使用session
    67. .and()
    68. .csrf()
    69. .disable()
    70. .sessionManagement()
    71. .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    72. /**
    73. * 自定义权限拒绝处理类
    74. * spring Security 认证授权相关的异常进行统一的自定义处理
    75. */
    76. .and().exceptionHandling()
    77. .accessDeniedHandler(restfulAccessDeniedHandler()).authenticationEntryPoint(restAuthenticationEntryPoint())
    78. // 自定义权限拦截器JWT过滤器
    79. .and()
    80. //.addFilterBefore(verifyCodeFilter(), UsernamePasswordAuthenticationFilter.class)
    81. .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    82. //有动态权限配置时添加动态权限校验过滤器
    83. if (dynamicSecurityService != null) {
    84. registry.and().addFilterBefore(dynamicSecurityFilter(), FilterSecurityInterceptor.class);
    85. }
    86. }
    87. /**
    88. * 解决错误:ERROR:Encoded password does not look like BCrypt
    89. * 原因:密码格式不匹配导致的
    90. * @param auth
    91. * @throws Exception
    92. *
    93. *
    94. */
    95. @Override
    96. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    97. /**
    98. * ERROR:WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:451)
    99. * java.lang.StackOverflowError: null
    100. * 没有执行UserDetailsService的实现类的loadUserByUsername方法,执行上面的loadUserByUsername方法递归调用导致栈溢出
    101. */
    102. // auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    103. auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    104. }
    105. /**
    106. * 登录接口
    107. * 开放这个接口的白名单,让用户访问这个接口的时候不用登录也能访问。
    108. * 在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要SecurityConfig中配置把AuthenticationManager注入容器。
    109. * 认证成功的话要生成一个jwt,放入响应中返回,并且为了让用户回请求时能通过jwt识别出具体的是哪个用户,我们需要把用户信息存储入redis,用户id作为key
    110. *
    111. * @return
    112. * @throws Exception 把AuthenticationManager注入容器中
    113. */
    114. @Bean
    115. @Override
    116. public AuthenticationManager authenticationManagerBean() throws Exception {
    117. return super.authenticationManagerBean();
    118. }
    119. // 替换掉默认的密码加密器
    120. /**
    121. * 我们一般使用springsecurity为我们提供的BCryptPasswordEncoder(内部会生成一个随机的盐,保证每次加密的结果都不一样)。
    122. * 我们只需要使用吧BCryptPasswordEncoder对象注入spring容器中,springsecurity就会使用该passwordEncoder来进行密码校验。
    123. *

    124. * 我们可以定义一个springsecurity的配置类,springsecurity要求这个配置类要继承WebSecurityConfigurerAdapter。然后在注册的时候,注入这个对象,给密码加密存储进数据库
    125. *
    126. * @return
    127. */
    128. @Bean
    129. public PasswordEncoder passwordEncoder() {
    130. return new BCryptPasswordEncoder();
    131. }
    132. @Bean
    133. public JwtTokenUtil jwtTokenUtil() {
    134. return new JwtTokenUtil();
    135. }
    136. /**
    137. * 配置不拦截的请求路径,放行
    138. * @return
    139. */
    140. @Bean
    141. public IgnoreUrlsConfig ignoreUrlsConfig() {
    142. return new IgnoreUrlsConfig();
    143. }
    144. /**
    145. * 自定义一个过滤器,这个过滤器会去获取请求头中的token,对token进行解析去除其中的userid
    146. * 使用userid去redis中获取对于的 AdminUserDetails 对象
    147. * 然后封装Authentication对象存入SecurityContextHolder
    148. * @return
    149. */
    150. @Bean
    151. public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
    152. return new JwtAuthenticationTokenFilter();
    153. }
    154. @Bean
    155. public RestfulAccessDeniedHandler restfulAccessDeniedHandler() {
    156. return new RestfulAccessDeniedHandler();
    157. }
    158. @Bean
    159. public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
    160. return new RestAuthenticationEntryPoint();
    161. }
    162. @ConditionalOnBean(name = "dynamicSecurityService")
    163. @Bean
    164. public DynamicAccessDecisionManager dynamicAccessDecisionManager() {
    165. return new DynamicAccessDecisionManager();
    166. }
    167. @ConditionalOnBean(name = "dynamicSecurityService")
    168. @Bean
    169. public DynamicSecurityFilter dynamicSecurityFilter() {
    170. return new DynamicSecurityFilter();
    171. }
    172. }

    ERROR:Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

    Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    2022-09-08 18:08:09.651 ERROR 20204 --- [           main] o.s.boot.SpringApplication               : Application run failed

    org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
        at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
        at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
        at java.lang.Iterable.forEach(Iterable.java:75)
        at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
        at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
        at com.logging.demo.SpringLoggingDemoApplication.main(SpringLoggingDemoApplication.java:13)
    Caused by: java.lang.NullPointerException: null
        at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:112)
        at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:109)
        at com.google.common.collect.ComparatorOrdering.compare(ComparatorOrdering.java:37)
        at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
        at java.util.TimSort.sort(TimSort.java:220)
        at java.util.Arrays.sort(Arrays.java:1438)
        at com.google.common.collect.Ordering.sortedCopy(Ordering.java:855)
        at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:57)
        at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:138)
        at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:135)
        at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
        at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
        at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
        at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:52)
        at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
        at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:249)
        at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:209)
        at com.google.common.collect.FluentIterable.toList(FluentIterable.java:614)
        at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.defaultContextBuilder(DocumentationPluginsBootstrapper.java:111)
        at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.buildContext(DocumentationPluginsBootstrapper.java:96)
        at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167)
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
        ... 14 common frames omitted

    Disconnected from the target VM, address: '127.0.0.1:52192', transport: 'socket'

    原因:使用springboot2.6.0后,配置swagger,不论是2.9.2还是3.0.0都报错

    解决方法:配置文件中加入 .yml 配置

    1. spring:
    2. mvc:
    3. pathmatch:
    4. matching-strategy: ant_path_matcher


    总结

    提示:这里对文章进行总结:
    例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 相关阅读:
    前篇 + 入门
    4Spring及Spring系列-基本
    MySQL的 validate_password插件 和 validate_password组件
    nodejs+mysql航空飞机票销售酒店预订系统vue
    Spring框架漏洞复现及解析(CVE-2016-4977、CVE-2022-22963、CVE-2017-8046、CVE-2022-22978)
    找出链表中间结点的三种解法
    MoeCTF2022 部分Crypto 复现
    结合两个Python小游戏,带你复习while循环、if判断、函数等知识点
    镜像大全记录使用
    redis命令使用
  • 原文地址:https://blog.csdn.net/qq_39766167/article/details/126663873