当前位置:

首页 > 编程开发 > 如何搭建SpringBoot+MyBatisPlus快速开发脚手架

如何搭建SpringBoot+MyBatisPlus快速开发脚手架

聊聊mall-tiny项目可能有些小伙伴还不了解这个脚手架,我们先来聊聊它!项目简介mall-tiny是一款基于SpringBoot+MyBatis-Plus的快速开发脚手架,目前在Github上已有1100+Star。它拥有完整的权限管理功能,支持使用MyBatis-Plus代码生成器生成代码,可对接mall项目的Vue前端,开箱即用。项目演示mall-tiny项目可无缝对接mall-admin-web前端项目,秒变前后端分离脚手架,由于mall-tiny项目仅实现了基础的权限管理功能,所以前端对接后只

本文目录

      聊聊mall-tiny项目

      可能有些小伙伴还不了解这个脚手架,我们先来聊聊它!

      项目简介

      mall-tiny是一款基于SpringBoot+MyBatis-Plus的快速开发脚手架,目前在Github上已有1100+Star。它拥有完整的权限管理功能,支持使用MyBatis-Plus代码生成器生成代码,可对接mall项目的Vue前端,开箱即用。

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      项目演示

      mall-tiny项目可无缝对接mall-admin-web前端项目,秒变前后端分离脚手架,由于mall-tiny项目仅实现了基础的权限管理功能,所以前端对接后只会展示权限管理相关功能。

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      技术选型

      这次升级不仅支持了Spring Boot 2.7.0,其他依赖版本也升级到了最新版本。

      技术版本说明
      SpringBoot2.7.0容器+MVC框架
      SpringSecurity5.7.1认证和授权框架
      MyBatis3.5.9ORM框架
      MyBatis-Plus3.5.1MyBatis增强工具
      MyBatis-Plus Generator3.5.1数据层代码生成器
      Swagger-UI3.0.0文档生产工具
      Redis5.0分布式缓存
      Docker18.09.0应用容器引擎
      Druid1.2.9数据库连接池
      Hutool5.8.0Java工具类库
      JWT0.9.1JWT登录支持
      Lombok1.18.24简化对象封装工具

      数据库表结构

      化繁为简,仅保留了权限管理功能相关的9张表,业务简单更加方便定制开发,觉得mall项目学习太复杂的小伙伴可以先学习下mall-tiny。

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      接口文档

      由于升级了Swagger版本,原来的接口文档访问路径已经改变,最新访问路径:http://localhost:8080/swagger-ui/

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      使用流程

      升级版本基本不影响之前的使用方式,具体使用流程可以参考最新版README文件:

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      升级过程

      接下来我们再来聊聊项目升级Spring Boot 2.7.0版本遇到的问题,这些应该是升级该版本的通用问题,你如果想升级2.7.0版本的话,了解下会很有帮助!

      Swagger升级

      • 在升级Spring Boot 2.6.x版本的时候,其实Swagger就有一定的兼容性问题,需要在配置中添加BeanPostProcessor这个Bean,具体可以参考升级 SpringBoot 2.6.x 版本后,Swagger 没法用了! ;

      /**
       * Swagger API文档相关配置
       * Created by macro on 2018/4/26.
       */
      @Configuration
      @EnableSwagger2
      public class SwaggerConfig extends BaseSwaggerConfig {
          @Bean
          public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
              return new BeanPostProcessor() {
                  @Override
                  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                      if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
                          customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                      }
                      return bean;
                  }
                  private  void customizeSpringfoxHandlerMappings(List mappings) {
                      List copy = mappings.stream()
                              .filter(mapping -> mapping.getPatternParser() == null)
                              .collect(Collectors.toList());
                      mappings.clear();
                      mappings.addAll(copy);
                  }
                  @SuppressWarnings("unchecked")
                  private List getHandlerMappings(Object bean) {
                      try {
                          Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
                          field.setAccessible(true);
                          return (List) field.get(bean);
                      } catch (IllegalArgumentException | IllegalAccessException e) {
                          throw new IllegalStateException(e);
                      }
                  }
              };
          }
      }
      • 之前我们通过@Api注解的description属性来配置接口描述的方法已经被弃用了;

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      • 我们可以使用@Tag注解来配置接口说明,并使用@Api注解中的tags属性来指定。

      如何搭建SpringBoot+MyBatisPlus快速开发脚手架

      Spring Security升级

      升级Spring Boot 2.7.0版本后,原来通过继承WebSecurityConfigurerAdapter来配置的方法已经被弃用了,仅需配置SecurityFilterChainBean即可,具体参考Spring Security最新用法。

      /**
       * SpringSecurity 5.4.x以上新用法配置
       * 为避免循环依赖,仅用于配置HttpSecurity
       * Created by macro on 2019/11/5.
       */
      @Configuration
      public class SecurityConfig {
          @Autowired
          private IgnoreUrlsConfig ignoreUrlsConfig;
          @Autowired
          private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
          @Autowired
          private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
          @Autowired
          private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
          @Autowired
          private DynamicSecurityService dynamicSecurityService;
          @Autowired
          private DynamicSecurityFilter dynamicSecurityFilter;
          @Bean
          SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
              ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity
                      .authorizeRequests();
              //不需要保护的资源路径允许访问
              for (String url : ignoreUrlsConfig.getUrls()) {
                  registry.antMatchers(url).permitAll();
              }
              //允许跨域请求的OPTIONS请求
              registry.antMatchers(HttpMethod.OPTIONS)
                      .permitAll();
              // 任何请求需要身份认证
              registry.and()
                      .authorizeRequests()
                      .anyRequest()
                      .authenticated()
                      // 关闭跨站请求防护及不使用session
                      .and()
                      .csrf()
                      .disable()
                      .sessionManagement()
                      .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                      // 自定义权限拒绝处理类
                      .and()
                      .exceptionHandling()
                      .accessDeniedHandler(restfulAccessDeniedHandler)
                      .authenticationEntryPoint(restAuthenticationEntryPoint)
                      // 自定义权限拦截器JWT过滤器
                      .and()
                      .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
              //有动态权限配置时添加动态权限校验过滤器
              if(dynamicSecurityService!=null){
                  registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
              }
              return httpSecurity.build();
          }
      }

      MyBatis-Plus升级

      MyBatis-Plus从之前的版本升级到了3.5.1版本,用法没有大的改变,感觉最大的区别就是代码生成器的用法改了。 在之前的用法中我们是通过new对象然后set各种属性来配置的,具体参考如下代码:

      /**
       * MyBatisPlus代码生成器
       * Created by macro on 2020/8/20.
       */
      public class MyBatisPlusGenerator {
          /**
           * 初始化全局配置
           */
          private static GlobalConfig initGlobalConfig(String projectPath) {
              GlobalConfig globalConfig = new GlobalConfig();
              globalConfig.setOutputDir(projectPath + "/src/main/java");
              globalConfig.setAuthor("macro");
              globalConfig.setOpen(false);
              globalConfig.setSwagger2(true);
              globalConfig.setBaseResultMap(true);
              globalConfig.setFileOverride(true);
              globalConfig.setDateType(DateType.ONLY_DATE);
              globalConfig.setEntityName("%s");
              globalConfig.setMapperName("%sMapper");
              globalConfig.setXmlName("%sMapper");
              globalConfig.setServiceName("%sService");
              globalConfig.setServiceImplName("%sServiceImpl");
              globalConfig.setControllerName("%sController");
              return globalConfig;
          }
      }

      而新版的MyBatis-Plus代码生成器已经改成使用建造者模式来配置了,具体可以参考MyBatisPlusGenerator类中的代码。

      /**
       * MyBatisPlus代码生成器
       * Created by macro on 2020/8/20.
       */
      public class MyBatisPlusGenerator {
          /**
           * 初始化全局配置
           */
          private static GlobalConfig initGlobalConfig(String projectPath) {
              return new GlobalConfig.Builder()
                      .outputDir(projectPath + "/src/main/java")
                      .author("macro")
                      .disableOpenDir()
                      .enableSwagger()
                      .fileOverride()
                      .dateType(DateType.ONLY_DATE)
                      .build();
          }
      }

      解决循环依赖问题

      • 其实Spring Boot从2.6.x版本已经开始不推荐使用循环依赖了,如果你的项目中使用的循环依赖比较多的话,可以使用如下配置开启;

      spring:
        main:
          allow-circular-references: true
      • 不过既然官方都不推荐使用了,我们最好还是避免循环依赖的好,这里分享下我解决循环依赖问题的一点思路。如果一个类里有多个依赖项,这个类非必要的Bean就不要配置了,可以使用单独的类来配置Bean。比如SecurityConfig这个配置类中,我只声明了必要的SecurityFilterChain配置;

      /**
       * SpringSecurity 5.4.x以上新用法配置
       * 为避免循环依赖,仅用于配置HttpSecurity
       * Created by macro on 2019/11/5.
       */
      @Configuration
      public class SecurityConfig {
          @Autowired
          private IgnoreUrlsConfig ignoreUrlsConfig;
          @Autowired
          private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
          @Autowired
          private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
          @Autowired
          private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
          @Autowired
          private DynamicSecurityService dynamicSecurityService;
          @Autowired
          private DynamicSecurityFilter dynamicSecurityFilter;
          @Bean
          SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
              //省略若干代码...
              return httpSecurity.build();
          }
      }
      • 其他配置都被我移动到了CommonSecurityConfig配置类中,这样就避免了之前的循环依赖;

      /**
       * SpringSecurity通用配置
       * 包括通用Bean、Security通用Bean及动态权限通用Bean
       * Created by macro on 2022/5/20.
       */
      @Configuration
      public class CommonSecurityConfig {
          @Bean
          public PasswordEncoder passwordEncoder() {
              return new BCryptPasswordEncoder();
          }
          @Bean
          public IgnoreUrlsConfig ignoreUrlsConfig() {
              return new IgnoreUrlsConfig();
          }
          @Bean
          public JwtTokenUtil jwtTokenUtil() {
              return new JwtTokenUtil();
          }
          @Bean
          public RestfulAccessDeniedHandler restfulAccessDeniedHandler() {
              return new RestfulAccessDeniedHandler();
          }
          @Bean
          public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
              return new RestAuthenticationEntryPoint();
          }
          @Bean
          public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
              return new JwtAuthenticationTokenFilter();
          }
          @Bean
          public DynamicAccessDecisionManager dynamicAccessDecisionManager() {
              return new DynamicAccessDecisionManager();
          }
          @Bean
          public DynamicSecurityMetadataSource dynamicSecurityMetadataSource() {
              return new DynamicSecurityMetadataSource();
          }
          @Bean
          public DynamicSecurityFilter dynamicSecurityFilter(){
              return new DynamicSecurityFilter();
          }
      }
      • 还有一个典型的循环依赖问题,UmsAdminServiceImpl和UmsAdminCacheServiceImpl相互依赖了;

      /**
       * 后台管理员管理Service实现类
       * Created by macro on 2018/4/26.
       */
      @Service
      public class UmsAdminServiceImpl extends ServiceImpl implements UmsAdminService {
          @Autowired
          private UmsAdminCacheService adminCacheService;
      }
      /**
       * 后台用户缓存管理Service实现类
       * Created by macro on 2020/3/13.
       */
      @Service
      public class UmsAdminCacheServiceImpl implements UmsAdminCacheService {
          @Autowired
          private UmsAdminService adminService;
      }
      • 我们可以创建一个用于获取Spring容器中的Bean的工具类来实现;

      /**
       * Spring工具类
       * Created by macro on 2020/3/3.
       */
      @Component
      public class SpringUtil implements ApplicationContextAware {
          private static ApplicationContext applicationContext;
          // 获取applicationContext
          public static ApplicationContext getApplicationContext() {
              return applicationContext;
          }
          @Override
          public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
              if (SpringUtil.applicationContext == null) {
                  SpringUtil.applicationContext = applicationContext;
              }
          }
          // 通过name获取Bean
          public static Object getBean(String name) {
              return getApplicationContext().getBean(name);
          }
          // 通过class获取Bean
          public static  T getBean(Class clazz) {
              return getApplicationContext().getBean(clazz);
          }
          // 通过name,以及Clazz返回指定的Bean
          public static  T getBean(String name, Class clazz) {
              return getApplicationContext().getBean(name, clazz);
          }
      }
      • 然后在UmsAdminServiceImpl中使用该工具类获取Bean来解决循环依赖。

      /**
       * 后台管理员管理Service实现类
       * Created by macro on 2018/4/26.
       */
      @Service
      public class UmsAdminServiceImpl extends ServiceImpl implements UmsAdminService {
          @Override
          public UmsAdminCacheService getCacheService() {
              return SpringUtil.getBean(UmsAdminCacheService.class);
          }
      }

      解决跨域问题

      在使用Spring Boot 2.7.0版本时,如果不修改之前的跨域配置,通过前端访问会出现跨域问题,后端报错如下。

      java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. 
      To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

      具体的意思就是allowedOrigins已经不再支持通配符*的配置了,改为需要使用allowedOriginPatterns来设置,具体配置修改如下。

      /**
       * 全局跨域配置
       * Created by macro on 2019/7/27.
       */
      @Configuration
      public class GlobalCorsConfig {
          /**
           * 允许跨域调用的过滤器
           */
          @Bean
          public CorsFilter corsFilter() {
              CorsConfiguration config = new CorsConfiguration();
              //允许所有域名进行跨域调用
              config.addAllowedOriginPattern("*");
              //该用法在SpringBoot 2.7.0中已不再支持
              //config.addAllowedOrigin("*");
              //允许跨越发送cookie
              config.setAllowCredentials(true);
              //放行全部原始头信息
              config.addAllowedHeader("*");
              //允许所有请求方法跨域调用
              config.addAllowedMethod("*");
              UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
              source.registerCorsConfiguration("/**", config);
              return new CorsFilter(source);
          }
      }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发
      相关文章 更多
      springBoot项目常用目录有哪些
      springBoot项目常用目录有哪些

      springBoot项目常用目录springBoot项目的目录结构及名规范介绍基于SpringBoot开发时的目录结构及命名规范,通过介绍能够为你解决,在实际项目中如何规划目录结构?如何命名目录更规范?各个目录分别代表什么含义?等三个问题。目录说明servicex//项目名|-admin-ui//管理服务前端代码(一般将UI和SERVICE放到一个工程中,便于管理)|-servicex-auth//模块1|-servicex-common//模块2|-servicex-gateway//模块3|-serv

      解析SpringBoot和SpringMVC之间的异同
      解析SpringBoot和SpringMVC之间的异同

      解析SpringBoot和SpringMVC之间的异同SpringBoot和SpringMVC是Java领域中非常重要的开发框架。虽然它们都属于Spring框架的一部分,但是在使用和功能上有一些明显的区别。本文将对SpringBoot和SpringMVC进行比较,解析它们之间的异同。首先,让我们来了解一下SpringBoot。SpringBo

      探索SpringCloud和SpringBoot在微服务领域的不同应用方式
      探索SpringCloud和SpringBoot在微服务领域的不同应用方式

      近年来,随着云计算和分布式架构的兴起,微服务架构的应用越来越广泛。而SpringCloud和SpringBoot作为Java开发中的两个重要框架,对于微服务的实现起到了重要的作用。然而,很多人对于它们在微服务领域的不同应用方式还存在一定的疑惑。本文将从不同的角度探索SpringCloud和SpringBoot在微服务中的应用方式。首先,我们来了解一下Spri

      SpringBoot和SpringMVC有何区别?
      SpringBoot和SpringMVC有何区别?

      SpringBoot与SpringMVC的不同之处在哪里?SpringBoot和SpringMVC是两个非常流行的Java开发框架,用于构建Web应用程序。尽管它们经常分别被使用,但它们之间的不同之处也是很明显的。首先,SpringBoot可以被看作是一个Spring框架的扩展或者增强版。它旨在简化Spring应用程序的初始化和配置过程,以帮助开发人

      比较SpringBoot和SpringMVC的异同
      比较SpringBoot和SpringMVC的异同

      SpringBoot和SpringMVC都是Java开发中常用的框架,但它们之间有一些明显的差异。本文将探究这两个框架的特点和用途,并对它们的差异进行比较。首先,我们来了解一下SpringBoot。SpringBoot是由Pivotal团队开发的,它旨在简化基于Spring框架的应用程序的创建和部署。它提供了一种快速、轻量级的方式来构建独立的、可执行

      SpringBoot与SpringMVC的不同点是什么?
      SpringBoot与SpringMVC的不同点是什么?

      SpringBoot和SpringMVC是Java开发中常用的两个框架,它们都是由Spring框架所提供的,但在功能和使用方式上有着一些区别。本文将分别介绍SpringBoot和SpringMVC的特点和区别。一、SpringBoot的特点:简化配置:SpringBoot通过约定优于配置的原则,大大简化了项目的配置过程。它可以自动配置项目所需要的参数,开发人

      比较和选择指南:SpringCloud与SpringBoot的功能比较
      比较和选择指南:SpringCloud与SpringBoot的功能比较

      SpringCloud和SpringBoot是目前Java领域中最热门的开源框架,它们分别提供了一套完善的微服务架构和快速构建应用程序的解决方案。本文将对它们的功能进行比较,并给出选择指南,以帮助读者了解它们的优势和适用场景。SpringBoot是一个用于开发Java应用程序的框架,它提供了一个简化的开发流程,集成了大量常用的功能和组件,减少了开发者的工作量

      SpringCloud与SpringBoot:分析它们之间的相似与不同
      SpringCloud与SpringBoot:分析它们之间的相似与不同

      深入剖析SpringCloud和SpringBoot的异同引言:在构建企业级应用程序时,Spring框架已经成为开发者们的首选。它提供了一种简单而强大的方式来构建独立于平台的应用程序。Spring框架由两个核心模块组成:SpringBoot和SpringCloud。虽然它们都可以帮助开发者快速搭建应用程序,但它们的目标和用途存在一些差异。本文将深入剖析Spr

      从架构角度看SpringCloud与SpringBoot的差异
      从架构角度看SpringCloud与SpringBoot的差异

      从架构角度看SpringCloud与SpringBoot的差异引言:在当今的互联网时代,构建分布式系统已经成为了一种必要的需求。而SpringBoot和SpringCloud正是为了满足这个需求而诞生的。尽管它们都是由Spring框架所提供的解决方案,但从架构角度来看,它们存在着一些重要的差异。本文将从架构的角度出发,对SpringBoot和SpringCl

      Java API 开发中使用 SpringBoot 的利弊分析
      Java API 开发中使用 SpringBoot 的利弊分析

      JavaAPI开发中使用SpringBoot的利弊分析随着互联网的快速发展和技术的不断更新迭代,Java技术在开发中的广泛应用引起了人们的重视。而SpringBoot作为一种微服务架构的解决方案,已经逐渐成为Java开发中的热门选择。那么,在JavaAPI开发中使用SpringBoot,到底有哪些利弊呢?下面来分析一下。利:简化开发

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。