springboot項目架構(gòu)(3)--- webmvc对湃,mybatis,redis,log4j2 —— JavaBean配置

springboot提倡0配置文件配置卡骂,改用JavaBean配置全跨,而剛轉(zhuǎn)到springboot的人不免有些無從下手,這篇文章就介紹一下挪钓,springboot的常用JavaBean配置。

1馏予、webmvc配置

這里webmvc配置主要是添加"過濾器"呢岗,"攔截器"敷燎,與重寫接口解析方式

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcAutoConfiguration implements WebMvcConfigurer{

    /**
     * 指定日期接口解析方式
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }

    /**
     * 把返回Json中的null換為""
     */
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new NullSerializer());
        return objectMapper;
    }

    /**
     * 添加攔截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> patterns = new ArrayList<>();
        patterns.add("/html/**");
        patterns.add("/script/**");
        patterns.add("/print/**");
        patterns.add("/index.html");
        patterns.add("/swagger-ui.html");
        patterns.add("/webjars/**");
        patterns.add("/swagger-resources/**");
        patterns.add("/swagger-resources/**");
        registry.addInterceptor(new SessionInterceptor()).excludePathPatterns(patterns); 
    }

    /**
     * 添加過濾器
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public FilterRegistrationBean<PageFilter> filterRegistrationBean() {
        FilterRegistrationBean<PageFilter> registrationBean = new FilterRegistrationBean<PageFilter>();
        PageFilter loginFilter = new PageFilter();
        registrationBean.setFilter(loginFilter);
        List<String> urlPatterns = new ArrayList<String>();
        urlPatterns.add("/login");
        urlPatterns.add("*.html");
        registrationBean.setUrlPatterns(urlPatterns);
        return registrationBean;
    }

}

2、mybatis配置

mybatis配置是通過注入的方式實現(xiàn)的务漩,只需要在webmcv配置最后添加即可

/**
 * mybatis配置
 * @return
 */
@Bean
ConfigurationCustomizer mybatisConfig(){
    return configuration -> {
        // setting
        configuration.setUseGeneratedKeys(true);
        configuration.setCacheEnabled(true);
        configuration.setLazyLoadingEnabled(true);
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
        configuration.setAggressiveLazyLoading(true);

        // typeAlias
        configuration.getTypeAliasRegistry().registerAliases("com.pcbwx.jsp.bean");
    };
}

3、reids配置

我這里的redis配置比較簡單,主要是配置redis所用操作類Template

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * 創(chuàng)建redis操作實例
     * @param clazz     泛型類
     * @param connectionFactory redis連接工廠
     * @return
     */
    private <T> RedisTemplate<String, T> createTemplate(Class<T> clazz, RedisConnectionFactory connectionFactory){
        Jackson2JsonRedisSerializer<T> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<T>(
            clazz);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        RedisTemplate<String, T> template = new RedisTemplate<String, T>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    // --------------------注入操作類---------------------------

    @Bean
    StringRedisTemplate stringTemplate(RedisConnectionFactory connectionFactory) {
        return new StringRedisTemplate(connectionFactory);
    }

    @Bean
    RedisTemplate<String, Object> template(RedisConnectionFactory connectionFactory) {
        return createTemplate(Object.class, connectionFactory);
    }

    @Bean
    RedisTemplate<String, Dictionary> templateDic(RedisConnectionFactory connectionFactory) {
        return createTemplate(Dictionary.class, connectionFactory);
    }
    
}

4抬旺、log4j2配置

在springboot使用log4j2,首先需要添加jar包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 去除springboot默認日志logback-->
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

log4j2配置添加了線上線下環(huán)境配置,日志文件按天保存碾褂,線上環(huán)境異步輸出日志。

@Plugin(name = "log4j2Config", category = ConfigurationFactory.CATEGORY)
@Order(Ordered.HIGHEST_PRECEDENCE)
@org.springframework.context.annotation.Configuration
public class Log4j2Config extends ConfigurationFactory{

    private static final String INFOAPPENDER = "myInfo";

    private static final String ERRORAPPENDER = "myError";

    private static final String CONSOLE = "Console";

    private static final String ASYNC = "ASYNC";

    private static final String FILEPATH = "/opt/logs/";

    private static final boolean dev = true;

    private Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
        builder.setConfigurationName(name);
        builder.setStatusLevel(Level.INFO);
        if (dev) {
            builder.add(getConsoleBuilder(builder));
            addDevLogger(builder);
            builder.add(builder.newRootLogger(Level.INFO).add(builder.newAppenderRef(CONSOLE)));
        } else {
            builder.add(getErrorFileBuilder(builder));
            builder.add(getInfoFileBuilder(builder));
            builder.add(getAsyncBuilder(builder));
            builder.add(builder.newRootLogger(Level.INFO).add(builder.newAppenderRef(ASYNC)));
        }
        return builder.build();
    }

    @Override
    public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
        return getConfiguration(loggerContext, source.toString(), null);
    }

    @Override
    public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
        ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
        return createConfiguration(name, builder);
    }

    @Override
    protected String[] getSupportedTypes() {
        return new String[] {"*"};
    }

    /**
     * 獲取顯示臺適配器
     * @param builder
     * @return
     */
    private AppenderComponentBuilder getConsoleBuilder(
        ConfigurationBuilder<BuiltConfiguration> builder) {
        AppenderComponentBuilder appenderBuilder = builder.newAppender(
              CONSOLE, "Console").addAttribute("target",
            ConsoleAppender.Target.SYSTEM_OUT);
        appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute(
            "pattern",
            "%d{HH:mm:ss} %-5level %logger{36} [%L] - %msg%n"));
        return appenderBuilder;
    }

    /**
     * 獲取Error文件日志適配器
     * @param builder
     * @return
     */
    private AppenderComponentBuilder getInfoFileBuilder(
        ConfigurationBuilder<BuiltConfiguration> builder) {
        AppenderComponentBuilder appenderBuilder = builder
            .newAppender(INFOAPPENDER, "RollingFile")
            .addAttribute("fileName", FILEPATH + "/info/info.log")
            .addAttribute("filePattern", FILEPATH + "/info/info-%d{yyyy-MM-dd}.log");
        appenderBuilder.add(builder.newLayout("ThresholdFilter")
            .addAttribute("level", Level.INFO)
            .addAttribute("onMatch", "ACCEPT")
            .addAttribute("onMismatch", "DENY"));
        appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute(
            "pattern",
            "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} [%L] - %msg%n"));
        appenderBuilder.add(builder.newLayout("Policies").addComponent(
            builder.newLayout("TimeBasedTriggeringPolicy")
                    .addAttribute("modulate", true)
                    .addAttribute("interval", "1")));
        return appenderBuilder;
    }

    /**
     * 獲取Info文件日志適配器
     * @param builder
     * @return
     */
    private AppenderComponentBuilder getErrorFileBuilder(
        ConfigurationBuilder<BuiltConfiguration> builder) {
        AppenderComponentBuilder appenderBuilder = builder
            .newAppender(ERRORAPPENDER, "RollingFile")
            .addAttribute("fileName",
                    FILEPATH + "/error/error.log")
            .addAttribute("filePattern",
                    FILEPATH + "/error/error-%d{yyyy-MM-dd}.log");
        appenderBuilder.add(builder.newLayout("ThresholdFilter")
            .addAttribute("level", Level.ERROR)
            .addAttribute("onMatch", "ACCEPT")
            .addAttribute("onMismatch", "DENY"));
        appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute(
            "pattern",
            "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} [%L] - %msg%n"));
        appenderBuilder.add(builder.newLayout("Policies").addComponent(
            builder.newLayout("TimeBasedTriggeringPolicy")
                    .addAttribute("modulate", true)
                    .addAttribute("interval", "1")));
        return appenderBuilder;
    }

    /**
     * 獲取異步寫日志適配器
     * @param builder
     * @return
     */
    private AppenderComponentBuilder getAsyncBuilder(
        ConfigurationBuilder<BuiltConfiguration> builder) {
        AppenderComponentBuilder appenderBuilder = builder
            .newAppender(ASYNC, "Async");
        appenderBuilder.add(builder.newLayout("AppenderRef")
                .addAttribute("ref", INFOAPPENDER));
        appenderBuilder.add(builder.newLayout("AppenderRef")
                .addAttribute("ref", ERRORAPPENDER));
        return appenderBuilder;
    }

    /**
     * 添加debug環(huán)境
     * @param builder
     */
    private void addDevLogger(ConfigurationBuilder<BuiltConfiguration> builder){
        // 添加mybatis-debug支持
        LoggerComponentBuilder loggerMyBatisBuilder = builder
            .newLogger("com.pcbwx.jsp.dao", Level.DEBUG)
            .addAttribute("additivity", false)
            .add(builder.newAppenderRef(CONSOLE));
        builder.add(loggerMyBatisBuilder);

        // 添加spring-debug支持
        LoggerComponentBuilder loggerSpringBuilder = builder
            .newLogger("org.springframework", Level.INFO)
            .addAttribute("additivity", false)
            .add(builder.newAppenderRef(CONSOLE));
        builder.add(loggerSpringBuilder);
    }

}

github: https://github.com/HeyuRise/jsp

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巍杈,一起剝皮案震驚了整個濱河市词裤,隨后出現(xiàn)的幾起案子吼砂,更是在濱河造成了極大的恐慌,老刑警劉巖周偎,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磷仰,死亡現(xiàn)場離奇詭異伺通,居然都是意外死亡罐监,警方通過查閱死者的電腦和手機沟堡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門屁药,熙熙樓的掌柜王于貴愁眉苦臉地迎上來复亏,“玉大人,你說我怎么就攤上這事刹淌≌钇簦” “怎么了挣磨?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵晤锥,是天一觀的道長矾瘾。 經(jīng)常有香客問我,道長北救,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任唉堪,我火速辦了婚禮链方,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己罢维,他們只是感情好颜阐,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著磅叛,像睡著了一般杖爽。 火紅的嫁衣襯著肌膚如雪腋寨。 梳的紋絲不亂的頭發(fā)上聪铺,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音萄窜,去河邊找鬼铃剔。 笑死,一個胖子當著我的面吹牛查刻,可吹牛的內(nèi)容都是我干的键兜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼穗泵,長吁一口氣:“原來是場噩夢啊……” “哼普气!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佃延,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤现诀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后履肃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仔沿,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年榆浓,在試婚紗的時候發(fā)現(xiàn)自己被綠了于未。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡陡鹃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抖坪,到底是詐尸還是另有隱情萍鲸,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布擦俐,位于F島的核電站脊阴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蚯瞧。R本人自食惡果不足惜嘿期,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埋合。 院中可真熱鬧备徐,春花似錦、人聲如沸甚颂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹭睡,卻和暖如春衍菱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肩豁。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工脊串, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人清钥。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓琼锋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親循捺。 傳聞我的和親對象是個殘疾皇子斩例,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容