我们在软件开发的时候,为了快速开发必须搭建框架,搭建好开发就会更快,更迅速。接下来我们使用idea搭建框架。
开发工具:IDEA
开发环境:jdk1.8,gradle,springBoot,JPA,hibernate,element-ui 2.11.0等。
接下来开始搭建了。可以参考使用IDEA开发的SpringBoot项目(集成JPA并且能够自动生成javabean)
第一步:创建内容结构
结构如下:
图1:架构结构图
其中1是存储dao,entity。
其中2是存储service,controller.
其中3是存储页面。
第二步:准备相应的jdk应用包
图2:jar包
由于我们使用的是gradle,所以图2中4就是使用初始化的jar包。
apply plugin: 'java'
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
}
}
test {
java {
srcDirs = ['src/test/java']
}
resources {
srcDirs = ['src/test/resources']
}
}
}
compileJava {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
compileJava.options*.compilerArgs = [
"-Xlint:unchecked", "-Xlint:options"
]
compileTestJava {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
compileTestJava.options*.compilerArgs = [
"-Xlint:unchecked", "-Xlint:options"
]
[compileJava, compileTestJava, javadoc]*.options*.encoding = "UTF-8"
configurations {
all { config ->
config.exclude group: "org.apache.geronimo.specs"
config.exclude group: "org.jboss.spec.javax.transaction"
config.exclude group: "org.springframework.boot", module:"spring-boot-starter-logging"
config.exclude group: "org.apache.tomcat", module:"tomcat-jdbc"
config.exclude group: "com.vaadin.external.google"
config.exclude group: "com.google.code.findbugs"
resolutionStrategy.eachDependency { details ->
println details.requested.group + ":" + details.requested.name + ":" + details.requested.version
if (details.requested.group == 'org.ow2.asm' && details.requested.name == 'asm') {
details.useVersion asm_version
} else if (details.requested.group == 'org.codehaus.mojo' && details.requested.name == 'animal-sniffer-annotations') {
details.useVersion animal_sniffer_annotations_version
} else if (details.requested.group == 'org.aspectj') {
details.useVersion aspectj_version
} else if (details.requested.group == 'net.bytebuddy') {
details.useVersion bytebuddy_version
} else if (details.requested.group == 'org.checkerframework') {
details.useVersion checker_version
} else if (details.requested.group == 'com.fasterxml' && details.requested.name == 'classmate') {
details.useVersion classmate_version
} else if (details.requested.group == 'commons-codec' && details.requested.name == 'commons-codec') {
details.useVersion commons_codec_version
} else if (details.requested.group == 'commons-collections' && details.requested.name == 'commons-collections') {
details.useVersion commons_collections_version
} else if (details.requested.group == 'commons-lang' && details.requested.name == 'commons-lang') {
details.useVersion commons_lang_version
} else if (details.requested.group == 'org.apache.commons') {
if(details.requested.name == 'commons-collections4') {
details.useVersion commons_collections4_version
} else if(details.requested.name == 'commons-compress') {
details.useVersion commons_compress_version
} else if(details.requested.name == 'commons-lang3') {
details.useVersion commons_lang3_version
} else if (details.requested.name == 'commons-pool2') {
details.useVersion commons_pool2_version
}
} else if (details.requested.group == 'com.github.virtuald' && details.requested.name == 'curvesapi') {
details.useVersion curvesapi_version
} else if (details.requested.group == 'org.dom4j' && details.requested.name == 'dom4j') {
details.useVersion dom4j2_version
} else if (details.requested.group == 'com.alibaba' && details.requested.name.startsWith('druid')) {
details.useVersion druid_version
} else if (details.requested.group == 'com.google.errorprone') {
details.useVersion errorprone_version
} else if (details.requested.group == 'org.hibernate') {
if(details.requested.name == 'hibernate-validator') {
details.useVersion hibernate_validator_version
} else {
details.useVersion hibernate_version
}
} else if (details.requested.group == 'org.apache.httpcomponents') {
if(details.requested.name == 'httpclient') {
details.useVersion httpclient_version
} else if (details.requested.name == 'httpcore' || details.requested.name == 'httpcore-nio') {
details.useVersion httpcore_version
}
} else if (details.requested.group == 'com.ibm.icu') {
details.useVersion icu_version
} else if (details.requested.group.startsWith('com.fasterxml.jackson')) {
details.useVersion jackson_version
} else if (details.requested.group == 'org.javassist') {
details.useVersion javassist_version
} else if (details.requested.group == 'org.jboss' && details.requested.name == 'jandex') {
details.useVersion jboss_jandex_version
} else if (details.requested.group == 'org.jboss.logging') {
details.useVersion jboss_logging_version
} else if (details.requested.group == 'org.jdom' && details.requested.name == 'jdom2') {
details.useVersion jdom2_version
} else if (details.requested.group == 'com.google.j2objc') {
details.useVersion j2objc_version
} else if (details.requested.group == 'org.apache.logging.log4j') {
details.useVersion log4j2_version
} else if (details.requested.group == 'com.google.code.gson') {
details.useVersion gson_version
} else if (details.requested.group == 'com.google.guava') {
details.useVersion guava_version
} else if (details.requested.group == 'org.mapstruct') {
details.useVersion mapstruct_version
} else if (details.requested.group == 'org.slf4j') {
details.useVersion slf4j_version
} else if (details.requested.group == "org.yaml" && details.requested.name == "snakeyaml") {
details.useVersion snakeyaml_version
} else if (details.requested.group == 'org.springframework') {
details.useVersion spring_version
} else if (details.requested.group == 'org.springframework.boot') {
details.useVersion spring_boot_version
} else if (details.requested.group == 'org.springframework.data') {
if(details.requested.name == 'spring-data-commons') {
details.useVersion spring_data_commons_version
} else if (details.requested.name == 'spring-data-jpa') {
details.useVersion spring_data_jpa_version
} else if (details.requested.name == 'spring-data-redis') {
details.useVersion spring_data_redis_version
}
} else if (details.requested.group == 'org.springframework.session') {
details.useVersion spring_session_version
} else if (details.requested.group == "io.swagger") {
details.useVersion swagger_version
} else if (details.requested.group == 'com.geewit.core') {
if(details.requested.name == 'gw-core-utils') {
details.useVersion gw_core_utils_version
} else if (details.requested.name == 'gw-core-okhttp') {
details.useVersion gw_core_okhttp_version
} else if (details.requested.name == 'gw-core-jackson') {
details.useVersion gw_core_jackson_version
}
}
}
}
}
然后图2中5是dao层中使用的jar包。
project(':dao') {
//初始化的jar包
apply from: "${rootDir}/gradle/java.gradle"
dependencies {
compileOnly("org.springframework.boot:spring-boot-starter:$spring_boot_version")
compileOnly("org.springframework.boot:spring-boot-starter-data-jpa:$spring_boot_version")
compileOnly("org.springframework.boot:spring-boot-starter-log4j2:$spring_boot_version")
compile("org.apache.commons:commons-collections4:$commons_collections4_version")
compile("org.apache.commons:commons-lang3:$commons_lang3_version")
compile group: 'org.apache.directory.studio', name: 'org.apache.commons.io', version: '2.4'
runtime("com.alibaba:druid:1.1.9")
compile("com.alibaba:druid-spring-boot-starter:1.1.9")
compile("com.alibaba:fastjson:1.2.36")
compile("commons-codec:commons-codec:1.11")
compile("commons-io:commons-io:2.6")
compile("com.squareup.okhttp3:okhttp:3.10.0")
compile("org.springframework.boot:spring-boot-starter-jersey:$spring_boot_version")
compile("org.apache.poi:poi:$poi_version")
compile("org.apache.poi:poi-ooxml:$poi_version")
compile("com.squareup.okhttp3:okhttp:$okhttp_version")
compile group: 'org.apache.directory.studio', name: 'org.apache.commons.io', version: '2.4'
compile("org.hibernate:hibernate-envers:$hibernate_version")
compile("org.hibernate:hibernate-core:$hibernate_version")
compile("org.hibernate:hibernate-ehcache:$hibernate_version")
compileOnly("io.springfox:springfox-swagger2:$springfox_version")
compileOnly("io.springfox:springfox-swagger-ui:$springfox_version")
/* compile("us.codecraft:webmagic-extension:0.7.3")
compile("us.codecraft:webmagic-core:0.7.3")*/
}
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
}
}
}
}
图2中3是service层和controller层中的jar包。
buildscript{
repositories {
mavenLocal()
//mavenCentral()
//jcenter()
maven { url "http://repo1.maven.org/maven2" }
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.13.RELEASE")
}
}
project(':server'){
apply plugin: 'org.springframework.boot'
apply from: "${rootDir}/gradle/java.gradle"
dependencies {
compile(project(":dao"))
runtime("com.alibaba:druid:1.1.9")
compile("com.alibaba:druid-spring-boot-starter:1.1.9")
compile("com.alibaba:fastjson:1.2.36")
compile("commons-codec:commons-codec:1.11")
compile("org.apache.commons:commons-collections4:4.1")
compile("commons-io:commons-io:2.6")
compile("org.apache.commons:commons-lang3:3.7")
compile("com.google.guava:guava:23.6-jre")
compile("com.squareup.okhttp3:okhttp:3.10.0")
compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework.boot:spring-boot-starter-cache')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-log4j2')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-validation')
compile('org.springframework.boot:spring-boot-starter-mail:1.5.13.RELEASE')
compile("io.springfox:springfox-swagger2:2.9.2")
compile("io.springfox:springfox-swagger-ui:2.9.2")
compile("org.hibernate:hibernate-envers:5.2.17.Final")
compile("org.hibernate:hibernate-core:5.2.17.Final")
//compile("org.hibernate:hibernate-core:4.1.2.Final")
compile("org.hibernate:hibernate-ehcache:5.2.17.Final")
compile("org.antlr:antlr4:4.7.1")
runtime("mysql:mysql-connector-java")
//用于生成验证码
compile("com.github.penggle:kaptcha:2.3.2")
//下面两个POI和pdfbox的jar包,是进行excel导入导出操作
compile("org.apache.poi:poi:$poi_version")
compile("org.apache.poi:poi-ooxml:$poi_version")
compile("org.apache.pdfbox:pdfbox:$pdfbox_version")
compile("org.apache.pdfbox:pdfbox-tools:$pdfbox_version")
compile group: 'org.apache.velocity', name: 'velocity', version: '1.7'
compile group: 'commons-configuration', name: 'commons-configuration', version: '1.10'
//该jar包是使用jwt来生辰token
compile group: 'com.auth0', name: 'java-jwt', version: '3.3.0'
compile group: 'org.apache.commons', name: 'commons-text', version: '1.8'
//該jar包是处理根据ip查询物理地址
compile group: 'org.lionsoul', name: 'ip2region', version: '1.7.2'
}
jar {
destinationDir = file("${rootProject.buildDir}")
archiveName = "${rootProject.name}.jar"
if(file("${rootDir}/ui/dist").exists()) {
from("${rootDir}/ui/dist") {
into 'META-INF/resources'
}
}
}
bootRun.systemProperty 'spring.profiles.active', 'development'
springBoot {
backupSource = false
executable = false
}
}
图2中2整个系统启动时候使用的jar包
allprojects{
group 'com.zhm'
version '1.0'
buildDir='target'
}
apply plugin: "idea"
subprojects{
configurations{
repositories{
maven { url "http://repo1.maven.org/maven2" }
maven { url "https://plugins.gradle.org/m2/" }
}
}
idea{
module{
excludeDirs=[file(".gradle")]
excludeDirs+=file("gradle")
excludeDirs+=file(".idea")
}
}
}
task run{
doFirst{
println 'run start'
}
doLast{
println 'run last'
}
}
run.dependsOn(':ui:runDev')
run.dependsOn(':server:bootRun')
task build{
doFirst{
println 'build start'
}
doLast{
println 'build last'
}
}
build.dependsOn(':server:bootRepackage')
图2中1是使用jar包的版本
version=1.0.0
systemProp.file.encoding=UTF-8
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true
#quiet, warn, lifecycle, info, or debug
org.gradle.logging.level = info
org.gradle.jvmargs=-Xms512M -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
gradle_node_version = 1.2.0
animal_sniffer_annotations_version = 1.16
antlr4_version = 4.7.1
asm_version = 6.1.1
aspectj_version = 1.9.1
bytebuddy_version = 1.8.11
checker_version = 2.5.1
classmate_version = 1.4.0
curvesapi_version = 1.06
commons_codec_version = 1.11
commons_collections_version = 3.2.2
commons_collections4_version = 4.1
commons_compress_version = 1.16.1
commons_lang_version = 2.6
commons_lang3_version = 3.7
commons_pool2_version = 2.5.0
commons_io_version = 2.6
dom4j2_version = 2.1.0
druid_version = 1.1.9
ehcache_version = 2.10.5
errorprone_version = 2.3.1
glassfish_javax_json_version = 1.1.2
guava_version = 25.0-jre
hibernate_version = 5.2.17.Final
hibernate_validator_version = 5.4.2.Final
hk2_version = 2.5.0-b61
httpclient_version = 4.5.5
httpcore_version = 4.4.9
icu_version = 61.1
javax_ws_rs_api_version=2.1
jackson_version = 2.9.5
javassist_version = 3.22.0-GA
javax_servlet_api_version = 3.1.0
jboss_jandex_version = 2.0.5.Final
jboss_logging_version = 3.3.2.Final
jboss_threads_version = 2.3.2.Final
jboss_xnio_version = 3.6.3.Final
jdom2_version = 2.0.6
jersey_version = 2.27
junit_version = 4.12
j2objc_version = 1.3
log4j2_version = 2.11.0
mapstruct_version = 1.2.0.Final
mysql_version = 5.1.46
okhttp_version = 3.10.0
okio_version = 1.14.1
slf4j_version = 1.7.25
snakeyaml_version = 1.21
spring_version = 4.3.17.RELEASE
spring_boot_version = 1.5.13.RELEASE
spring_data_commons_version = 1.13.12.RELEASE
spring_data_jpa_version = 1.11.12.RELEASE
spring_data_redis_version = 1.8.12.RELEASE
spring_session_version = 1.3.3.RELEASE
springfox_version = 2.9.2
swagger_version = 1.5.19
fastjson_version = 1.2.47
commons_fileupload_version = 1.3.3
pdfbox_version = 2.0.8
gw_core_jackson_version = 1.0.9
gw_core_okhttp_version = 1.1.0
gw_core_utils_version = 1.0.33
essential_jpa_version = 1.3.10
spring_boot_oss_version = 2.4.0
spring_data_envers_version = 1.1.20
spring_boot_starter_authority_version = 1.3.12
spring_boot_starter_aliyun_oss_version = 1.3.17
spring_boot_http_version=4.5.3
spring_boot_starter_jdbc_version = 1.0.4
spring_boot_starter_jpa_version = 1.3.24
spring_boot_starter_nashorn_version = 1.0.5
spring_boot_starter_stringtemplate_version = 1.0.6
module_actionlog_version = 1.0.0
module_attachment_version = 1.0.3
undertow_version = 2.0.7.Final
unbescape_version = 1.1.6.RELEASE
wildfly_common_version = 1.4.0.Final
poi_version = 3.17
joda_time_version = 2.9.9
如上面,这样jar包就准备好了。
第三步:准备相应的配置
其中config是配置文件,包括接口配置,定时任务,Redis配置,参数配置,验证码配置。
KaptchaConfig是验证码的配置,这个需要相应的kaptcha的jar包。
compile("com.github.penggle:kaptcha:2.3.2")
KaptchaConfig.java
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Properties;
/**
* 验证码
*/
@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha(){
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.image.width", "110");
properties.setProperty("kaptcha.image.height", "40");
properties.setProperty("kaptcha.textproducer.font.size", "30");
properties.setProperty("kaptcha.session.key", "code");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
MvcConfig是配置,如图片地址参数,分页设置等
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.data.web.SortHandlerMethodArgumentResolver;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.List;
/**
* Created by 赵红明 on 2019/6/14.
*/
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
private static Logger logger= LoggerFactory.getLogger(MvcConfig.class);
@Autowired
private Environment environment;
/**
* 分页设置
* @param argumentResolvers
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
SortHandlerMethodArgumentResolver sortArgumentResolver = new SortHandlerMethodArgumentResolver();
sortArgumentResolver.setPropertyDelimiter(",");
argumentResolvers.add(sortArgumentResolver);
PageableHandlerMethodArgumentResolver pageableArgumentResolver = new PageableHandlerMethodArgumentResolver(sortArgumentResolver);
pageableArgumentResolver.setPageParameterName("page");
pageableArgumentResolver.setSizeParameterName("size");
pageableArgumentResolver.setOneIndexedParameters(true);
argumentResolvers.add(pageableArgumentResolver);
super.addArgumentResolvers(argumentResolvers);
}
/**
*图片等地址映射
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
logger.info("pdfURL="+environment.getProperty("service.addrss"));
registry.addResourceHandler("/pdf/**").addResourceLocations("file:"+environment.getProperty("service.addrss"));
super.addResourceHandlers(registry);
}
@Bean
public CommonsRequestLoggingFilter requestLoggingFilter() {
CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
loggingFilter.setMaxPayloadLength(2048);
loggingFilter.setIncludeClientInfo(true);
loggingFilter.setIncludeQueryString(true);
loggingFilter.setIncludePayload(true);
loggingFilter.setIncludeHeaders(true);
return loggingFilter;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
RedisConfig是Redis的配置
package com.zhm.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
/**
* @author huangfang
* @since 2017-04-07
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private final static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
private static String generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append('.');
sb.append(method.getName());
for (Object param : params) {
sb.append('.');
sb.append(param.toString());
}
return sb.toString();
}
@Bean
public KeyGenerator wiselyKeyGenerator(){
return RedisConfig::generate;
}
@Bean
public CacheManager cacheManager(@Qualifier("redisTemplate") RedisTemplate<String, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//cacheManager.setDefaultExpiration(3000);
return cacheManager;
}
/**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
* @param factory
* @return
*/
@Bean("redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory, ObjectMapper existsObjectMapper) {
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = existsObjectMapper.copy();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
ScheduledConfig是定时任务的配置
package com.zhm.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Created by 赵红明 on 2019/5/30.
* 配置定时任务,如果不配置,设置的定时任务就没法启动
*/
@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
/**ScheduleTimer
* 设置定时任务的线程(四种线程池)
* @return
*/
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
//1:固定大小线程池: 设置固定值会造成高并发线程排队等待空闲线程,尤其是当读取大数据量时线程处理时间长而不释放线程,导致无法创建新线程。
//Executors.newFixedThreadPool(10);
//2:可缓存线程池 线程池无限大,而系统资源(内存等)有限,会导致机器内存溢出OOM。
//Executors.newCachedThreadPool();
//3:定长且可定时、周期线程池
//Executors.newScheduledThreadPool(5);
//4:单线程线程池
//Executors.newSingledThreadPool();
return Executors.newScheduledThreadPool(5);
}
}
Swagger2Config是swagger-ui的配置
package com.zhm.config;
import com.google.common.base.Predicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 查看接口Swagger-ui设置
* Created by 赵红明 on 2019/5/27.
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Autowired
private Environment environment;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(selector())
.paths(PathSelectors.any())
.build();
}
private Predicate<RequestHandler> selector() {
// return RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class);
return RequestHandlerSelectors.basePackage("com.zhm.controller");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description(environment.getProperty("spring.application.name", "spring boot application"))
.termsOfServiceUrl("http://www.zhaohongming.cn")
.contact(new Contact("赵红明", "http://www.zhaohongming.cn", "hongming.zhao@seedeer.com"))
.version(environment.getProperty("spring.application.version", "1.0.0"))
.build();
}
}
LoginFilter是过滤器,过滤掉一些接口需要处理的问题。如什么样接口要校验等
package com.zhm.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.zhm.util.*;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.util.ResourceUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.WebUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Created by 赵红明 on 2019/6/27.
*
* filterName的首字母一定要小写!!!小写!!!小写!!!
* 如果不小写,会导致配置的多个过滤器拦截url都失效了
*/
@WebFilter(urlPatterns = {"/api/*"}, filterName = "loginFilter")
public class LoginFilter implements Filter {
private static Logger logger= LoggerFactory.getLogger(LoginFilter.class);
private final Environment environment;
private final StringRedisTemplate redisTemplate;
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
/**
* 记录那些方法需要token
*/
private Map<RequestMappingInfo, HandlerMethod> ignoredRequestMappingInfoMap;
private String HTML_403;
public LoginFilter(Environment environment,StringRedisTemplate redisTemplate){
this.environment=environment;
this.redisTemplate=redisTemplate;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("LoginFilter----init----");
/* Map<RequestMappingInfo, HandlerMethod> allRequestMappingInfoMap = requestMappingHandlerMapping.getHandlerMethods();
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : allRequestMappingInfoMap.entrySet()) {
HandlerMethod handlerMethod = entry.getValue();
boolean hasIgnoreFilter = handlerMethod.hasMethodAnnotation(TokenFilter.class);
if (hasIgnoreFilter) {
if (ignoredRequestMappingInfoMap == null) {
ignoredRequestMappingInfoMap = Maps.newConcurrentMap();
}
ignoredRequestMappingInfoMap.put(entry.getKey(), entry.getValue());
}
}*/
logger.info("getFilterName:"+filterConfig.getFilterName());//返回<filter-name>元素的设置值。
logger.info("getServletContext:"+filterConfig.getServletContext());//返回FilterConfig对象中所包装的ServletContext对象的引用。
logger.info("getInitParameter:"+filterConfig.getInitParameter("cacheTimeout"));//用于返回在web.xml文件中为Filter所设置的某个名称的初始化的参数值
logger.info("getInitParameterNames:"+filterConfig.getInitParameterNames());//返回一个Enum
try {
HTML_403 = FileUtils.readFileToString(ResourceUtils.getFile("classpath*:403.html"), StandardCharsets.UTF_8);
} catch (IOException e) {
logger.warn(e.getMessage());
HTML_403 = "<!DOCTYPE html><html><head><title>403 Forbidden</title></head><body><div style=\"text-align: center;\"><h1>403 Forbidden</h1></div><hr><div style=\"text-align: center;\">Permission denied</div></body></html>";
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("LoginFilter----doFilter----");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String servletPath = httpServletRequest.getServletPath();
/* HandlerExecutionChain handlerExecutionChain = null;
try {
handlerExecutionChain = requestMappingHandlerMapping.getHandler(httpServletRequest);
} catch (Exception e) {
logger.info(e.getMessage(), e);
}*/
logger.debug("servletPath : " + servletPath);
//如果是登录页面则不需要拦截
if(servletPath.contains("/api/login")){
chain.doFilter(request, response);
return;
}
//验证码不需要拦截
if(servletPath.contains("/api/defaultKaptcha")){
chain.doFilter(request, response);
return;
}
//接口类不拦截 但是要校验token是否存在
if(servletPath.contains("/api/interface")){
/*boolean isIgnore = ignore(handlerExecutionChain);
if (!isIgnore) {
chain.doFilter(request, response);
return;
}else{
String token = httpServletRequest.getHeader("access_token");
//token不存在
if (null != token) {
//验证token是否正确
boolean result = JwtUtil.verify(token);
if (!result) {
logger.info("jwt token 没有校验失败!");
this.sendTokenJson(response,JSONObject.parseObject(JSONObject.toJSONString(Result.failure("jwt token 没有校验失败!"))));
return;
}
}else{
logger.info("jwt token 不存在!");
this.sendTokenJson(response,JSONObject.parseObject(JSONObject.toJSONString(Result.failure("jwt token 不存在!"))));
return;
}
}*/
chain.doFilter(request, response);
return;
}
//登录页面
String loginUrl=environment.getProperty("systemmodel.authority.login_url");
//cookie
String cookieName= environment.getProperty("systemmodel.authority.default.cookie_name");
Cookie cookie = WebUtils.getCookie(httpServletRequest, cookieName);
if(cookie!=null){
logger.info("cookie found");
}else{
logger.info("cookie not found");
httpServletResponse.sendRedirect(loginUrl);
return;
}
String loginToken = cookie.getValue();
logger.debug("loginToken : " + loginToken);
Map<String, Object> userInfo=new HashMap<String, Object>();
String redisName=environment.getProperty("systemmodel.user.info")+loginToken;
try {
userInfo = this.getUserInfo(redisName);
LoginUser loginUser=new LoginUser();
loginUser.setUserId(Integer.parseInt(userInfo.get("userId").toString()));
loginUser.setUserName(userInfo.get("userName").toString());
if(userInfo.get("avataUrl")!=null){
loginUser.setAvataUrl(userInfo.get("avataUrl").toString());
}else{
loginUser.setAvataUrl("");
}
loginUser.setExpires(userInfo.get("expires").toString());
AuthorityUtils.setCurrentUser(loginUser);
} catch (Exception e) {
logger.info("redisName not exist");
httpServletResponse.sendRedirect(loginUrl);
return;
}
if (userInfo == null) {
logger.info("user info not exist");
httpServletResponse.sendRedirect(loginUrl);
return;
}
chain.doFilter(request, response);
}
public Map<String,Object> getUserInfo(String loginToken){
String userInfoJson = redisTemplate.opsForValue().get(loginToken);
logger.debug("redis.userInfoJson : " + userInfoJson);
if(userInfoJson!=null){
Map<String,Object> map= JsonUtil.fromJson(userInfoJson, new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {});
if(map!=null){
return map;
}
}
return null;
}
private void TokenErrorHtml(HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(MediaType.TEXT_HTML_VALUE);
response.getWriter().write(HTML_403);
}
private boolean ignore(HandlerExecutionChain handlerExecutionChain) {
HandlerMethod handler;
try {
if(handlerExecutionChain == null) {
return false;
}
handler = (HandlerMethod) handlerExecutionChain.getHandler();
if (handler == null) {
return false;
}
} catch (Exception ignore) {
return false;
}
if(ignoredRequestMappingInfoMap != null && !ignoredRequestMappingInfoMap.isEmpty()) {
Collection<HandlerMethod> handlerMethods = ignoredRequestMappingInfoMap.values();
for (HandlerMethod handlerMethod : handlerMethods) {
if (handler.getBeanType().equals(handlerMethod.getBeanType()) && handler.getMethod().equals(handlerMethod.getMethod())) {
return true;
}
}
}
return false;
}
@Override
public void destroy() {
logger.info("LoginFilter----destroy----");
}
private void sendTokenJson(ServletResponse response, JSONObject menuJson) throws IOException {
PrintWriter out = setPrintWriter(response);
out.print(menuJson);
out.flush();
out.close();
}
private PrintWriter setPrintWriter(ServletResponse response) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json; charset=utf-8");
httpResponse.setStatus(HttpServletResponse.SC_OK);
return response.getWriter();
}
}
InitParamStartupRunner是项目正在启动的时候启动的一些内容。
package com.zhm.interceptor;
import com.alibaba.fastjson.JSON;
import com.zhm.dto.AddressDto;
import com.zhm.entity.ParamDetail;
import com.zhm.entity.Params;
import com.zhm.service.ParamService;
import com.zhm.service.SysAreaService;
import com.zhm.util.Constants;
import com.zhm.util.DateUtil;
import com.zhm.util.JsonUtil;
import com.zhm.util.PropertiesUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* Created by 赵红明 on 2019/6/24.
* 项目启动数据初始化拦截器
*
*/
@Component
public class InitParamStartupRunner implements CommandLineRunner {
private static Logger logger= LoggerFactory.getLogger(InitParamStartupRunner.class);
@Autowired
private ParamService paramService;
@Autowired
private StringRedisTemplate rt;
@Autowired
private SysAreaService sysAreaService;
@Override
public void run(String... args) throws Exception {
/**
* 用于项目启动的时候一些数据的初始化,比如系统参数存储在redis中。
*/
//所有主参数
List<Params> paramsList = paramService.findAll();
logger.info("主参数"+ JsonUtil.toJson(paramsList));
saveParamsToRedis(paramsList);
// 所有子参
List<ParamDetail> paramDetails = paramService.findAllDetails();
logger.info("子参数"+ JsonUtil.toJson(paramDetails));
saveParamsDetailToRedis(paramDetails);
//省市县信息初始化
List<AddressDto> addressDtos=sysAreaService.getAddress();
logger.info("地址信息"+ JsonUtil.toJson(addressDtos));
saveAddress(addressDtos);
logger.info("当前项目启动时间是: {}", DateUtil.dateToString(new Date()));
}
/**
* 总参 存在redis中
*
* @return void
* @throws
* @author bob
* @Param [paramsList]
* @date 2018/6/15 16:20
*/
private void saveParamsToRedis(List<Params> paramsList) {
if (CollectionUtils.isNotEmpty(paramsList)) {
HashMap<String, String> map = new HashMap<>(paramsList.size());
Params params;
for (int i = 0; i < paramsList.size(); i++) {
params = paramsList.get(i);
map.put(params.getParamCode(), JSON.toJSONString(params));
}
rt.opsForHash().putAll(PropertiesUtil.getRedisPrefixKey() + Constants.PARENT_PARAMS, map);
}
}
private void saveAddress(List<AddressDto> addressDtos){
if (CollectionUtils.isNotEmpty(addressDtos)) {
String redisKey = PropertiesUtil.getRedisPrefixKey() + Constants.address_local;
rt.opsForValue().set(redisKey, JSON.toJSONString(addressDtos));
}
}
/**
* 子参 存在redis中
*
* @return void
* @throws
* @author bob
* @Param [paramDetails]
* @date 2018/6/15 16:20
*/
private void saveParamsDetailToRedis(List<ParamDetail> paramDetails) {
if (CollectionUtils.isNotEmpty(paramDetails)) {
ParamDetail paramDetail;
Map<String, Map<String, String>> mapHashMap = new HashMap<>();
Map<String, String> map;
String detailCode;
String redisKey;
for (int i = 0; i < paramDetails.size(); i++) {
paramDetail = paramDetails.get(i);
detailCode = paramDetail.getParamDetailCode();
redisKey = PropertiesUtil.getRedisPrefixKey() + Constants.SON_PARAMS + paramDetail.getParamCode();
map = mapHashMap.get(redisKey);
if (MapUtils.isEmpty(map)) {
map = new LinkedHashMap<>();
}
map.put(detailCode, JSON.toJSONString(paramDetail));
mapHashMap.put(redisKey, map);
}
saveMapToRedis(mapHashMap);
}
}
/**
* 先清缓存再插入
* @author bob
* @Param [mapHashMap]
* @return void
* @exception
* @date 2018/6/15 17:59
*/
private void saveMapToRedis(Map<String,Map<String,String>> mapHashMap) {
mapHashMap.forEach((key, value) ->{
rt.delete(key);
rt.opsForHash().putAll(key, value);
});
}
}
最后,还需要Bootstrap的启动类。
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* Created by 赵红明 on 2019/6/25.
*/
@SpringBootApplication(scanBasePackages = {"com.zhm"})//扫描包
@EnableJpaRepositories(basePackages = {"com.zhm.**.dao"})//扫描dao层
@EntityScan(basePackages = {"com.zhm.**.entity"})
@PropertySource("classpath:env/${spring.profiles.active}/application.properties")//启动后饮用参数
@EnableSpringDataWebSupport
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableAsync
@ServletComponentScan//Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。
public class Bootstrap {
public static void main(String[] args){
SpringApplication.run(Bootstrap.class);
}
}