最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從零搭建SpringBoot+MyBatisPlus快速開(kāi)發(fā)腳手架

 更新時(shí)間:2022年06月20日 17:13:41   作者:MacroZheng  
這篇文章主要為大家介紹了從零搭建SpringBoot+MyBatisPlus快速開(kāi)發(fā)腳手架示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

關(guān)注我Github的小伙伴應(yīng)該了解,之前我開(kāi)源了一款快速開(kāi)發(fā)腳手架mall-tiny,該腳手架繼承了mall項(xiàng)目的技術(shù)棧,擁有完整的權(quán)限管理功能。最近抽空把該項(xiàng)目支持了Spring Boot 2.7.0,今天再和大家聊聊這個(gè)腳手架,同時(shí)聊聊升級(jí)項(xiàng)目到Spring Boot 2.7.0的一些注意點(diǎn),希望對(duì)大家有所幫助!

SpringBoot實(shí)戰(zhàn)電商項(xiàng)目mall(50k+star)地址:https://github.com/macrozheng/mall

聊聊mall-tiny項(xiàng)目

可能有些小伙伴還不了解這個(gè)腳手架,我們先來(lái)聊聊它!

項(xiàng)目簡(jiǎn)介

mall-tiny是一款基于SpringBoot+MyBatis-Plus的快速開(kāi)發(fā)腳手架,目前在Github上已有1100+Star。它擁有完整的權(quán)限管理功能,支持使用MyBatis-Plus代碼生成器生成代碼,可對(duì)接mall項(xiàng)目的Vue前端,開(kāi)箱即用。

項(xiàng)目地址:https://github.com/macrozheng/mall-tiny

項(xiàng)目演示

mall-tiny項(xiàng)目可無(wú)縫對(duì)接mall-admin-web前端項(xiàng)目,秒變前后端分離腳手架,由于mall-tiny項(xiàng)目?jī)H實(shí)現(xiàn)了基礎(chǔ)的權(quán)限管理功能,所以前端對(duì)接后只會(huì)展示權(quán)限管理相關(guān)功能。

前端項(xiàng)目地址:https://github.com/macrozheng/mall-admin-web

技術(shù)選型

這次升級(jí)不僅支持了Spring Boot 2.7.0,其他依賴版本也升級(jí)到了最新版本。

技術(shù)版本說(shuō)明
SpringBoot2.7.0容器+MVC框架
SpringSecurity5.7.1認(rèn)證和授權(quán)框架
MyBatis3.5.9ORM框架
MyBatis-Plus3.5.1MyBatis增強(qiáng)工具
MyBatis-Plus Generator3.5.1數(shù)據(jù)層代碼生成器
Swagger-UI3.0.0文檔生產(chǎn)工具
Redis5.0分布式緩存
Docker18.09.0應(yīng)用容器引擎
Druid1.2.9數(shù)據(jù)庫(kù)連接池
Hutool5.8.0Java工具類庫(kù)
JWT0.9.1JWT登錄支持
Lombok1.18.24簡(jiǎn)化對(duì)象封裝工具

數(shù)據(jù)庫(kù)表結(jié)構(gòu)

化繁為簡(jiǎn),僅保留了權(quán)限管理功能相關(guān)的9張表,業(yè)務(wù)簡(jiǎn)單更加方便定制開(kāi)發(fā),覺(jué)得mall項(xiàng)目學(xué)習(xí)太復(fù)雜的小伙伴可以先學(xué)習(xí)下mall-tiny。

接口文檔

由于升級(jí)了Swagger版本,原來(lái)的接口文檔訪問(wèn)路徑已經(jīng)改變,最新訪問(wèn)路徑:http://localhost:8080/swagger-ui/

使用流程

升級(jí)版本基本不影響之前的使用方式,具體使用流程可以參考最新版README文件:

https://github.com/macrozheng/mall-tiny

升級(jí)過(guò)程

接下來(lái)我們?cè)賮?lái)聊聊項(xiàng)目升級(jí)Spring Boot 2.7.0版本遇到的問(wèn)題,這些應(yīng)該是升級(jí)該版本的通用問(wèn)題,你如果想升級(jí)2.7.0版本的話,了解下會(huì)很有幫助!

Swagger升級(jí)

/**
 * Swagger API文檔相關(guān)配置
 * 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 <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                List<T> copy = mappings.stream()
                        .filter(mapping -> mapping.getPatternParser() == null)
                        .collect(Collectors.toList());
                mappings.clear();
                mappings.addAll(copy);
            }
            @SuppressWarnings("unchecked")
            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
                try {
                    Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
                    field.setAccessible(true);
                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }
}
  • 之前我們通過(guò)@Api注解的description屬性來(lái)配置接口描述的方法已經(jīng)被棄用了;

  • 我們可以使用@Tag注解來(lái)配置接口說(shuō)明,并使用@Api注解中的tags屬性來(lái)指定。

Spring Security升級(jí)

升級(jí)Spring Boot 2.7.0版本后,原來(lái)通過(guò)繼承WebSecurityConfigurerAdapter來(lái)配置的方法已經(jīng)被棄用了,僅需配置SecurityFilterChainBean即可,具體參考Spring Security最新用法。

/**
 * SpringSecurity 5.4.x以上新用法配置
 * 為避免循環(huán)依賴,僅用于配置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<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity
                .authorizeRequests();
        //不需要保護(hù)的資源路徑允許訪問(wèn)
        for (String url : ignoreUrlsConfig.getUrls()) {
            registry.antMatchers(url).permitAll();
        }
        //允許跨域請(qǐng)求的OPTIONS請(qǐng)求
        registry.antMatchers(HttpMethod.OPTIONS)
                .permitAll();
        // 任何請(qǐng)求需要身份認(rèn)證
        registry.and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                // 關(guān)閉跨站請(qǐng)求防護(hù)及不使用session
                .and()
                .csrf()
                .disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // 自定義權(quán)限拒絕處理類
                .and()
                .exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint)
                // 自定義權(quán)限攔截器JWT過(guò)濾器
                .and()
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //有動(dòng)態(tài)權(quán)限配置時(shí)添加動(dòng)態(tài)權(quán)限校驗(yàn)過(guò)濾器
        if(dynamicSecurityService!=null){
            registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
        }
        return httpSecurity.build();
    }
}

MyBatis-Plus升級(jí)

MyBatis-Plus從之前的版本升級(jí)到了3.5.1版本,用法沒(méi)有大的改變,感覺(jué)最大的區(qū)別就是代碼生成器的用法改了。 在之前的用法中我們是通過(guò)new對(duì)象然后set各種屬性來(lái)配置的,具體參考如下代碼:

/**
 * 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代碼生成器已經(jīng)改成使用建造者模式來(lái)配置了,具體可以參考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();
    }
}

解決循環(huán)依賴問(wèn)題

  • 其實(shí)Spring Boot從2.6.x版本已經(jīng)開(kāi)始不推薦使用循環(huán)依賴了,如果你的項(xiàng)目中使用的循環(huán)依賴比較多的話,可以使用如下配置開(kāi)啟;
spring:
  main:
    allow-circular-references: true
  • 不過(guò)既然官方都不推薦使用了,我們最好還是避免循環(huán)依賴的好,這里分享下我解決循環(huán)依賴問(wèn)題的一點(diǎn)思路。如果一個(gè)類里有多個(gè)依賴項(xiàng),這個(gè)類非必要的Bean就不要配置了,可以使用單獨(dú)的類來(lái)配置Bean。比如SecurityConfig這個(gè)配置類中,我只聲明了必要的SecurityFilterChain配置;
/**
 * SpringSecurity 5.4.x以上新用法配置
 * 為避免循環(huán)依賴,僅用于配置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();
    }
}
  • 其他配置都被我移動(dòng)到了CommonSecurityConfig配置類中,這樣就避免了之前的循環(huán)依賴;
/**
 * SpringSecurity通用配置
 * 包括通用Bean、Security通用Bean及動(dòng)態(tài)權(quán)限通用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();
    }
}
  • 還有一個(gè)典型的循環(huán)依賴問(wèn)題,UmsAdminServiceImpl和UmsAdminCacheServiceImpl相互依賴了;
/**
 * 后臺(tái)管理員管理Service實(shí)現(xiàn)類
 * Created by macro on 2018/4/26.
 */
@Service
public class UmsAdminServiceImpl extends ServiceImpl<UmsAdminMapper,UmsAdmin> implements UmsAdminService {
    @Autowired
    private UmsAdminCacheService adminCacheService;
}
/**
 * 后臺(tái)用戶緩存管理Service實(shí)現(xiàn)類
 * Created by macro on 2020/3/13.
 */
@Service
public class UmsAdminCacheServiceImpl implements UmsAdminCacheService {
    @Autowired
    private UmsAdminService adminService;
}
  • 我們可以創(chuàng)建一個(gè)用于獲取Spring容器中的Bean的工具類來(lái)實(shí)現(xiàn);
/**
 * 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;
        }
    }
    // 通過(guò)name獲取Bean
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }
    // 通過(guò)class獲取Bean
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }
    // 通過(guò)name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
  • 然后在UmsAdminServiceImpl中使用該工具類獲取Bean來(lái)解決循環(huán)依賴。
/**
 * 后臺(tái)管理員管理Service實(shí)現(xiàn)類
 * Created by macro on 2018/4/26.
 */
@Service
public class UmsAdminServiceImpl extends ServiceImpl<UmsAdminMapper,UmsAdmin> implements UmsAdminService {
    @Override
    public UmsAdminCacheService getCacheService() {
        return SpringUtil.getBean(UmsAdminCacheService.class);
    }
}

解決跨域問(wèn)題

在使用Spring Boot 2.7.0版本時(shí),如果不修改之前的跨域配置,通過(guò)前端訪問(wèn)會(huì)出現(xiàn)跨域問(wèn)題,后端報(bào)錯(cuò)如下。

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已經(jīng)不再支持通配符*的配置了,改為需要使用allowedOriginPatterns來(lái)設(shè)置,具體配置修改如下。

/**
 * 全局跨域配置
 * Created by macro on 2019/7/27.
 */
@Configuration
public class GlobalCorsConfig {
    /**
     * 允許跨域調(diào)用的過(guò)濾器
     */
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        //允許所有域名進(jìn)行跨域調(diào)用
        config.addAllowedOriginPattern("*");
        //該用法在SpringBoot 2.7.0中已不再支持
        //config.addAllowedOrigin("*");
        //允許跨越發(fā)送cookie
        config.setAllowCredentials(true);
        //放行全部原始頭信息
        config.addAllowedHeader("*");
        //允許所有請(qǐng)求方法跨域調(diào)用
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

總結(jié)

今天分享了下我的開(kāi)源項(xiàng)目腳手架mall-tiny,以及它升級(jí)SpringBoot 2.7.0的過(guò)程。我們?cè)趯?xiě)代碼的時(shí)候,如果有些用法已經(jīng)廢棄,應(yīng)該盡量去尋找新的用法來(lái)使用,這樣才能保證我們的代碼足夠優(yōu)雅!

項(xiàng)目地址 https://github.com/macrozheng/mall-tiny

以上就是從零搭建SpringBoot+MyBatisPlus快速開(kāi)發(fā)腳手架的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot+MyBatisPlus從零搭建的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Idea開(kāi)發(fā)工具之SpringBoot整合JSP的過(guò)程

    Idea開(kāi)發(fā)工具之SpringBoot整合JSP的過(guò)程

    最近在學(xué)習(xí)SpringBoot,看到SpringBoot整合jsp,順帶記錄一下。本文通過(guò)圖文實(shí)例相結(jié)合給大家講解SpringBoot整合JSP的過(guò)程,感興趣的朋友一起看看吧
    2021-09-09
  • Spring Boot中使用LDAP來(lái)統(tǒng)一管理用戶信息的示例

    Spring Boot中使用LDAP來(lái)統(tǒng)一管理用戶信息的示例

    本篇文章主要介紹了Spring Boot中使用LDAP來(lái)統(tǒng)一管理用戶信息的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法

    Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法

    這篇文章主要介紹了Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-12-12
  • java實(shí)現(xiàn)md5加密示例

    java實(shí)現(xiàn)md5加密示例

    這篇文章主要介紹了java實(shí)現(xiàn)md5加密示例,需要的朋友可以參考下
    2014-05-05
  • SpringBoot中Filter?bean如何添加到Servlet容器

    SpringBoot中Filter?bean如何添加到Servlet容器

    這篇文章主要介紹了SpringBoot中Filter bean是怎么被添加到Servlet容器中的,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • java多線程實(shí)現(xiàn)下載圖片并壓縮

    java多線程實(shí)現(xiàn)下載圖片并壓縮

    這篇文章主要為大家詳細(xì)介紹了java多線程實(shí)現(xiàn)下載圖片并壓縮,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Java 8 中 Map 騷操作之 merge() 的使用方法

    Java 8 中 Map 騷操作之 merge() 的使用方法

    本文簡(jiǎn)單介紹了一下Map.merge()的方法,除此之外,Java 8 中的HashMap實(shí)現(xiàn)方法使用了TreeNode和 紅黑樹(shù),原理很相似,今天通過(guò)本文給大家介紹Java 8 中 Map 騷操作之 merge() 的用法 ,需要的朋友參考下吧
    2021-07-07
  • SpringBoot中的Actuator詳解

    SpringBoot中的Actuator詳解

    這篇文章主要介紹了SpringBoot中的Actuator詳解,Spring Boot Actuator 在Spring Boot第一個(gè)版本發(fā)布的時(shí)候就有了,它為Spring Boot提供了一系列產(chǎn)品級(jí)的特性,監(jiān)控應(yīng)用程序,收集元數(shù)據(jù),運(yùn)行情況或者數(shù)據(jù)庫(kù)狀態(tài)等,需要的朋友可以參考下
    2023-09-09
  • 如何解決maven搭建一直處于running:..狀態(tài)問(wèn)題

    如何解決maven搭建一直處于running:..狀態(tài)問(wèn)題

    在使用Maven搭建項(xiàng)目時(shí),有時(shí)會(huì)遇到一直處于加載狀態(tài)的情況,通過(guò)修改設(shè)置可以解決這個(gè)問(wèn)題,具體步驟為:1. 打開(kāi)File->Settings->Build, Execution, Deployment->Maven->running,然后在VMOptions中填寫(xiě)"-DarchetypeCatalog=internal"
    2024-09-09
  • JFreeChart簡(jiǎn)單實(shí)現(xiàn)光滑曲線繪制

    JFreeChart簡(jiǎn)單實(shí)現(xiàn)光滑曲線繪制

    這篇文章主要為大家詳細(xì)介紹了JFreeChart簡(jiǎn)單實(shí)現(xiàn)光滑曲線的繪制,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06

最新評(píng)論

卢氏县| 桂东县| 红原县| 新野县| 玉林市| 兴仁县| 通州区| 汉中市| 宜丰县| 双牌县| 滨海县| 喜德县| 商洛市| 万州区| 进贤县| 绥化市| 大港区| 永顺县| 报价| 聂荣县| 芜湖县| 阿拉善左旗| 溆浦县| 和田县| 泗水县| 巧家县| 鄂伦春自治旗| 普宁市| 仁怀市| 府谷县| 西宁市| 林西县| 朝阳市| 阜南县| 胶南市| 靖边县| 陕西省| 石家庄市| 涡阳县| 铜梁县| 东明县|