Upgrade dependencies (#1184)

* Update spring boot version and source compatibility version

* Rearrange some configs

* Upgrade swagger to 3.0.0

* Make swagger configurable

* Make swagger-ui.html path backward compatible

* Change jdk version into 11 in ci/cd scripts and Dockerfile
pull/1190/head
John Niang 2020-12-08 01:20:19 +08:00 committed by GitHub
parent 7c0be43c0d
commit 30e28b5257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 167 additions and 121 deletions

View File

@ -13,10 +13,10 @@ jobs:
- uses: actions/checkout@v1
with:
submodules: true
- name: Set up JDK 1.8
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 1.8
java-version: 11
- name: Cache Gradle
id: cache-gradle
uses: actions/cache@v1

View File

@ -1,6 +1,6 @@
language: java
jdk:
- oraclejdk8
- openjdk:11
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/

View File

@ -1,4 +1,4 @@
FROM adoptopenjdk/openjdk8-openj9
FROM adoptopenjdk/openjdk11-openj9
VOLUME /tmp
ARG JAR_FILE=build/libs/halo.jar

View File

@ -1,5 +1,5 @@
plugins {
id "org.springframework.boot" version "2.3.4.RELEASE"
id "org.springframework.boot" version "2.4.0"
id "io.spring.dependency-management" version "1.0.10.RELEASE"
id "checkstyle"
id "java"
@ -11,7 +11,7 @@ description = "Halo, An excellent open source blog publishing application."
java {
archivesBaseName = "halo"
sourceCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_11
}
repositories {
@ -50,7 +50,7 @@ ext {
baiduSdkVersion = "0.10.36"
qcloudSdkVersion = "5.6.25"
minioSdkVersion = "7.1.4"
swaggerVersion = "2.9.2"
swaggerVersion = "3.0.0"
commonsFileUploadVersion = "1.4"
commonsLangVersion = "3.10"
httpclientVersion = "4.5.12"
@ -91,8 +91,7 @@ dependencies {
implementation "com.qcloud:cos_api:$qcloudSdkVersion"
implementation "com.huaweicloud:esdk-obs-java:$huaweiObsVersion"
implementation "io.minio:minio:$minioSdkVersion"
implementation "io.springfox:springfox-swagger2:$swaggerVersion"
implementation "io.springfox:springfox-swagger-ui:$swaggerVersion"
implementation "io.springfox:springfox-boot-starter:$swaggerVersion"
implementation "commons-fileupload:commons-fileupload:$commonsFileUploadVersion"
implementation "org.apache.commons:commons-lang3:$commonsLangVersion"
implementation "org.apache.httpcomponents:httpclient:$httpclientVersion"

View File

@ -2,13 +2,6 @@ package run.halo.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import run.halo.app.repository.base.BaseRepositoryImpl;
/**
* Halo main class.
@ -16,23 +9,16 @@ import run.halo.app.repository.base.BaseRepositoryImpl;
* @author ryanwang
* @date 2017-11-14
*/
@SpringBootApplication(exclude = { MultipartAutoConfiguration.class })
@EnableAsync
@EnableScheduling
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class)
public class Application extends SpringBootServletInitializer {
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// Customize the spring config location
System.setProperty("spring.config.additional-location", "file:${user.home}/.halo/,file:${user.home}/halo-dev/");
System.setProperty("spring.config.additional-location",
"optional:file:${user.home}/.halo/,optional:file:${user.home}/halo-dev/");
// Run application
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
System.setProperty("spring.config.additional-location", "file:${user.home}/.halo/,file:${user.home}/halo-dev/");
return application.sources(Application.class);
}
}

View File

@ -8,11 +8,18 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import run.halo.app.cache.*;
import run.halo.app.cache.AbstractStringCacheStore;
import run.halo.app.cache.InMemoryCacheStore;
import run.halo.app.cache.LevelCacheStore;
import run.halo.app.cache.RedisCacheStore;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.repository.base.BaseRepositoryImpl;
import run.halo.app.utils.HttpClientUtils;
import java.security.KeyManagementException;
@ -24,9 +31,12 @@ import java.security.NoSuchAlgorithmException;
*
* @author johnniang
*/
@Configuration
@EnableConfigurationProperties(HaloProperties.class)
@Slf4j
@EnableAsync
@EnableScheduling
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HaloProperties.class)
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class)
public class HaloConfiguration {
@Autowired

View File

@ -5,7 +5,11 @@ import freemarker.core.TemplateClassResolver;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jackson.JsonComponentModule;
import org.springframework.context.annotation.Bean;
@ -22,8 +26,9 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
@ -43,7 +48,7 @@ import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
import static run.halo.app.utils.HaloUtils.*;
/**
* Spring mvc configuration.
* Halo mvc configuration.
*
* @author ryanwang
* @date 2018-01-02
@ -51,17 +56,21 @@ import static run.halo.app.utils.HaloUtils.*;
@Slf4j
@Configuration
@EnableConfigurationProperties(MultipartProperties.class)
public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
@ImportAutoConfiguration(exclude = MultipartAutoConfiguration.class)
public class HaloMvcConfiguration implements WebMvcConfigurer {
private static final String FILE_PROTOCOL = "file:///";
@Value("${springfox.documentation.swagger-ui.base-url:}")
private String swaggerBaseUrl;
private final PageableHandlerMethodArgumentResolver pageableResolver;
private final SortHandlerMethodArgumentResolver sortResolver;
private final HaloProperties haloProperties;
public WebMvcAutoConfiguration(PageableHandlerMethodArgumentResolver pageableResolver,
public HaloMvcConfiguration(PageableHandlerMethodArgumentResolver pageableResolver,
SortHandlerMethodArgumentResolver sortResolver,
HaloProperties haloProperties) {
this.pageableResolver = pageableResolver;
@ -69,77 +78,13 @@ public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
this.haloProperties = haloProperties;
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.ifPresent(converter -> {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
JsonComponentModule module = new JsonComponentModule();
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
ObjectMapper objectMapper = builder.modules(module).build();
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
});
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
resolvers.add(pageableResolver);
resolvers.add(sortResolver);
}
/**
* Configuring static resource path
*
* @param registry registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + ensureSuffix(haloProperties.getWorkDir(), FILE_SEPARATOR);
// register /** resource handler.
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/admin/")
.addResourceLocations(workDir + "static/");
// register /themes/** resource handler.
registry.addResourceHandler("/themes/**")
.addResourceLocations(workDir + "templates/themes/");
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
String adminPathPattern = ensureSuffix(haloProperties.getAdminPath(), URL_SEPARATOR) + "**";
registry.addResourceHandler(uploadUrlPattern)
.setCacheControl(CacheControl.maxAge(7L, TimeUnit.DAYS))
.addResourceLocations(workDir + "upload/");
registry.addResourceHandler(adminPathPattern)
.addResourceLocations("classpath:/admin/");
if (!haloProperties.isDocDisabled()) {
// If doc is enable
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new StringToEnumConverterFactory());
}
/**
* Configuring freemarker template file path.
*
* @return new FreeMarkerConfigurer
*/
@Bean
public FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties) throws IOException, TemplateException {
FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties) throws IOException, TemplateException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPaths(FILE_PROTOCOL + haloProperties.getWorkDir() + "templates/", "classpath:/templates/");
configurer.setDefaultEncoding("UTF-8");
@ -170,7 +115,7 @@ public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
* @return new multipartResolver
*/
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver(MultipartProperties multipartProperties) {
MultipartResolver multipartResolver(MultipartProperties multipartProperties) {
MultipartConfigElement multipartConfigElement = multipartProperties.createMultipartConfig();
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
@ -183,6 +128,85 @@ public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
return resolver;
}
@Bean
WebMvcRegistrations webMvcRegistrations() {
return new WebMvcRegistrations() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new HaloRequestMappingHandlerMapping(haloProperties);
}
};
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.ifPresent(converter -> {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
JsonComponentModule module = new JsonComponentModule();
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
ObjectMapper objectMapper = builder.modules(module).build();
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
});
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
resolvers.add(pageableResolver);
resolvers.add(sortResolver);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// for backward compatibility
registry.addViewController("/swagger-ui.html")
.setViewName("redirect:" + swaggerBaseUrl + "/swagger-ui/");
}
/**
* Configuring static resource path
*
* @param registry registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + ensureSuffix(haloProperties.getWorkDir(), FILE_SEPARATOR);
// register /** resource handler.
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/admin/")
.addResourceLocations(workDir + "static/");
// register /themes/** resource handler.
registry.addResourceHandler("/themes/**")
.addResourceLocations(workDir + "templates/themes/");
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
String adminPathPattern = ensureSuffix(haloProperties.getAdminPath(), URL_SEPARATOR) + "**";
registry.addResourceHandler(uploadUrlPattern)
.setCacheControl(CacheControl.maxAge(7L, TimeUnit.DAYS))
.addResourceLocations(workDir + "upload/");
registry.addResourceHandler(adminPathPattern)
.addResourceLocations("classpath:/admin/");
// If doc is enable
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new StringToEnumConverterFactory());
}
/**
* Configuring view resolver
*
@ -201,9 +225,4 @@ public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
registry.viewResolver(resolver);
}
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new HaloRequestMappingHandlerMapping(haloProperties);
}
}

View File

@ -25,7 +25,8 @@ import static run.halo.app.utils.HaloUtils.ensureBoth;
* @date 2020-03-24
*/
@Slf4j
public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping implements ApplicationListener<StaticStorageChangedEvent> {
public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping
implements ApplicationListener<StaticStorageChangedEvent> {
private final Set<String> blackPatterns = new HashSet<>(16);
@ -63,6 +64,7 @@ public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMappi
blackPatterns.add("/assets/**");
blackPatterns.add("/color.less");
blackPatterns.add("/swagger-ui.html");
blackPatterns.add("/swagger-ui/**");
blackPatterns.add("/csrf");
blackPatterns.add("/webjars/**");
blackPatterns.add(uploadUrlPattern);
@ -93,4 +95,5 @@ public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMappi
log.error("Failed to refresh static directory mapping", e);
}
}
}

View File

@ -3,6 +3,7 @@ package run.halo.app.config;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@ -21,9 +22,7 @@ import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.documentation.swagger.web.*;
import java.lang.reflect.Type;
import java.time.temporal.Temporal;
@ -39,9 +38,12 @@ import static springfox.documentation.schema.AlternateTypeRules.newRule;
*
* @author johnniang
*/
@EnableSwagger2
@Configuration
@Slf4j
@Configuration
@ConditionalOnProperty(
value = "springfox.documentation.enabled",
havingValue = "true",
matchIfMissing = true)
public class SwaggerConfiguration {
private final HaloProperties haloProperties;
@ -60,16 +62,11 @@ public class SwaggerConfiguration {
@Bean
public Docket haloDefaultApi() {
if (haloProperties.isDocDisabled()) {
log.debug("Doc has been disabled");
}
return buildApiDocket("run.halo.app.content.api",
"run.halo.app.controller.content.api",
"/api/content/**")
.securitySchemes(contentApiKeys())
.securityContexts(contentSecurityContext())
.enable(!haloProperties.isDocDisabled());
.securityContexts(contentSecurityContext());
}
@Bean
@ -82,8 +79,7 @@ public class SwaggerConfiguration {
"run.halo.app.controller.admin",
"/api/admin/**")
.securitySchemes(adminApiKeys())
.securityContexts(adminSecurityContext())
.enable(!haloProperties.isDocDisabled());
.securityContexts(adminSecurityContext());
}
@Bean
@ -99,6 +95,27 @@ public class SwaggerConfiguration {
.build();
}
@Bean
UiConfiguration uiConfig() {
return UiConfigurationBuilder.builder()
.deepLinking(true)
.displayOperationId(false)
.defaultModelsExpandDepth(1)
.defaultModelExpandDepth(1)
.defaultModelRendering(ModelRendering.EXAMPLE)
.displayRequestDuration(false)
.docExpansion(DocExpansion.NONE)
.filter(false)
.maxDisplayedTags(null)
.operationsSorter(OperationsSorter.ALPHA)
.showExtensions(false)
.showCommonExtensions(false)
.tagsSorter(TagsSorter.ALPHA)
.supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS)
.validatorUrl(null)
.build();
}
private Docket buildApiDocket(@NonNull String groupName, @NonNull String basePackage, @NonNull String antPattern) {
Assert.hasText(groupName, "Group name must not be blank");
Assert.hasText(basePackage, "Base package must not be blank");
@ -119,7 +136,7 @@ public class SwaggerConfiguration {
.directModelSubstitute(Temporal.class, String.class);
}
private List<ApiKey> adminApiKeys() {
private List<SecurityScheme> adminApiKeys() {
return Arrays.asList(
new ApiKey("Token from header", ADMIN_TOKEN_HEADER_NAME, In.HEADER.name()),
new ApiKey("Token from query", ADMIN_TOKEN_QUERY_NAME, In.QUERY.name())
@ -135,7 +152,7 @@ public class SwaggerConfiguration {
);
}
private List<ApiKey> contentApiKeys() {
private List<SecurityScheme> contentApiKeys() {
return Arrays.asList(
new ApiKey("Access key from header", API_ACCESS_KEY_HEADER_NAME, In.HEADER.name()),
new ApiKey("Access key from query", API_ACCESS_KEY_QUERY_NAME, In.QUERY.name())

View File

@ -55,6 +55,10 @@ logging:
file:
path: ${user.home}/halo-demo/logs
springfox:
documentation:
enabled: true
halo:
download-timeout: 5m
doc-disabled: false

View File

@ -58,6 +58,10 @@ logging:
file:
path: ${user.home}/halo-dev/logs
springfox:
documentation:
enabled: true
halo:
doc-disabled: false
production-env: false

View File

@ -50,6 +50,10 @@ logging:
file:
path: ${user.home}/.halo/logs
springfox:
documentation:
enabled: false
halo:
download-timeout: 5m
cache: memory