由于前些日子比较忙着一些工作事情,导致没有更新连续性的教程文章,现在往后一段时间我打算写当下比较流行的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启动方式可查看官方示例,由于比较简单我就不多说了,如上文有不明白或疑问的同学请自行仔细看看代码,如还不明白可@我解答,如我说的错误地方也可指出,先在此谢谢大家的阅读