Spring Boot从入门到进阶教程系列 -- 外部Tomcat多方式启动,加密解密配置数据

       由于前些日子比较忙着一些工作事情,导致没有更新连续性的教程文章,现在往后一段时间我打算写当下比较流行的Spring Boot框架教程,从入门到进阶的使用方式,希望该系列文章对大家有一些开发上的帮助,而不需要看其他站点上让你看到花眼又不得本质的教程文章,本系列教程需要有一定的开发经验基础,如有不正确的地方望指出;前言到此,我们开启教程之旅.

步骤1.

准备我们的POM.xml文件,我使用的是Spring Boot 2.0.0版本,JDK建议1.8+(关键),其中我们可以看到配置移除了内嵌Tomcat插件,因为我们真实应用项目中需要比较多自定义的容器,所以我不建议使用内嵌的Tomcat作为开发使用

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.soho</groupId>
    <artifactId>soho</artifactId>
    <version>3.0.6</version>
    <packaging>pom</packaging>

    <properties>
        <maven.local.server>https://localhost</maven.local.server>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <mybatis.boot.version>1.3.1</mybatis.boot.version>
        <mysql.version>5.1.18</mysql.version>
        <fastjson.version>1.2.46</fastjson.version>
        <druid.version>1.1.0</druid.version>
        <log4j.version>1.2.17</log4j.version>
        <shiro.spring.version>1.4.0</shiro.spring.version>
        <servlet.version>3.1.0</servlet.version>
        <commons.io.version>2.4</commons.io.version>
    </properties>

    <!-- maven install不过滤指定资源 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <dependencies>
        <!-- Spring Boot Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 移除嵌入式tomcat插件 -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Spring Boot Aop 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- Spring Boot Freemarker 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- Spring Boot Ehcache需要的依赖-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <!-- Spring Boot Logback需要的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!-- Spring Boot Mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.boot.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons.io.version}</version>
        </dependency>
    </dependencies>

</project>

步骤2.

编写我们的启动类,其中我们应该设计有两种启动实现类,一种是读取本地application.properties方式,一种是读取zookeeper配置数据方式,所以我们需要设计一个合理的启动类,方便我们切换启动方式

以下类是Spring读取配置数据,我们可在该扩展类操作我们的一些配置数据加密解密,比如数据库的账号和密码等等,其中AESUtils可自行编写一个AES加密工具类即可,decodeKeys是我们需要解密的配置数据集合

/**
 * Spring加载配置文件
 *
 * @author shadow
 */
public abstract class AbstractPropertyConfigurer extends PropertyPlaceholderConfigurer {

    private String[] decodeKeys;

    public AbstractPropertyConfigurer(String filePath, String[] decodeKeys) {
        this.decodeKeys = decodeKeys;
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource resource = resolver.getResource(filePath);
        setLocation(resource);
    }

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties properties) {
        properties = appendProperties(properties);
        properties = decodeProperties(properties);
        super.processProperties(beanFactoryToProcess, properties);
    }

    public Properties decodeProperties(Properties properties) {
        String encrypt_key = properties.getProperty("default.projectKey");
        encrypt_key = StringUtils.isEmpty(encrypt_key) ? "" : AESUtils.decrypt(encrypt_key);
        if (!StringUtils.isEmpty(decodeKeys) && decodeKeys.length > 0) {
            for (String decodeKey : decodeKeys) {
                String data = properties.getProperty(decodeKey);
                if (!StringUtils.isEmpty(data)) {
                    properties.put(decodeKey, AESUtils.decrypt(data, encrypt_key));
                }
            }
        }
        return properties;
    }

    public abstract Properties appendProperties(Properties properties);

}


默认配置类读取实现

/**
 * Spring加载配置文件
 *
 * @author shadow
 */
public class DefaultPropertyConfigurer extends AbstractPropertyConfigurer {

    public DefaultPropertyConfigurer(String filePath, String[] decodeKeys) {
        super(filePath, decodeKeys);
    }

    @Override
    public Properties appendProperties(Properties properties) {
        return properties;
    }

}

默认SpringBoot启动类实现

/**
 * Spring Boot启动类实现
 *
 * @author shadow
 */
public class DefaultServletInitializer extends SpringBootServletInitializer {

    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(getClass());
    }

    public PropertyPlaceholderConfigurer initPropertyPlaceholderConfigurer(String filePath, String[] decodeKeys) {
        if (StringUtils.isEmpty(filePath)) {
            filePath = "classpath:application.properties";
        }
        if (decodeKeys == null || decodeKeys.length == 0) {
            decodeKeys = new String[]{"spring.datasource.username", "spring.datasource.password"};
        }
        return new DefaultPropertyConfigurer(filePath, decodeKeys);
    }

}


步骤3.

Application.java 非内嵌Tomcat启动需要从该类初始化

/**
 * @author shadow
 */
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.soho"})
public class Application extends DefaultServletInitializer {

    @Bean
    public PropertyPlaceholderConfigurer initPropertyPlaceholderConfigurer() {
        return super.initPropertyPlaceholderConfigurer(null, null); // 本地启动方式
    }

}

application.properties配置参数文件

########################################################
### log
########################################################
logging.config=classpath:logback.xml
########################################################
### database
########################################################
spring.datasource.database=MySQL
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test_db
spring.datasource.username=55867b5f32a962b4d5e9e4247b21f7a5
spring.datasource.password=c1ab036d736cc8f87465b7d2d4162642
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.logSlowSql=true
spring.datasource.mgbXmlLocation=classpath*:/com/soho/demo/**/mapper/*.xml
########################################################
### spring aop
########################################################
spring.aop.auto=true
spring.aop.proxy-target-class=true
########################################################
### freemarker
########################################################
spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=/WEB-INF/ftl/
########################################################
### mybatis
########################################################
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
########################################################
### default
########################################################
default.domain=http://localhost:8011
default.projectCode=000001
default.projectKey=9a41fba77913364c4be505fcd8dab18495685ab0846fe6e88b3006dbed0daf84

步骤4.

把项目部署到Tomcat上,然后启动Tomcat容器即可,附上启动信息

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.0.RELEASE)

2018-06-19 10:53:02 INFO  com.soho.demo.Application >>> No active profile set, falling back to default profiles: default
2018-06-19 10:53:02 INFO  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext >>> Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@11a08579: startup date [Tue Jun 19 10:53:02 CST 2018]; parent: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@7099c281
2018-06-19 10:53:03 INFO  o.s.b.f.s.DefaultListableBeanFactory >>> Overriding bean definition for bean 'filterRegistrationBean' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=druidConfiguration; factoryMethodName=filterRegistrationBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/soho/spring/configuration/DruidConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.alibaba.druid.spring.boot.autoconfigure.DruidWebStatFilterConfiguration; factoryMethodName=filterRegistrationBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/alibaba/druid/spring/boot/autoconfigure/DruidWebStatFilterConfiguration.class]]
2018-06-19 10:53:03 WARN  o.m.s.mapper.ClassPathMapperScanner >>> No MyBatis mapper was found in '[com.soho.demo]' package. Please check your configuration.
2018-06-19 10:53:03 WARN  o.s.c.a.ConfigurationClassEnhancer >>> @Bean method Application.initPropertyPlaceholderConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2018-06-19 10:53:04 DEBUG c.s.s.e.DefaultPropertyConfigurer >>> Loading properties file from class path resource [application.properties]
19-Jun-2018 10:53:08.089 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [E:\apache-tomcat-8.5.30\webapps\manager]
19-Jun-2018 10:53:08.252 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [E:\apache-tomcat-8.5.30\webapps\manager] has finished in [161] ms
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$c9eb5301] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'initCacheManager' of type [com.soho.spring.cache.imp.SimpleCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'shiroDataCache' of type [com.soho.spring.shiro.cache.ShiroDataCache] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'simpleShiroCacheManager' of type [com.soho.spring.shiro.cache.SimpleShiroCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'shiroInitializeServiceImp' of type [com.soho.shiro.ShiroInitializeServiceImp] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'deftConfig' of type [com.soho.spring.model.DeftConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:09 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'shiroConfiguration' of type [com.soho.spring.configuration.ShiroConfiguration$$EnhancerBySpringCGLIB$$32876d86] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:10 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker >>> Bean 'initSecurityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-06-19 10:53:10 INFO  o.s.web.context.ContextLoader >>> Root WebApplicationContext: initialization completed in 7424 ms


本章教程主要让大家明白如何通过外部Tomcat启动我们的Spring Boot应用,以及多方式启动(zookeeper方式启动后续讲解)并扩展配置数据的加密解密操作,如果有同学喜欢本来原本的内嵌Tomcat启动方式可查看官方示例,由于比较简单我就不多说了,如上文有不明白或疑问的同学请自行仔细看看代码,如还不明白可@我解答,如我说的错误地方也可指出,先在此谢谢大家的阅读

猜你喜欢

转载自blog.csdn.net/shadowsick/article/details/80728971