Commit 65872f90 by giaogiao

init

parents
/target/
/classes
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
.DS_Store
*.log
logs
*.rdb
/admin/src/main/resources/rebel.xml
/bootstrap/src/main/resources/rebel.xml
/config/src/main/resources/rebel.xml
/distribution/src/main/resources/rebel.xml
/example/src/main/resources/rebel.xml
/framework/src/main/resources/rebel.xml
/generator/src/main/resources/rebel.xml
/scheduled/src/main/resources/rebel.xml
/service/src/main/resources/rebel.xml
/admin/src/main/resources/rebel.xml
*/.rebel.xml.bak
*/rebel.xml
/server/src/main/resources/rebel.xml
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
# 卓美亚航空 - 后端项目
## 框架介绍
> 本项目使用第三方开源脚手架项目: spring-boot-plus
> 参考:README-zh.md
\ No newline at end of file
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
/src/main/resources/rebel.xml
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Spring Security](https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#boot-features-security)
* [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#production-ready)
* [Spring Boot Admin (Client)](https://codecentric.github.io/spring-boot-admin/current/#getting-started)
* [Spring Boot Admin (Server)](https://codecentric.github.io/spring-boot-admin/current/#getting-started)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>parent</artifactId>
<version>2.0</version>
</parent>
<artifactId>admin</artifactId>
<name>admin</name>
<description>Spring Boot Admin Server</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring-boot-admin.version}</version>
<exclusions>
<exclusion>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-cloud</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.admin;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* Spring Boot Admin 启动类
*
* @author geekidea
* @date 2020/3/20
**/
@Slf4j
@Configuration
@EnableAutoConfiguration
@EnableAdminServer
@SpringBootApplication
public class SpringBootPlusAdminApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootPlusAdminApplication.class, args);
ConfigurableEnvironment environment = context.getEnvironment();
String serverPort = environment.getProperty("server.port");
log.info("SpringBootAdmin: http://localhost:" + serverPort);
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.admin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* WebMvc配置
*
* @author geekidea
* @date 2020/3/19
*/
@Configuration
public class AdminWebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 设置项目静态资源访问
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.admin.config;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.util.UUID;
/**
* Spring Boot Admin Security配置
* https://codecentric.github.io/spring-boot-admin/current/#_securing_spring_boot_admin_server
*
* @author geekidea
* @date 2020/3/20
*/
@Configuration(proxyBeanMethods = false)
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final AdminServerProperties adminServer;
@Value("${spring-boot-plus.admin.username}")
private String username;
@Value("${spring-boot-plus.admin.password}")
private String password;
public SecuritySecureConfig(AdminServerProperties adminServer) {
this.adminServer = adminServer;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(this.adminServer.path("/"));
http.authorizeRequests(
(authorizeRequests) -> authorizeRequests
.antMatchers(this.adminServer.path("/assets/**")).permitAll()
.antMatchers(this.adminServer.path("/static/**")).permitAll()
.antMatchers(this.adminServer.path("/login")).permitAll()
.anyRequest().authenticated()
).formLogin(
(formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and()
).logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout"))).httpBasic(Customizer.withDefaults())
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
new AntPathRequestMatcher(this.adminServer.path("/instances"),
HttpMethod.POST.toString()),
new AntPathRequestMatcher(this.adminServer.path("/instances/*"),
HttpMethod.DELETE.toString()),
new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))
))
.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(username).password("{noop}" + password).roles("USER");
}
}
\ No newline at end of file
server:
port: 8000
# Spring Boot Admin Server配置
spring:
boot:
admin:
monitor:
period: 100000
status-lifetime: 100000
connect-timeout: 100000
read-timeout: 100000
ui:
external-views:
- label: "🚀"
url: https://springboot.plus
order: 2000
# Spring Boot Admin 登录账号密码
spring-boot-plus:
admin:
username: admin
password: admin
/target/
/classes
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
.DS_Store
*.log
logs
*.rdb
# bootstrap 项目启动模块
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>parent</artifactId>
<version>2.0</version>
</parent>
<artifactId>bootstrap</artifactId>
<name>bootstrap</name>
<description>项目启动模块</description>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>framework</artifactId>
</dependency>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>example</artifactId>
</dependency>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>server</artifactId>
</dependency>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>scheduled</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus;
import io.geekidea.springbootplus.framework.util.PrintApplicationInfo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* spring-boot-plus 项目启动入口
*
* @author geekidea
* @since 2018-11-08
*/
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@EnableConfigurationProperties
@ServletComponentScan
@MapperScan({"io.geekidea.springbootplus.**.mapper", "com.example.**.mapper"})
@SpringBootApplication(scanBasePackages = {"io.geekidea.springbootplus", "com.example"})
public class SpringBootPlusApplication {
public static void main(String[] args) {
// 启动spring-boot-plus
ConfigurableApplicationContext context = SpringApplication.run(SpringBootPlusApplication.class, args);
// 打印项目信息
PrintApplicationInfo.print(context);
// 打印项目提示
PrintApplicationInfo.printTip(context);
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.aop;
import io.geekidea.springbootplus.framework.log.aop.BaseLogAop;
import io.geekidea.springbootplus.framework.log.bean.OperationLogInfo;
import io.geekidea.springbootplus.framework.log.bean.RequestInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
* <p>
* Controller Aop
* 获取响应结果信息
* </p>
*
* @author geekidea
* @date 2019-10-23
*/
@Slf4j
@Aspect
@Component
@ConditionalOnProperty(value = {"spring-boot-plus.aop.log.enable"}, matchIfMissing = true)
public class LogAop extends BaseLogAop {
/**
* 切点
*/
private static final String POINTCUT =
"execution(public * io.geekidea.springbootplus..*.controller..*.*(..)) || " +
"execution(public * com.example..*.controller..*.*(..))";
@Around(POINTCUT)
@Override
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
return super.handle(joinPoint);
}
@AfterThrowing(pointcut = POINTCUT, throwing = "exception")
@Override
public void afterThrowing(JoinPoint joinPoint, Exception exception) {
super.handleAfterThrowing(exception);
}
@Override
protected void setRequestId(RequestInfo requestInfo) {
super.handleRequestId(requestInfo);
}
@Override
protected void getRequestInfo(RequestInfo requestInfo) {
// 处理请求参数日志
super.handleRequestInfo(requestInfo);
}
@Override
protected void getResponseResult(Object result) {
// 处理响应结果日志
super.handleResponseResult(result);
}
@Override
protected void finish(RequestInfo requestInfo, OperationLogInfo operationLogInfo, Object result, Exception exception) {
// 异步保存操作日志
super.saveSysOperationLog(requestInfo, operationLogInfo, result, exception);
// 异步保存登录日志
super.saveSysLoginLog(requestInfo, operationLogInfo, result, exception);
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import io.geekidea.springbootplus.config.constant.DatePattern;
import io.geekidea.springbootplus.framework.config.jackson.deserializer.JacksonDateDeserializer;
import io.geekidea.springbootplus.framework.config.jackson.deserializer.JacksonDoubleDeserializer;
import io.geekidea.springbootplus.framework.config.jackson.serializer.JacksonDateSerializer;
import io.geekidea.springbootplus.framework.config.jackson.serializer.JacksonIntegerDeserializer;
import io.geekidea.springbootplus.framework.core.xss.XssJacksonDeserializer;
import io.geekidea.springbootplus.framework.core.xss.XssJacksonSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
/**
* @author geekidea
* @author 2018-11-08
*/
@Configuration
public class JacksonConfig implements WebMvcConfigurer {
@Value("${spring-boot-plus.filter.xss.enable}")
private boolean enableXss;
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
// objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
SimpleModule simpleModule = new SimpleModule();
// Long类型序列化成字符串,避免Long精度丢失
// simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
// simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
// XSS序列化
if (enableXss) {
simpleModule.addSerializer(String.class, new XssJacksonSerializer());
simpleModule.addDeserializer(String.class, new XssJacksonDeserializer());
}
// Date
// simpleModule.addSerializer(Date.class, new JacksonDateSerializer());
// simpleModule.addDeserializer(Date.class, new JacksonDateDeserializer());
simpleModule.addDeserializer(Integer.class, new JacksonIntegerDeserializer());
simpleModule.addDeserializer(Double.class, new JacksonDoubleDeserializer());
// jdk8日期序列化和反序列化设置
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.HH_MM_SS)));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.HH_MM_SS)));
objectMapper.registerModule(simpleModule).registerModule(javaTimeModule).registerModule(new ParameterNamesModule());
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
//放到第一个
converters.add(0, jackson2HttpMessageConverter);
}
}
\ No newline at end of file
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>
* MybatisPlus配置
* </p>
*
* @author geekidea
* @since 2018-11-08
*/
@Configuration
public class MybatisPlusConfig {
/**
* mybatis-plus分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
/**
* mybatios-plus乐观锁插件
*
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
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.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* <p>
* Redis Cache配置
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuffer redisKey = new StringBuffer();
redisKey.append(target.getClass().getName()).append("-");
redisKey.append(method.getName());
if (params.length > 0) {
redisKey.append("-").append(Arrays.deepToString(params));
}
return redisKey.toString();
};
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置
// 过期时间5分钟
config = config.entryTtl(Duration.ofMinutes(5));
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("my-redis-cache1");
cacheNames.add("my-redis-cache2");
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>(10);
configMap.put("my-redis-cache1", config);
configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
// 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
// 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* <p>
* Redis Template 配置
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 自定义的string序列化器和fastjson序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// jackson 序列化器
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// kv 序列化
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jsonRedisSerializer);
// hash 序列化
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* @author geekidea
* @date 2018-11-08
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//单位为ms
factory.setReadTimeout(5000);
//单位为ms
factory.setConnectTimeout(5000);
return factory;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import lombok.extern.slf4j.Slf4j;
/**
* spring-boot-plus配置
*
* @author geekidea
* @date 2019/8/4
* @since 1.2.0-RELEASE
*/
@Slf4j
public class SpringBootPlusConfig {
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import io.geekidea.springbootplus.config.properties.SpringBootPlusCorsProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域配置
*
* @author geekidea
* @date 2019/10/14
*/
@Slf4j
@Configuration
@ConditionalOnProperty(value = {"spring-boot-plus.cors.enable"}, matchIfMissing = true)
public class SpringBootPlusCorsConfig {
/**
* CORS跨域设置
*
* @return
*/
@Bean
public FilterRegistrationBean corsFilter(SpringBootPlusCorsProperties corsProperties) {
log.debug("corsProperties:{}", corsProperties);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 跨域配置
corsConfiguration.setAllowedOrigins(corsProperties.getAllowedOrigins());
corsConfiguration.setAllowedHeaders(corsProperties.getAllowedHeaders());
corsConfiguration.setAllowedMethods(corsProperties.getAllowedMethods());
corsConfiguration.setAllowCredentials(corsProperties.isAllowCredentials());
corsConfiguration.setExposedHeaders(corsProperties.getExposedHeaders());
corsConfiguration.setMaxAge(corsConfiguration.getMaxAge());
source.registerCorsConfiguration(corsProperties.getPath(), corsConfiguration);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
bean.setEnabled(corsProperties.isEnable());
return bean;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config;
import com.alibaba.fastjson.JSON;
import io.geekidea.springbootplus.config.properties.SpringBootPlusFilterProperties;
import io.geekidea.springbootplus.config.properties.SpringBootPlusInterceptorProperties;
import io.geekidea.springbootplus.config.properties.SpringBootPlusProperties;
import io.geekidea.springbootplus.framework.core.filter.RequestDetailFilter;
import io.geekidea.springbootplus.framework.core.interceptor.PermissionInterceptor;
import io.geekidea.springbootplus.framework.core.xss.XssFilter;
import io.geekidea.springbootplus.framework.util.IniUtil;
import io.geekidea.springbootplus.system.interceptor.DownloadInterceptor;
import io.geekidea.springbootplus.system.interceptor.ResourceInterceptor;
import io.geekidea.springbootplus.system.interceptor.UploadInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.PostConstruct;
import java.util.Map;
/**
* WebMvc配置
*
* @author geekidea
* @date 2018-11-08
*/
@Slf4j
@Configuration
public class SpringBootPlusWebMvcConfig implements WebMvcConfigurer {
/**
* spring-boot-plus配置属性
*/
@Autowired
private SpringBootPlusProperties springBootPlusProperties;
/**
* Filter配置
*/
private SpringBootPlusFilterProperties filterConfig;
/**
* 拦截器配置
*/
private SpringBootPlusInterceptorProperties interceptorConfig;
/**
* RequestDetailFilter配置
*
* @return
*/
@Bean
public FilterRegistrationBean requestDetailFilter() {
SpringBootPlusFilterProperties.FilterConfig requestFilterConfig = filterConfig.getRequest();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new RequestDetailFilter());
filterRegistrationBean.setEnabled(requestFilterConfig.isEnable());
filterRegistrationBean.addUrlPatterns(requestFilterConfig.getUrlPatterns());
filterRegistrationBean.setOrder(requestFilterConfig.getOrder());
filterRegistrationBean.setAsyncSupported(requestFilterConfig.isAsync());
return filterRegistrationBean;
}
/**
* XssFilter配置
*
* @return
*/
@Bean
public FilterRegistrationBean xssFilter() {
SpringBootPlusFilterProperties.FilterConfig xssFilterConfig = filterConfig.getXss();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new XssFilter());
filterRegistrationBean.setEnabled(xssFilterConfig.isEnable());
filterRegistrationBean.addUrlPatterns(xssFilterConfig.getUrlPatterns());
filterRegistrationBean.setOrder(xssFilterConfig.getOrder());
filterRegistrationBean.setAsyncSupported(xssFilterConfig.isAsync());
return filterRegistrationBean;
}
/**
* 自定义权限拦截器
*
* @return
*/
@Bean
public PermissionInterceptor permissionInterceptor() {
return new PermissionInterceptor();
}
/**
* 上传拦截器
*
* @return
*/
@Bean
public UploadInterceptor uploadInterceptor() {
return new UploadInterceptor();
}
/**
* 资源拦截器
*
* @return
*/
@Bean
public ResourceInterceptor resourceInterceptor() {
return new ResourceInterceptor();
}
/**
* 下载拦截器
*
* @return
*/
@Bean
public DownloadInterceptor downloadInterceptor() {
return new DownloadInterceptor();
}
@PostConstruct
public void init() {
filterConfig = springBootPlusProperties.getFilter();
interceptorConfig = springBootPlusProperties.getInterceptor();
// 打印SpringBootPlusProperties配置信息
log.debug("SpringBootPlusProperties:{}", JSON.toJSONString(springBootPlusProperties));
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 上传拦截器
if (interceptorConfig.getUpload().isEnable()) {
registry.addInterceptor(uploadInterceptor())
.addPathPatterns(interceptorConfig.getUpload().getIncludePaths());
}
// 资源拦截器注册
if (interceptorConfig.getResource().isEnable()) {
registry.addInterceptor(resourceInterceptor())
.addPathPatterns(interceptorConfig.getResource().getIncludePaths());
}
// 下载拦截器注册
if (interceptorConfig.getDownload().isEnable()) {
registry.addInterceptor(downloadInterceptor())
.addPathPatterns(interceptorConfig.getDownload().getIncludePaths());
}
// 自定义权限拦截器注册
if (interceptorConfig.getPermission().isEnable()) {
registry.addInterceptor(permissionInterceptor())
.addPathPatterns(interceptorConfig.getPermission().getIncludePaths())
.excludePathPatterns(interceptorConfig.getPermission().getExcludePaths());
}
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 设置项目静态资源访问
String resourceHandlers = springBootPlusProperties.getResourceHandlers();
if (StringUtils.isNotBlank(resourceHandlers)) {
Map<String, String> map = IniUtil.parseIni(resourceHandlers);
for (Map.Entry<String, String> entry : map.entrySet()) {
String pathPatterns = entry.getKey();
String resourceLocations = entry.getValue();
registry.addResourceHandler(pathPatterns)
.addResourceLocations(resourceLocations);
}
}
// 设置上传文件访问路径
registry.addResourceHandler(springBootPlusProperties.getResourceAccessPatterns())
.addResourceLocations("file:" + springBootPlusProperties.getUploadPath());
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.handler;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.JWTDecodeException;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.exception.DaoException;
import io.geekidea.springbootplus.framework.common.exception.SpringBootPlusException;
import io.geekidea.springbootplus.framework.core.bean.RequestDetail;
import io.geekidea.springbootplus.framework.core.util.RequestDetailThreadLocal;
import io.geekidea.springbootplus.system.exception.SysLoginException;
import io.geekidea.springbootplus.system.exception.VerificationCodeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 全局异常处理器, 封装错误response
*
* @author geekidea
* @date 2018-11-08
*/
@ControllerAdvice
@RestController
@Slf4j
public class GlobalExceptionHandler {
/**
* 非法参数验证异常
*
* @param ex
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.OK)
public ApiResult<List<String>> handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
printRequestDetail();
BindingResult bindingResult = ex.getBindingResult();
List<String> list = new ArrayList<>();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
list.add(fieldError.getDefaultMessage());
}
Collections.sort(list);
log.error(getApiCodeString(ApiCode.PARAMETER_EXCEPTION) + ":" + JSON.toJSONString(list));
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, list);
}
/**
* 系统登录异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = SysLoginException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> sysLoginExceptionHandler(SysLoginException exception) {
printRequestDetail();
printApiCodeException(ApiCode.LOGIN_EXCEPTION, exception);
return ApiResult.fail(ApiCode.LOGIN_EXCEPTION);
}
/**
* HTTP解析请求参数异常
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> httpMessageNotReadableException(HttpMessageNotReadableException exception) {
printRequestDetail();
printApiCodeException(ApiCode.PARAMETER_EXCEPTION, exception);
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION);
}
/**
* HTTP
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpMediaTypeException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> httpMediaTypeException(HttpMediaTypeException exception) {
printRequestDetail();
printApiCodeException(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION, exception);
return ApiResult.fail(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION);
}
/**
* 自定义业务/数据异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = {SpringBootPlusException.class})
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> springBootPlusExceptionHandler(SpringBootPlusException exception) {
printRequestDetail();
log.error("springBootPlusException:", exception);
int errorCode;
if (exception instanceof BusinessException) {
errorCode = ApiCode.BUSINESS_EXCEPTION.getCode();
} else if (exception instanceof DaoException) {
errorCode = ApiCode.DAO_EXCEPTION.getCode();
} else if (exception instanceof VerificationCodeException) {
errorCode = ApiCode.VERIFICATION_CODE_EXCEPTION.getCode();
} else {
errorCode = ApiCode.SPRING_BOOT_PLUS_EXCEPTION.getCode();
}
return new ApiResult<Boolean>()
.setCode(errorCode)
.setMessage(exception.getMessage());
}
/**
* 登录授权异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = AuthenticationException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> authenticationExceptionHandler(AuthenticationException exception) {
printRequestDetail();
printApiCodeException(ApiCode.AUTHENTICATION_EXCEPTION, exception);
return ApiResult.fail(ApiCode.AUTHENTICATION_EXCEPTION);
}
/**
* 未认证异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = UnauthenticatedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> unauthenticatedExceptionHandler(UnauthenticatedException exception) {
printRequestDetail();
printApiCodeException(ApiCode.UNAUTHENTICATED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.UNAUTHENTICATED_EXCEPTION);
}
/**
* 未授权异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = UnauthorizedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> unauthorizedExceptionHandler(UnauthorizedException exception) {
printRequestDetail();
printApiCodeException(ApiCode.UNAUTHORIZED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.UNAUTHORIZED_EXCEPTION);
}
/**
* JWT Token解析异常
*
* @param exception
* @return
*/
@ExceptionHandler(value = JWTDecodeException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> jWTDecodeExceptionHandler(JWTDecodeException exception) {
printRequestDetail();
printApiCodeException(ApiCode.JWTDECODE_EXCEPTION, exception);
return ApiResult.fail(ApiCode.JWTDECODE_EXCEPTION);
}
/**
* 默认的请求异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<String> httpRequestMethodNotSupportedExceptionHandler(Exception exception) {
printRequestDetail();
printApiCodeException(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION.getCode(), exception.getMessage());
}
/**
* 默认的全局异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> exceptionHandler(Exception exception) {
printRequestDetail();
printApiCodeException(ApiCode.SYSTEM_EXCEPTION, exception);
return ApiResult.fail(ApiCode.SYSTEM_EXCEPTION);
}
/**
* 打印请求详情
*/
private void printRequestDetail() {
RequestDetail requestDetail = RequestDetailThreadLocal.getRequestDetail();
if (requestDetail != null) {
log.error("异常来源:ip: {}, path: {}", requestDetail.getIp(), requestDetail.getPath());
}
}
/**
* 获取ApiCode格式化字符串
*
* @param apiCode
* @return
*/
private String getApiCodeString(ApiCode apiCode) {
if (apiCode != null) {
return String.format("errorCode: %s, errorMessage: %s", apiCode.getCode(), apiCode.getMessage());
}
return null;
}
/**
* 打印错误码及异常
*
* @param apiCode
* @param exception
*/
private void printApiCodeException(ApiCode apiCode, Exception exception) {
log.error(getApiCodeString(apiCode), exception);
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.test;
import io.geekidea.springbootplus.SpringBootPlusApplication;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author geekidea
* @date 2020/3/16
**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootPlusApplication.class)
public class BaseTest {
}
/target/
/classes
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
.DS_Store
*.log
logs
*.rdb
# config 项目配置模块
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>parent</artifactId>
<version>2.0</version>
</parent>
<artifactId>config</artifactId>
<name>config</name>
<description>项目配置模块</description>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>config/application-*.yml</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/config</directory>
<filtering>true</filtering>
<targetPath>config</targetPath>
<includes>
<include>application-${profileActive}.yml</include>
</includes>
</resource>
</resources>
</build>
</project>
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.constant;
/**
* 可排序查询参数对象
*
* @author geekidea
* @since 2019-08-08
*/
public interface CacheKey {
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.constant;
/**
* 公共常量
*
* @author geekidea
* @date 2018-11-08
*/
public interface CommonConstant {
/**
* 默认页码为1
*/
Long DEFAULT_PAGE_INDEX = 1L;
/**
* 默认页大小为10
*/
Long DEFAULT_PAGE_SIZE = 10L;
/**
* 数量最大为100
*/
Long MAX_PAGE_SIZE = 100L;
/**
* 分页总行数名称
*/
String PAGE_TOTAL_NAME = "total";
/**
* 分页数据列表名称
*/
String PAGE_RECORDS_NAME = "records";
/**
* 分页当前页码名称
*/
String PAGE_INDEX_NAME = "pageIndex";
/**
* 分页当前页大小名称
*/
String PAGE_SIZE_NAME = "pageSize";
/**
* 登录用户
*/
String LOGIN_SYS_USER = "loginSysUser";
/**
* 登录token
*/
String JWT_DEFAULT_TOKEN_NAME = "token";
/**
* JWT用户名
*/
String JWT_USERNAME = "username";
/**
* JWT刷新新token响应状态码
*/
int JWT_REFRESH_TOKEN_CODE = 460;
/**
* JWT刷新新token响应状态码,
* Redis中不存在,但jwt未过期,不生成新的token,返回361状态码
*/
int JWT_INVALID_TOKEN_CODE = 461;
/**
* JWT Token默认密钥
*/
String JWT_DEFAULT_SECRET = "666666";
/**
* JWT 默认过期时间,3600L,单位秒
*/
Long JWT_DEFAULT_EXPIRE_SECOND = 3600L;
/**
* 默认头像
*/
String DEFAULT_HEAD_URL = "";
/**
* 管理员角色名称
*/
String ADMIN_ROLE_NAME = "管理员";
String ADMIN_LOGIN = "adminLogin";
/**
* 验证码token
*/
String VERIFY_TOKEN = "verifyToken";
/**
* 图片
*/
String IMAGE = "image";
/**
* JPEG
*/
String JPEG = "JPEG";
/**
* base64前缀
*/
String BASE64_PREFIX = "data:image/png;base64,";
/**
* ..
*/
String SPOT_SPOT = "..";
/**
* ../
*/
String SPOT_SPOT_BACKSLASH = "../";
/**
* SpringBootAdmin登录信息
*/
String ADMIN_LOGIN_SESSION = "adminLoginSession";
/**
* 用户浏览器代理
*/
String USER_AGENT = "User-Agent";
/**
* 本机地址IP
*/
String LOCALHOST_IP = "127.0.0.1";
/**
* 本机地址名称
*/
String LOCALHOST_IP_NAME = "本机地址";
/**
* 局域网IP
*/
String LAN_IP = "192.168";
/**
* 局域网名称
*/
String LAN_IP_NAME = "局域网";
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.constant;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public interface CommonRedisKey {
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String LOGIN_TOKEN = "login:token:%s";
/**
* 登录用户信息key
* login:user:username
*/
String LOGIN_USER = "login:user:%s";
/**
* 登录用户盐值信息key
* login:salt:username
*/
String LOGIN_SALT = "login:salt:%s";
/**
* 登录用户username token
* login:user:token:username:token
*/
String LOGIN_USER_TOKEN = "login:user:token:%s:%s";
/**
* 登录用户下的所有token
* login:user:token:username:*
*/
String LOGIN_USER_ALL_TOKEN = "login:user:token:%s:*";
/**
* 验证码
* verify.code:666666
*/
String VERIFY_CODE = "verify.code:%s";
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.constant;
/**
* <p>
* 日期格式常量
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public interface DatePattern {
/**
* 年-月-日
*/
String YYYY_MM_DD = "yyyy-MM-dd";
/**
* 年-月-日 时:分
*/
String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
/**
* 年-月-日 时:分:秒
*/
String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 年-月-日 时:分:秒:毫秒
*/
String YYYY_MM_DD_HH_MM_SS_S = "yyyy-MM-dd HH:mm:ss.S";
/**
* 时:分
*/
String HH_MM = "HH:mm";
/**
* 时:分:秒
*/
String HH_MM_SS = "HH:mm:ss";
/**
* 时:分:秒:毫秒
*/
String HH_MM_SS_S = "HH:mm:ss:S";
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import io.geekidea.springbootplus.config.constant.CommonConstant;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* JWT属性配置
*
* @author geekidea
* @date 2019-05-22
**/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.jwt")
public class JwtProperties {
/**
* token名称,默认名称为:token,可自定义
*/
private String tokenName = CommonConstant.JWT_DEFAULT_TOKEN_NAME;
/**
* 密码
*/
private String secret = CommonConstant.JWT_DEFAULT_SECRET;
/**
* 签发人
*/
private String issuer;
/**
* 主题
*/
private String subject;
/**
* 签发的目标
*/
private String audience;
/**
* token失效时间,默认1小时,60*60=3600
*/
private Long expireSecond = CommonConstant.JWT_DEFAULT_EXPIRE_SECOND;
/**
* 是否刷新token,默认为true
*/
private boolean refreshToken = true;
/**
* 刷新token倒计时,默认10分钟,10*60=600
*/
private Integer refreshTokenCountdown;
/**
* redis校验jwt token是否存在
*/
private boolean redisCheck;
/**
* 单用户登录,一个用户只能又一个有效的token
*/
private boolean singleLogin;
/**
* 是否进行盐值校验
*/
private boolean saltCheck;
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
/**
* Shiro权限配置映射类
*
* @author geekidea
* @date 2019-09-28
**/
@Data
public class ShiroPermissionProperties {
/**
* 路径
*/
private String url;
/**
* 路径数组
*/
private String[] urls;
/**
* 权限
*/
private String permission;
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import java.util.List;
/**
* Shiro配置映射类
*
* @author geekidea
* @date 2019-09-28
**/
@Data
@ConfigurationProperties(prefix = "spring-boot-plus.shiro")
public class ShiroProperties {
/**
* 是否启用
*/
private boolean enable;
/**
* 路径权限配置
*/
private String filterChainDefinitions;
/**
* 设置无需权限路径集合
*/
private List<String[]> anon;
/**
* 权限配置集合
*/
@NestedConfigurationProperty
private List<ShiroPermissionProperties> permission;
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
import java.util.Set;
/**
* AOP配置属性
*
* @author geekidea
* @date 2019-09-29
**/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.aop")
public class SpringBootPlusAopProperties {
/**
* 请求路径Filter配置
*/
@NestedConfigurationProperty
private LogAopConfig log = new LogAopConfig();
/**
* 操作日志配置
*/
@NestedConfigurationProperty
private OperationLogConfig operationLog;
/**
* 登录日志配置
*/
private LoginLogConfig loginLog;
/**
* 日志打印类型
*
* @author geekidea
* @date 2020/3/19
**/
public enum LogPrintType {
/**
* 不打印日志
*/
NONE,
/**
* 请求和响应日志,按照执行顺序分开打印
*/
ORDER,
/**
* 方法执行结束时,连续分开打印请求和响应日志
*/
LINE,
/**
* 方法执行结束时,合并请求和响应日志,同时打印
*/
MERGE
}
/**
* 请求ID生成类型
*
* @author geekidea
* @date 2020/3/25
**/
public enum RequestIdType {
/**
* 生成UUID无中横线
*/
UUID,
/**
* 生成数字
*/
IDWORK
}
@Data
public static class AopConfig {
/**
* 是否启用
*/
private boolean enable;
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class LogAopConfig extends AopConfig {
/**
* 是否启用requestId
*/
private boolean enableRequestId = true;
/**
* 日志输出类型:print-type
*/
private LogPrintType logPrintType = LogPrintType.ORDER;
/**
* 请求ID生成类型
*/
private RequestIdType requestIdType = RequestIdType.IDWORK;
/**
* 请求日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
*/
private boolean requestLogFormat = true;
/**
* 响应日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
*/
private boolean responseLogFormat = true;
/**
* 排除路径
*/
private Set<String> excludePaths;
}
/**
* 操作日志配置
*/
@Data
public static class OperationLogConfig {
/**
* 是否启用
*/
private boolean enable = true;
/**
* 排除路径
*/
private Set<String> excludePaths;
}
/**
* 登录日志配置
*/
@Data
public static class LoginLogConfig {
/**
* 是否启用
*/
private boolean enable = true;
/**
* 登录路径
*/
private String loginPath = "/login";
/**
* 登出路径
*/
private String logoutPath = "/logout";
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 跨域属性配置
*
* @author geekidea
* @date 2019-10-09
**/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.cors")
public class SpringBootPlusCorsProperties {
/**
* 是否启用跨域,默认启用
*/
private boolean enable = true;
/**
* CORS过滤的路径,默认:/**
*/
private String path = "/**";
/**
* 允许访问的源
*/
private List<String> allowedOrigins = Collections.singletonList(CorsConfiguration.ALL);
/**
* 允许访问的请求头
*/
private List<String> allowedHeaders = Collections.singletonList(CorsConfiguration.ALL);
/**
* 是否允许发送cookie
*/
private boolean allowCredentials = true;
/**
* 允许访问的请求方式
*/
private List<String> allowedMethods = Collections.singletonList(CorsConfiguration.ALL);
/**
* 允许响应的头
*/
private List<String> exposedHeaders = Arrays.asList("token");
/**
* 该响应的有效时间默认为30分钟,在有效时间内,浏览器无须为同一请求再次发起预检请求
*/
private Long maxAge = 1800L;
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
* Filter配置属性
*
* @author geekidea
* @date 2019-09-29
**/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.filter")
public class SpringBootPlusFilterProperties {
/**
* RequestDetail Filter配置
*/
@NestedConfigurationProperty
private FilterConfig request = new FilterConfig();
/**
* XSS Filter配置
*/
@NestedConfigurationProperty
private FilterConfig xss = new FilterConfig();
@Data
public static class FilterConfig {
/**
* 是否启用
*/
private boolean enable;
/**
* 过滤的路径
*/
private String[] urlPatterns;
/**
* 排序
*/
private int order;
/**
* 是否支持异步
*/
private boolean async;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
* spring-boot-plus拦截器配置属性
*
* @author geekidea
* @date 2019/8/5
*/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.interceptor")
public class SpringBootPlusInterceptorProperties {
/**
* SpringBootAdmin权限拦截器
*/
private InterceptorConfig springbootadmin = new InterceptorConfig();
/**
* 自定义权限拦截器
*/
@NestedConfigurationProperty
private InterceptorConfig permission = new InterceptorConfig();
/**
* 资源拦截器
*/
@NestedConfigurationProperty
private InterceptorConfig resource = new InterceptorConfig();
/**
* 上传拦截器
*/
@NestedConfigurationProperty
private InterceptorConfig upload = new InterceptorConfig();
/**
* 下载拦截器
*/
@NestedConfigurationProperty
private InterceptorConfig download = new InterceptorConfig();
@Data
public static class InterceptorConfig {
/**
* 是否启用
*/
private boolean enable;
/**
* 包含的路径
*/
private String[] includePaths = new String[]{};
/**
* 排除路径
*/
private String[] excludePaths = new String[]{};
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* spring-boot-plus属性配置信息
*
* @author geekidea
* @date 2019-08-04
*/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus")
public class SpringBootPlusProperties {
/**
* 是否启用ansi控制台输出有颜色的字体,local环境建议开启,服务器环境设置为false
*/
private boolean enableAnsi;
/**
* 项目IP或域名地址
*/
private String serverIp;
/**
* 是否启用验证码
*/
private boolean enableVerifyCode;
/**
* 新建登录用户初始化盐值
*/
private String loginInitSalt;
/**
* 新建登录用户初始化密码
*/
private String loginInitPassword;
/**
* 新建用户初始化头像
*/
private String loginInitHead;
/**
* 实现BaseEnum接口的枚举包
*/
private String[] enumPackages;
/**
* 拦截器配置
*/
@NestedConfigurationProperty
private SpringBootPlusInterceptorProperties interceptor;
/**
* 过滤器配置
*/
@NestedConfigurationProperty
private SpringBootPlusFilterProperties filter;
/**
* 上传目录
*/
private String uploadPath;
/**
* 资源访问路径,前端访问
*/
private String resourceAccessPath;
/**
* 资源访问路径,后段配置,资源映射/拦截器使用
*/
private String resourceAccessPatterns;
/**
* 资源访问全路径
*/
private String resourceAccessUrl;
/**
* 允许上传的文件后缀集合
*/
private List<String> allowUploadFileExtensions;
/**
* 允许下载的文件后缀集合
*/
private List<String> allowDownloadFileExtensions;
/**
* JWT配置
*/
@NestedConfigurationProperty
private JwtProperties jwt;
/**
* Shiro配置
*/
@NestedConfigurationProperty
private ShiroProperties shiro = new ShiroProperties();
/**
* 项目静态资源访问配置
*
* @see SpringBootPlusWebMvcConfig addResourceHandlers
*/
private String resourceHandlers;
/**
* 跨域配置
*/
@NestedConfigurationProperty
private SpringBootPlusCorsProperties cors = new SpringBootPlusCorsProperties();
/**
* Swagger路径
*/
private List<String> swaggerPaths;
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 配置文件属性映射为静态属性
*
* @author geekidea
* @date 2019-10-11
**/
@Slf4j
@Data
@Component
public class SpringBootPlusStaticProperties {
public static String INFO_PROJECT_VERSION = "";
@Value("${info.project-version}")
private String infoProjectVersion;
@PostConstruct
public void init() {
INFO_PROJECT_VERSION = this.infoProjectVersion;
log.debug("INFO_PROJECT_VERSION:" + INFO_PROJECT_VERSION);
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.geekidea.springbootplus.config.properties;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Swagger配置属性
*
* @author geekidea
* @date 2020/3/21
**/
@Data
@Component
@ConfigurationProperties(prefix = "spring-boot-plus.swagger")
public class SwaggerProperties {
/**
* 是否启用Swagger
*/
private boolean enable;
/**
* 扫描的基本包
*/
@Value("${spring-boot-plus.swagger.base.package}")
private String basePackage;
/**
* 联系人邮箱
*/
@Value("${spring-boot-plus.swagger.contact.email}")
private String contactEmail;
/**
* 联系人名称
*/
@Value("${spring-boot-plus.swagger.contact.name}")
private String contactName;
/**
* 联系人网址
*/
@Value("${spring-boot-plus.swagger.contact.url}")
private String contactUrl;
/**
* 描述
*/
private String description;
/**
* 标题
*/
private String title;
/**
* 网址
*/
private String url;
/**
* 版本
*/
private String version;
/**
* 自定义参数配置
*/
@NestedConfigurationProperty
private List<ParameterConfig> parameterConfig;
/**
* 自定义参数配置
*/
@Data
public static class ParameterConfig {
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
/**
* 参数类型
* header, cookie, body, query
*/
private String type = "head";
/**
* 数据类型
*/
private String dataType = "String";
/**
* 是否必填
*/
private boolean required;
/**
* 默认值
*/
private String defaultValue;
}
}
spring-boot-plus:
# 是否启用ansi控制台输出有颜色的字体,dev环境建议开启,服务器环境设置为false
enable-ansi: true
# 当前环境服务IP地址
server-ip: 127.0.0.1
# 文件上传下载配置
upload-path: /opt/upload/
aop:
log:
enable: true
log-print-type: LINE
request-log-format: false
response-log-format: false
spring:
datasource:
# url: jdbc:mysql://localhost:3306/spring_boot_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
url: jdbc:mysql://localhost:3306/vike?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123
# Redis配置
redis:
database: 0
host: localhost
password:
port: 6379
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
\ No newline at end of file
spring-boot-plus:
# 是否启用ansi控制台输出有颜色的字体,local环境建议开启,服务器环境设置为false
enable-ansi: false
# 当前环境服务IP地址
server-ip:
# 生产环境禁用Swagger
swagger:
enable: false
# AOP配置
aop:
log:
enable: true
log-print-type: NONE
request-log-format: false
response-log-format: false
spring:
datasource:
url: jdbc:mysql://mysql57:3306/vike?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123
# Redis配置
redis:
database: 0
host: redis6
password:
port: 6379
spring-boot-plus:
# 是否启用ansi控制台输出有颜色的字体,local环境建议开启,服务器环境设置为false
enable-ansi: false
# 当前环境服务IP地址
server-ip: 47.105.159.10
# 文件上传下载配置
upload-path: /opt/upload/
# AOP配置
aop:
log:
enable: true
log-print-type: LINE
request-log-format: false
response-log-format: false
spring:
datasource:
url: jdbc:mysql://mysql57:3306/vike?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123
# Redis配置
redis:
database: 0
host: redis6
password:
port: 6379
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring-boot-plus:
# 是否启用ansi控制台输出有颜色的字体,local环境建议开启,服务器环境设置为false
enable-ansi: false
# 当前环境服务IP地址
server-ip:
# AOP配置
aop:
log:
enable: true
log-print-type: LINE
request-log-format: false
response-log-format: false
spring:
datasource:
url:
username:
password:
# Redis配置
redis:
database:
host:
password:
port:
${AnsiColor.BLUE}
_ _ _ _
(_) | | | | | |
___ _ __ _ __ _ _ __ __ _ ______| |__ ___ ___ | |_ ______ _ __ | |_ _ ___
/ __| '_ \| '__| | '_ \ / _` |______| '_ \ / _ \ / _ \| __|______| '_ \| | | | / __|
\__ \ |_) | | | | | | | (_| | | |_) | (_) | (_) | |_ | |_) | | |_| \__ \
|___/ .__/|_| |_|_| |_|\__, | |_.__/ \___/ \___/ \__| | .__/|_|\__,_|___/
| | __/ | | |
|_| |___/ |_|
${AnsiColor.YELLOW} :: Spring Boot :: ${AnsiColor.WHITE}(v${spring-boot.version})
${AnsiColor.YELLOW} :: spring-boot-plus :: ${AnsiColor.WHITE}(v${project.version})
https://springboot.plus
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<configuration>
<property name="CONTEXT_NAME" value="spring-boot-plus"/>
<property name="LOG_PATH" value="logs"/>
<property name="MAX_FILE_SIZE" value="10MB"/>
<property name="MAX_HISTORY" value="30"/>
<contextName>${CONTEXT_NAME}</contextName>
<!-- 彩色日志 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 控制台日志样式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%15.15t]){faint} [%X{requestId}] %clr(%-40.40logger{39}){cyan} [%L] %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 文件日志样式 -->
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} [%t] [%X{requestId}] %-40.40logger{39} %L : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 禁用logback自身日志输出 -->
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
<!-- 控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 运行日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/spring-boot-plus.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/spring-boot-plus-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
</rollingPolicy>
</appender>
<!-- 错误日志文件 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/spring-boot-plus-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/spring-boot-plus-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 异步写日志 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1024</queueSize>
<appender-ref ref="FILE"/>
</appender>
<appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1024</queueSize>
<appender-ref ref="ERROR_FILE"/>
</appender>
<!-- 不同环境的日志级别配置 -->
<springProfile name="dev">
<logger name="io.geekidea.springbootplus" level="DEBUG"/>
</springProfile>
<!-- 解决SpringBootAdmin错误日志问题 -->
<logger name="org.apache.catalina.connector.CoyoteAdapter" level="OFF"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="ASYNC_ERROR_FILE"/>
</root>
</configuration>
\ No newline at end of file
#
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# 扩展mime-type
# 参考:https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?revision=1752884&view=co
md=text/markdown
\ No newline at end of file
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
<h1>Not Found</h1>
</body>
</html>
\ No newline at end of file
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>500</title>
</head>
<body>
<h1>500</h1>
</body>
</html>
\ No newline at end of file
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
<h1>Error</h1>
</body>
</html>
\ No newline at end of file
#/**
#* 操作成功
#**/
api.response.code.SUCCESS=成功
#/**
#* 非法访问
#**/
api.response.code.UNAUTHORIZED=非法访问
#/**
#* 没有权限
#**/
api.response.code.NOT_PERMISSION=没有权限
#/**
#* 你请求的资源不存在
#**/
api.response.code.NOT_FOUND=你请求的资源不存在
#/**
#* 操作失败
#**/
api.response.code.FAIL=操作失败
#/**
#* 登录失败
#**/
api.response.code.LOGIN_EXCEPTION=登录失败
#/**
#* 系统异常
#**/
api.response.code.SYSTEM_EXCEPTION=系统异常
#/**
#* 请求参数校验异常
#**/
api.response.code.PARAMETER_EXCEPTION=请求参数校验异常
#/**
#* 请求参数解析异常
#**/
api.response.code.PARAMETER_PARSE_EXCEPTION=请求参数解析异常
#/**
#* HTTP内容类型异常
#**/
api.response.code.HTTP_MEDIA_TYPE_EXCEPTION=HTTP内容类型异常
#/**
#* 系统处理异常
#**/
api.response.code.SPRING_BOOT_PLUS_EXCEPTION=系统处理异常
#/**
#* 业务处理异常
#**/
api.response.code.BUSINESS_EXCEPTION=业务处理异常
#/**
#* 数据库处理异常
#**/
api.response.code.DAO_EXCEPTION=数据库处理异常
#/**
#* 验证码校验异常
#**/
api.response.code.VERIFICATION_CODE_EXCEPTION=验证码校验异常
#/**
#* 登录授权异常
#**/
api.response.code.AUTHENTICATION_EXCEPTION=登录授权异常
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHENTICATED_EXCEPTION=没有访问权限
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHORIZED_EXCEPTION=没有访问权限
#/**
#* JWT Token解析异常
#**/
api.response.code.JWTDECODE_EXCEPTION=Token解析异常
#
#/**
#* 默认的异常处理
#*/
api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION=默认的异常处理
api.response.code.user.PWD_OR_USERNAME_ERROR=账号或密码错误
#/**
#* 操作成功
#**/
api.response.code.SUCCESS=SUCCESS
#/**
#* 非法访问
#**/
api.response.code.UNAUTHORIZED=UNAUTHORIZED
#/**
#* 没有权限
#**/
api.response.code.NOT_PERMISSION=NOT_PERMISSION
#/**
#* 你请求的资源不存在
#**/
api.response.code.NOT_FOUND=NOT_FOUND
#/**
#* 操作失败
#**/
api.response.code.FAIL=FAIL
#/**
#* 登录失败
#**/
api.response.code.LOGIN_EXCEPTION=LOGIN_EXCEPTION
#/**
#* 系统异常
#**/
api.response.code.SYSTEM_EXCEPTION=SYSTEM_EXCEPTION
#/**
#* 请求参数校验异常
#**/
api.response.code.PARAMETER_EXCEPTION=PARAMETER_EXCEPTION
#/**
#* 请求参数解析异常
#**/
api.response.code.PARAMETER_PARSE_EXCEPTION=PARAMETER_PARSE_EXCEPTION
#/**
#* HTTP内容类型异常
#**/
api.response.code.HTTP_MEDIA_TYPE_EXCEPTION=HTTP_MEDIA_TYPE_EXCEPTION
#/**
#* 系统处理异常
#**/
api.response.code.SPRING_BOOT_PLUS_EXCEPTION=SPRING_BOOT_PLUS_EXCEPTION
#/**
#* 业务处理异常
#**/
api.response.code.BUSINESS_EXCEPTION=BUSINESS_EXCEPTION
#/**
#* 数据库处理异常
#**/
api.response.code.DAO_EXCEPTION=DAO_EXCEPTION
#/**
#* 验证码校验异常
#**/
api.response.code.VERIFICATION_CODE_EXCEPTION=VERIFICATION_CODE_EXCEPTION
#/**
#* 登录授权异常
#**/
api.response.code.AUTHENTICATION_EXCEPTION=AUTHENTICATION_EXCEPTION
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHENTICATED_EXCEPTION=UNAUTHENTICATED_EXCEPTION
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHORIZED_EXCEPTION=UNAUTHORIZED_EXCEPTION
#/**
#* JWT Token解析异常
#**/
api.response.code.JWTDECODE_EXCEPTION=JWTDECODE_EXCEPTION
#
#/**
#* 默认的异常处理
#*/
api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION=HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION
api.response.code.user.PWD_OR_USERNAME_ERROR=password or phone number error
\ No newline at end of file
#/**
#* 操作成功
#**/
api.response.code.SUCCESS=SUCCESS
#/**
#* 非法访问
#**/
api.response.code.UNAUTHORIZED=UNAUTHORIZED
#/**
#* 没有权限
#**/
api.response.code.NOT_PERMISSION=NOT_PERMISSION
#/**
#* 你请求的资源不存在
#**/
api.response.code.NOT_FOUND=NOT_FOUND
#/**
#* 操作失败
#**/
api.response.code.FAIL=FAIL
#/**
#* 登录失败
#**/
api.response.code.LOGIN_EXCEPTION=LOGIN_EXCEPTION
#/**
#* 系统异常
#**/
api.response.code.SYSTEM_EXCEPTION=SYSTEM_EXCEPTION
#/**
#* 请求参数校验异常
#**/
api.response.code.PARAMETER_EXCEPTION=PARAMETER_EXCEPTION
#/**
#* 请求参数解析异常
#**/
api.response.code.PARAMETER_PARSE_EXCEPTION=PARAMETER_PARSE_EXCEPTION
#/**
#* HTTP内容类型异常
#**/
api.response.code.HTTP_MEDIA_TYPE_EXCEPTION=HTTP_MEDIA_TYPE_EXCEPTION
#/**
#* 系统处理异常
#**/
api.response.code.SPRING_BOOT_PLUS_EXCEPTION=SPRING_BOOT_PLUS_EXCEPTION
#/**
#* 业务处理异常
#**/
api.response.code.BUSINESS_EXCEPTION=BUSINESS_EXCEPTION
#/**
#* 数据库处理异常
#**/
api.response.code.DAO_EXCEPTION=DAO_EXCEPTION
#/**
#* 验证码校验异常
#**/
api.response.code.VERIFICATION_CODE_EXCEPTION=VERIFICATION_CODE_EXCEPTION
#/**
#* 登录授权异常
#**/
api.response.code.AUTHENTICATION_EXCEPTION=AUTHENTICATION_EXCEPTION
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHENTICATED_EXCEPTION=UNAUTHENTICATED_EXCEPTION
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHORIZED_EXCEPTION=UNAUTHORIZED_EXCEPTION
#/**
#* JWT Token解析异常
#**/
api.response.code.JWTDECODE_EXCEPTION=JWTDECODE_EXCEPTION
#
#/**
#* 默认的异常处理
#*/
api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION=HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION
api.response.code.user.PWD_OR_USERNAME_ERROR=password or phone number error KH
\ No newline at end of file
#/**
#* 操作成功
#**/
api.response.code.SUCCESS=成功
#/**
#* 非法访问
#**/
api.response.code.UNAUTHORIZED=非法访问
#/**
#* 没有权限
#**/
api.response.code.NOT_PERMISSION=没有权限
#/**
#* 你请求的资源不存在
#**/
api.response.code.NOT_FOUND=你请求的资源不存在
#/**
#* 操作失败
#**/
api.response.code.FAIL=操作失败
#/**
#* 登录失败
#**/
api.response.code.LOGIN_EXCEPTION=登录失败
#/**
#* 系统异常
#**/
api.response.code.SYSTEM_EXCEPTION=系统异常
#/**
#* 请求参数校验异常
#**/
api.response.code.PARAMETER_EXCEPTION=请求参数校验异常
#/**
#* 请求参数解析异常
#**/
api.response.code.PARAMETER_PARSE_EXCEPTION=请求参数解析异常
#/**
#* HTTP内容类型异常
#**/
api.response.code.HTTP_MEDIA_TYPE_EXCEPTION=HTTP内容类型异常
#/**
#* 系统处理异常
#**/
api.response.code.SPRING_BOOT_PLUS_EXCEPTION=系统处理异常
#/**
#* 业务处理异常
#**/
api.response.code.BUSINESS_EXCEPTION=业务处理异常
#/**
#* 数据库处理异常
#**/
api.response.code.DAO_EXCEPTION=数据库处理异常
#/**
#* 验证码校验异常
#**/
api.response.code.VERIFICATION_CODE_EXCEPTION=验证码校验异常
#/**
#* 登录授权异常
#**/
api.response.code.AUTHENTICATION_EXCEPTION=登录授权异常
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHENTICATED_EXCEPTION=没有访问权限
#/**
#* 没有访问权限
#**/
api.response.code.UNAUTHORIZED_EXCEPTION=没有访问权限
#/**
#* JWT Token解析异常
#**/
api.response.code.JWTDECODE_EXCEPTION=Token解析异常
#
#/**
#* 默认的异常处理
#*/
api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION=默认的异常处理
api.response.code.user.PWD_OR_USERNAME_ERROR=账号或密码错误
\ No newline at end of file
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
</head>
<body>
<div>
<p>方式一:获取图片</p>
<img alt="" id="imageCode" onclick="changeImage()" src="http://localhost:8888/verificationCode/getImage">
<p>verifyToken:查看Responses Headers</p>
</div>
<hr>
<div>
<p>方式二:获取base64图片编码</p>
<img alt="" id="base64ImageCode" onclick="changeBase64Image()" src="">
<p id="verifyToken"></p>
</div>
<script type="text/javascript">
function changeImage() {
document.getElementById('imageCode').src = "http://localhost:8888/api/verificationCode/getImage?time=" + new Date().getTime();
}
var url = "http://localhost:8888/api/verificationCode/getBase64Image";
function changeBase64Image() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var result = JSON.parse(xhr.responseText);
document.getElementById('base64ImageCode').src = result.data.image;
document.getElementById('verifyToken').innerText = "verifyToken:" + result.data.verifyToken;
}
};
xhr.open("GET", url, true);
xhr.send(null);
}
changeBase64Image();
</script>
</body>
</html>
\ No newline at end of file
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome to spring-boot-plus</title>
</head>
<body>
<h1>Welcome to spring-boot-plus</h1>
<h3>
<a href="https://github.com/geekidea/spring-boot-plus" target="_blank">GITHUB</a>
</h3>
<h3>
<a href="https://gitee.com/geekidea/spring-boot-plus" target="_blank">GITEE</a>
</h3>
<h2>
<a href="https://springboot.plus" target="_blank">springboot.plus</a>
</h2>
</body>
</html>
\ No newline at end of file
/target/
/classes
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
.DS_Store
*.log
logs
*.rdb
# distribution 项目打包模块
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 项目重启shell脚本
# 先调用shutdown.sh停服
# 然后调用startup.sh启动服务
#
# author: geekidea
# date: 2020-3-28
#======================================================================
# 项目名称
# 停服
sh shutdown.sh
# 启动服务
sh startup.sh
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 项目停服shell脚本
# 通过项目名称查找到PID
# 然后kill -9 pid
#
# author: geekidea
# date: 2020-3-28
#======================================================================
# 项目名称
APPLICATION="${admin.artifact.name}"
# 项目启动jar包名称
APPLICATION_JAR="${APPLICATION}.jar"
PID=$(ps -ef | grep ${APPLICATION_JAR} | grep -v grep | awk '{ print $2 }')
if [ -z "$PID" ]
then
echo ${APPLICATION} is already stopped
else
echo kill ${PID}
kill -9 ${PID}
echo ${APPLICATION} stopped successfully
fi
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# Admin项目启动shell脚本
# config目录: 配置文件目录
# logs目录: 项目运行日志目录
# logs/spring-boot-plus_startup.log: 记录启动日志
# logs/back目录: 项目运行日志备份目录
# nohup后台运行
#
# author: geekidea
# date: 2020-3-28
#======================================================================
# 项目名称
APPLICATION="${admin.artifact.name}"
# 项目启动jar包名称
APPLICATION_JAR="${APPLICATION}.jar"
echo ${APPLICATION_JAR}
# bin目录绝对路径
BIN_PATH=$(cd `dirname $0`; pwd)
# 进入bin目录
cd `dirname $0`
# 返回到上一级项目根目录路径
cd ..
# 打印项目根目录绝对路径
# `pwd` 执行系统命令并获得结果
BASE_PATH=`pwd`
# 外部配置文件绝对目录,如果是目录需要/结尾,也可以直接指定文件
# 如果指定的是目录,spring则会读取目录中的所有配置文件
CONFIG_DIR=${BASE_PATH}"/config/"
# 项目日志输出绝对路径
LOG_DIR=${BASE_PATH}"/logs"
LOG_FILE="${APPLICATION}.log"
LOG_PATH="${LOG_DIR}/${LOG_FILE}"
# 日志备份目录
LOG_BACK_DIR="${LOG_DIR}/back/"
# 项目启动日志输出绝对路径
LOG_STARTUP_PATH="${LOG_DIR}/${APPLICATION}_startup.log"
# 当前时间
NOW=$(date --date='0 days ago' "+%Y-%m-%d-%H-%M-%S")
NOW_PRETTY=$(date --date='0 days ago' "+%Y-%m-%d %H:%M:%S")
# 启动日志
STARTUP_LOG="================================================ ${NOW_PRETTY} ================================================\n"
# 如果logs文件夹不存在,则创建文件夹
if [ ! -d "${LOG_DIR}" ]; then
mkdir "${LOG_DIR}"
fi
# 如果logs/back文件夹不存在,则创建文件夹
if [ ! -d "${LOG_BACK_DIR}" ]; then
mkdir "${LOG_BACK_DIR}"
fi
# 如果项目运行日志存在,则重命名备份
if [ -f "${LOG_PATH}" ]; then
mv ${LOG_PATH} "${LOG_BACK_DIR}/${APPLICATION}_back_${NOW}.log"
fi
# 创建新的项目运行日志
echo "" > ${LOG_PATH}
# 如果项目启动日志不存在,则创建,否则追加
echo ${STARTUP_LOG} >> ${LOG_STARTUP_PATH}
#=======================================================
# 将命令启动相关日志追加到日志文件
#=======================================================
# 输出项目名称
STARTUP_LOG="${STARTUP_LOG}application name: ${APPLICATION}\n"
# 输出jar包名称
STARTUP_LOG="${STARTUP_LOG}application jar name: ${APPLICATION_JAR}\n"
# 输出项目bin路径
STARTUP_LOG="${STARTUP_LOG}application bin path: ${BIN_PATH}\n"
# 输出项目根目录
STARTUP_LOG="${STARTUP_LOG}application root path: ${BASE_PATH}\n"
# 打印日志路径
STARTUP_LOG="${STARTUP_LOG}application log path: ${LOG_PATH}\n"
# 打印启动命令
STARTUP_LOG="${STARTUP_LOG}application background startup command: nohup java -jar ${BASE_PATH}/lib/${APPLICATION_JAR} --spring.config.location=${CONFIG_DIR} > ${LOG_PATH} 2>&1 &\n"
#======================================================================
# 执行启动命令:后台启动项目,并将日志输出到项目根目录下的logs文件夹下
#======================================================================
nohup java -jar ${BASE_PATH}/lib/${APPLICATION_JAR} --spring.config.location=${CONFIG_DIR} > ${LOG_PATH} 2>&1 &
# 进程ID
PID=$(ps -ef | grep ${APPLICATION_JAR} | grep -v grep | awk '{ print $2 }')
STARTUP_LOG="${STARTUP_LOG}application pid: ${PID}\n"
# 启动日志追加到启动日志文件中
echo -e ${STARTUP_LOG} >> ${LOG_STARTUP_PATH}
# 打印启动日志
echo -e ${STARTUP_LOG}
# 打印项目日志
tail -f ${LOG_PATH}
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 项目重启shell脚本
# 先调用shutdown.sh停服
# 然后调用startup.sh启动服务
#
# author: geekidea
# date: 2018-12-2
#======================================================================
# 项目名称
# 停服
sh shutdown.sh
# 启动服务
sh startup.sh
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 项目停服shell脚本
# 通过项目名称查找到PID
# 然后kill -9 pid
#
# author: geekidea
# date: 2018-12-2
#======================================================================
# 项目名称
APPLICATION="${boot.artifact.name}"
# 项目启动jar包名称
APPLICATION_JAR="${APPLICATION}.jar"
PID=$(ps -ef | grep ${APPLICATION_JAR} | grep -v grep | awk '{ print $2 }')
if [ -z "$PID" ]
then
echo ${APPLICATION} is already stopped
else
echo kill ${PID}
kill -9 ${PID}
echo ${APPLICATION} stopped successfully
fi
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 项目启动shell脚本
# config目录: 配置文件目录
# logs目录: 项目运行日志目录
# logs/spring-boot-plus_startup.log: 记录启动日志
# logs/back目录: 项目运行日志备份目录
# nohup后台运行
#
# author: geekidea
# date: 2018-12-2
#======================================================================
# 项目名称
APPLICATION="${boot.artifact.name}"
# 项目启动jar包名称
APPLICATION_JAR="${APPLICATION}.jar"
echo ${APPLICATION_JAR}
# bin目录绝对路径
BIN_PATH=$(cd `dirname $0`; pwd)
# 进入bin目录
cd `dirname $0`
# 返回到上一级项目根目录路径
cd ..
# 打印项目根目录绝对路径
# `pwd` 执行系统命令并获得结果
BASE_PATH=`pwd`
# 外部配置文件绝对目录,如果是目录需要/结尾,也可以直接指定文件
# 如果指定的是目录,spring则会读取目录中的所有配置文件
CONFIG_DIR=${BASE_PATH}"/config/"
# 项目日志输出绝对路径
LOG_DIR=${BASE_PATH}"/logs"
LOG_FILE="${APPLICATION}.log"
LOG_PATH="${LOG_DIR}/${LOG_FILE}"
# 日志备份目录
LOG_BACK_DIR="${LOG_DIR}/back/"
# 项目启动日志输出绝对路径
LOG_STARTUP_PATH="${LOG_DIR}/${APPLICATION}_startup.log"
# 当前时间
NOW=$(date --date='0 days ago' "+%Y-%m-%d-%H-%M-%S")
NOW_PRETTY=$(date --date='0 days ago' "+%Y-%m-%d %H:%M:%S")
# 启动日志
STARTUP_LOG="================================================ ${NOW_PRETTY} ================================================\n"
# 如果logs文件夹不存在,则创建文件夹
if [ ! -d "${LOG_DIR}" ]; then
mkdir "${LOG_DIR}"
fi
# 如果logs/back文件夹不存在,则创建文件夹
if [ ! -d "${LOG_BACK_DIR}" ]; then
mkdir "${LOG_BACK_DIR}"
fi
# 如果项目运行日志存在,则重命名备份
if [ -f "${LOG_PATH}" ]; then
mv ${LOG_PATH} "${LOG_BACK_DIR}/${APPLICATION}_back_${NOW}.log"
fi
# 创建新的项目运行日志
echo "" > ${LOG_PATH}
# 如果项目启动日志不存在,则创建,否则追加
echo ${STARTUP_LOG} >> ${LOG_STARTUP_PATH}
#==========================================================================================
# JVM Configuration
# -Xmx1g:设置JVM最大可用内存为1G。
# -Xms1g:设置JVM初始内存1g。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存
# -Xmn512m:设置年轻代大小为512m。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。
# 持久代一般固定大小为64m,所以增大年轻代,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
# -XX:MetaspaceSize=64m:存储class的内存大小,该值越大触发Metaspace GC的时机就越晚
# -XX:MaxMetaspaceSize=256m:限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序
# -XX:-OmitStackTraceInFastThrow:解决重复异常不打印堆栈信息问题
#==========================================================================================
JAVA_OPT="-server -Xms1g -Xmx1g -Xmn512m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
#=======================================================
# 将命令启动相关日志追加到日志文件
#=======================================================
# 输出项目名称
STARTUP_LOG="${STARTUP_LOG}application name: ${APPLICATION}\n"
# 输出jar包名称
STARTUP_LOG="${STARTUP_LOG}application jar name: ${APPLICATION_JAR}\n"
# 输出项目bin路径
STARTUP_LOG="${STARTUP_LOG}application bin path: ${BIN_PATH}\n"
# 输出项目根目录
STARTUP_LOG="${STARTUP_LOG}application root path: ${BASE_PATH}\n"
# 打印日志路径
STARTUP_LOG="${STARTUP_LOG}application log path: ${LOG_PATH}\n"
# 打印JVM配置
STARTUP_LOG="${STARTUP_LOG}application JAVA_OPT : ${JAVA_OPT}\n"
# 打印启动命令
STARTUP_LOG="${STARTUP_LOG}application background startup command: nohup java ${JAVA_OPT} -jar ${BASE_PATH}/lib/${APPLICATION_JAR} --spring.config.location=${CONFIG_DIR} --logging.config=${CONFIG_DIR}logback.xml > ${LOG_PATH} 2>&1 &\n"
#======================================================================
# 执行启动命令:后台启动项目,并将日志输出到项目根目录下的logs文件夹下
#======================================================================
nohup java ${JAVA_OPT} -jar ${BASE_PATH}/lib/${APPLICATION_JAR} --spring.config.location=${CONFIG_DIR} --logging.config=${CONFIG_DIR}logback.xml > ${LOG_PATH} 2>&1 &
# 进程ID
PID=$(ps -ef | grep ${APPLICATION_JAR} | grep -v grep | awk '{ print $2 }')
STARTUP_LOG="${STARTUP_LOG}application pid: ${PID}\n"
# 启动日志追加到启动日志文件中
echo -e ${STARTUP_LOG} >> ${LOG_STARTUP_PATH}
# 打印启动日志
echo -e ${STARTUP_LOG}
# 打印项目日志
tail -f ${LOG_PATH}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>parent</artifactId>
<version>2.0</version>
</parent>
<artifactId>distribution</artifactId>
<name>distribution</name>
<description>项目打包模块</description>
<profiles>
<profile>
<id>release</id>
<dependencies>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>bin</directory>
<filtering>true</filtering>
<targetPath>bin</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<configuration>
<finalName>${assembly.name}</finalName>
<descriptors>
<descriptor>release.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release-admin</id>
<build>
<resources>
<resource>
<directory>admin</directory>
<filtering>true</filtering>
<targetPath>admin</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<configuration>
<finalName>${assembly.name}-admin</finalName>
<descriptors>
<descriptor>release-admin.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<assembly>
<id>admin</id>
<includeBaseDirectory>true</includeBaseDirectory>
<formats>
<format>dir</format>
<format>tar.gz</format>
<format>zip</format>
</formats>
<fileSets>
<!--
0755->即用户具有读/写/执行权限,组用户和其它用户具有读写权限;
0644->即用户具有读写权限,组用户和其它用户具有只读权限;
-->
<fileSet>
<directory>target/classes/admin/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>admin/config</directory>
<outputDirectory>config</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>admin/logs</directory>
<outputDirectory>logs</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>../admin/target/classes</directory>
<includes>
<include>application.yml</include>
</includes>
<outputDirectory>config</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>../admin/target</directory>
<includes>
<include>*.jar</include>
</includes>
<outputDirectory>lib</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>../</directory>
<includes>
<include>LICENSE</include>
<include>README.md</include>
</includes>
</fileSet>
</fileSets>
</assembly>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019-2029 geekidea(https://github.com/geekidea)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<assembly>
<id>server</id>
<includeBaseDirectory>true</includeBaseDirectory>
<formats>
<format>dir</format>
<format>tar.gz</format>
<format>zip</format>
</formats>
<fileSets>
<!--
0755->即用户具有读/写/执行权限,组用户和其它用户具有读写权限;
0644->即用户具有读写权限,组用户和其它用户具有只读权限;
-->
<fileSet>
<directory>target/classes/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<includes>
<include>config/**</include>
</includes>
</fileSet>
<fileSet>
<includes>
<include>logs/**</include>
</includes>
</fileSet>
<fileSet>
<directory>../config/target/classes/config</directory>
<outputDirectory>config</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>../</directory>
<includes>
<include>LICENSE</include>
<include>README.md</include>
</includes>
</fileSet>
</fileSets>
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>io.geekidea.springbootplus:bootstrap</include>
</includes>
<binaries>
<!-- 将依赖的jar包抽取到lib目录中 -->
<outputDirectory>lib/</outputDirectory>
<unpack>false</unpack>
<dependencySets>
<dependencySet>
<outputDirectory>lib/</outputDirectory>
</dependencySet>
</dependencySets>
</binaries>
</moduleSet>
</moduleSets>
</assembly>
\ No newline at end of file
# 使用openjdk:8-jre为基础镜像
FROM openjdk:8-jre
# 拷贝jar文件
COPY bootstrap-2.0.jar my.jar
# 运行jar,$JAVA_OPTS变量启动时指定相关环境参数
ENTRYPOINT ["java","-Dspring.profiles.active=test","-jar","my.jar"]
# 暴露端口
EXPOSE 8888
# 1. (构建镜像) 将jar文件复制到此位置
# docker rmi vike
# docker build -t xxxxxx-java .
# 2. (运行容器) --link为连接的mysql redis容器
# docker run --name xxx-java -d -p 8888:8888 --link mysql57 --link redis6 xxxxxx-java
# docker安装
## nginx
```
1.运行一个nginx容器
docker run --name my-nginx -d nginx
2.将默认nginx默认配置文件copy到宿主机,后面需要用到做为默认配置挂载到容器中
docker cp my-nginx/
```
## redis
```
```
## mysql
```
```
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 1. 下载或更新spring-boot-plus版本库
# 2. maven打包
# 3. 停服
# 4. 备份
# 5. 运行spring-boot-plus
# author: geekidea
# date: 2020-3-25
#======================================================================
NOW=$(date --date='0 days ago' "+%Y-%m-%d-%H-%M-%S")
echo "${NOW}"
PULL_RESULT=""
IS_UPDATE=0
# 项目名称
PROJECT_NAME="spring-boot-plus"
# 版本库路径
REPO_URL="https://gitee.com/geekidea/spring-boot-plus.git"
# 打包文件名称
ASSEMBLY_NAME="spring-boot-plus-server-2.0.tar.gz"
# 服务目录名称
SERVER_DIR="spring-boot-plus-server-2.0"
# 发布的GIT分支名称
DEPLOY_BRANCH=dev
# 发布的Maven Profile
ACTIVE_PROFILE=test
# 1. 下载或更新spring-boot-plus版本库
# 先判断当前目录下是否有spring-boot-plus目录
# 如果有,则执行git pull
# 如果没有,则clone
if [ ! -d "${PROJECT_NAME}" ]; then
git clone ${REPO_URL}
cd ${PROJECT_NAME}
else
cd ${PROJECT_NAME}
# 拉取代码,并获取结果判断,是否有新的代码更新,如果有,则备份之前的server,否则替换
PULL_RESULT=$(git pull)
echo "${PULL_RESULT}"
if [[ ! $PULL_RESULT == *up-to-date* ]]
then
echo "update code..."
IS_UPDATE=1
fi
fi
pwd
git checkout ${DEPLOY_BRANCH}
git branch
# 2. maven打包
mvn clean install -P release,${ACTIVE_PROFILE}
mvn clean package -P release,${ACTIVE_PROFILE}
pwd
# 判断是否生成成功
if [ ! -f "distribution/target/${ASSEMBLY_NAME}" ]; then
echo "maven build fail"
exit
fi
# 3. 停服
cd ..
pwd
if [ -d "${SERVER_DIR}" ]; then
sh ${SERVER_DIR}/bin/shutdown.sh
fi
# 4. 复制spring-boot-plus-server-assembly.tar.gz到项目同级目录下
# 备份之前的server
if [ ! -d "${SERVER_DIR}-back" ]; then
mkdir ${SERVER_DIR}-back
fi
if [[ -d "${SERVER_DIR}" ]]
then
echo "back ${SERVER_DIR}..."
mv ${SERVER_DIR} ${SERVER_DIR}-back/${SERVER_DIR}-back-"${NOW}"
echo "back success"
fi
echo "copy ${ASSEMBLY_NAME}..."
# 复制到项目同级目录,如果有,则覆盖
cp -r -f ${PROJECT_NAME}/distribution/target/${ASSEMBLY_NAME} ${ASSEMBLY_NAME}
echo "copy success"
pwd
# 5. 运行spring-boot-plus
tar -zxvf ${ASSEMBLY_NAME}
echo "tar.gz decompression success"
pwd
sh ${SERVER_DIR}/bin/shutdown.sh
sh ${SERVER_DIR}/bin/startup.sh
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 使用阿里云镜像
#
# author: geekidea
# date: 2020-3-25
#======================================================================
yum clean all
yum update
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 先下载按照脚本,多次执行该脚本,会覆盖以下下载的文件
# 快速安装jdk/git/maven/redis/mysql
#
# author: geekidea
# date: 2019-8-29
#======================================================================
# 下载脚本
wget -O install-all.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-all.sh
wget -O install-jdk.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-jdk.sh
wget -O install-git.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-git.sh
wget -O install-maven.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-maven.sh
wget -O install-redis.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-redis.sh
wget -O install-mysql.sh https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/bin/install/install-mysql.sh
wget -O mysql_spring_boot_plus.sql https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/db/mysql_spring_boot_plus.sql
# 执行安装所有
sh install-all.sh
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 快速安装jdk/git/maven/redis/mysql
#
# author: geekidea
# date: 2019-8-29
#======================================================================
sh install-jdk.sh
sh install-git.sh
sh install-maven.sh
sh install-redis.sh
sh install-mysql.sh
\ No newline at end of file
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 快速安装GIT
# CentOS7 中已成功验证
# 使用yum方式安装
#
# author: sy
# date: 2019-8-29
#======================================================================
hasGit(){
GIT_VERSION=$(git --version)
echo "${GIT_VERSION}"
if [[ $GIT_VERSION == *version* ]]
then
return 1;
fi
return 0;
}
hasGit
if [ $? != 1 ]
then
echo "Not Found git"
echo "Installing Git..."
yum install -y git
hasGit
if [ $? != 1 ]
then
echo "Install maven Fail"
fi
fi
echo ""
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 快速安装JDK
# CentOS7 中已成功验证
# 使用yum方式安装
#
# author: sy
# date: 2019-8-29
#======================================================================
hasJdk(){
RESULT=$(pgrep java)
if [[ ! $RESULT ]]
then
return 0;
fi
return 1;
}
hasJdk
if [ $? != 1 ]
then
echo "Not Found jdk"
echo "Installing jdk..."
yum install -y java-1.8.0-openjdk
hasJdk
if [ $? != 1 ]
then
echo "Install jdk Fail"
fi
fi
java -version
echo ""
#! /bin/shell
# Copyright 2019-2029 geekidea(https://github.com/geekidea)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#======================================================================
# 快速安装maven shell脚本
#
# author: chenkun
# date: 2019-08-30
#======================================================================
hasMaven(){
MAVEN_VERSION=$(mvn -version)
echo "${MAVEN_VERSION}"
if [[ ! $MAVEN_VERSION ]]
then
return 0;
fi
return 1;
}
hasMaven
if [ $? != 1 ]
then
echo "Not Found maven"
echo "Installing maven..."
# 下载 maven aliyun mirror settings.xml
wget -O settings.xml https://raw.githubusercontent.com/geekidea/spring-boot-plus/master/docs/config/settings.xml
yum install -y maven
hasMaven
if [ $? == 1 ]
then
echo "Config Aliyun Maven Mirror..."
rm -rf /etc/maven/settings.xml
cp settings.xml /etc/maven/
mvn -version
else
echo "Install maven Fail"
fi
fi
echo ""
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment