mirror of
https://github.com/chillzhuang/blade-tool
synced 2024-12-23 01:29:29 +08:00
🎉 4.0.0.RELEASE 升级 SpringBoot3 SpringCloud2023 JDK17
This commit is contained in:
parent
45d7b20b75
commit
4bbcf53e63
@ -1,7 +1,8 @@
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Cloud-2021-blue.svg" alt="Coverage Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.10-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/JDK-17+-green.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Cloud-2023-blue.svg" alt="Coverage Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg" alt="Downloads">
|
||||
</p>
|
||||
|
||||
## SpringBlade微服务开发平台
|
||||
|
@ -19,7 +19,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
<version>${maven-flatten.version}</version>
|
||||
<version>${maven.flatten.version}</version>
|
||||
<configuration>
|
||||
<updatePomFile>true</updatePomFile>
|
||||
<flattenMode>oss</flattenMode>
|
||||
|
@ -62,38 +62,27 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-typehandlers-jsr310</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
<!-- Ehcache -->
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>2.10.5</version>
|
||||
</dependency>
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.2.19</version>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- MySQL -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.32</version>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<!-- PostgreSql -->
|
||||
<!--<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -23,7 +23,7 @@ import org.springblade.core.tool.api.R;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -21,8 +21,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
@ -69,7 +69,6 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
<version>${alibaba.nacos.version}</version>
|
||||
</dependency>
|
||||
<!-- Sentinel -->
|
||||
<dependency>
|
||||
@ -81,7 +80,6 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83_noneautotype</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -25,7 +25,7 @@ import org.springblade.core.cloud.sentinel.BladeSentinelInvocationHandler;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.openfeign.FallbackFactory;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.cloud.openfeign.FeignContext;
|
||||
import org.springframework.cloud.openfeign.FeignClientFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@ -50,11 +50,10 @@ public class BladeFeignSentinel {
|
||||
public static final class Builder extends Feign.Builder implements ApplicationContextAware {
|
||||
private Contract contract = new Contract.Default();
|
||||
private ApplicationContext applicationContext;
|
||||
private FeignContext feignContext;
|
||||
private FeignClientFactory feignContext;
|
||||
|
||||
@Override
|
||||
public Feign.Builder invocationHandlerFactory(
|
||||
InvocationHandlerFactory invocationHandlerFactory) {
|
||||
public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ public class BladeFeignSentinel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Feign build() {
|
||||
public Feign internalBuild() {
|
||||
super.invocationHandlerFactory(new InvocationHandlerFactory() {
|
||||
@SneakyThrows
|
||||
@Override
|
||||
@ -115,13 +114,13 @@ public class BladeFeignSentinel {
|
||||
}
|
||||
});
|
||||
super.contract(new SentinelContractHolder(contract));
|
||||
return super.build();
|
||||
return super.internalBuild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
feignContext = this.applicationContext.getBean(FeignContext.class);
|
||||
feignContext = this.applicationContext.getBean(FeignClientFactory.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import org.springblade.core.secure.utils.SecureUtil;
|
||||
import org.springblade.core.tool.utils.Charsets;
|
||||
import org.springblade.core.tool.utils.UrlUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 用户信息获取器
|
||||
|
@ -18,7 +18,7 @@ package org.springblade.core.cloud.header;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Blade 用户信息获取器,用于请求头传递
|
||||
|
@ -23,7 +23,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.cloud.http;
|
||||
|
||||
import org.springblade.core.cloud.props.BladeFeignHeadersProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* http 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties({BladeHttpProperties.class, BladeFeignHeadersProperties.class})
|
||||
public class BladeHttpConfiguration {
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.cloud.http;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springblade.core.launch.log.BladeLogLevel;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* http 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@RefreshScope
|
||||
@ConfigurationProperties("blade.http")
|
||||
public class BladeHttpProperties {
|
||||
/**
|
||||
* 最大连接数,默认:200
|
||||
*/
|
||||
private int maxConnections = 200;
|
||||
/**
|
||||
* 连接存活时间,默认:900L
|
||||
*/
|
||||
private long timeToLive = 900L;
|
||||
/**
|
||||
* 连接池存活时间单位,默认:秒
|
||||
*/
|
||||
private TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
/**
|
||||
* 链接超时,默认:2000毫秒
|
||||
*/
|
||||
private int connectionTimeout = 2000;
|
||||
/**
|
||||
* 是否支持重定向,默认:true
|
||||
*/
|
||||
private boolean followRedirects = true;
|
||||
/**
|
||||
* 关闭证书校验
|
||||
*/
|
||||
private boolean disableSslValidation = true;
|
||||
/**
|
||||
* 日志级别
|
||||
*/
|
||||
private BladeLogLevel level = BladeLogLevel.NONE;
|
||||
}
|
@ -17,10 +17,10 @@ package org.springblade.core.cloud.http;
|
||||
|
||||
import okhttp3.*;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.GzipSource;
|
||||
import org.springblade.core.launch.log.BladeLogLevel;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
@ -29,8 +29,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static okhttp3.internal.platform.Platform.INFO;
|
||||
|
||||
/**
|
||||
* An OkHttp interceptor which logs request and response information. Can be applied as an
|
||||
* {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain
|
||||
@ -42,121 +40,46 @@ import static okhttp3.internal.platform.Platform.INFO;
|
||||
*/
|
||||
public final class HttpLoggingInterceptor implements Interceptor {
|
||||
private static final Charset UTF8 = StandardCharsets.UTF_8;
|
||||
|
||||
public enum Level {
|
||||
/**
|
||||
* No logs.
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* Logs request and response lines.
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1 (3-byte body)
|
||||
*
|
||||
* <-- 200 OK (22ms, 6-byte body)
|
||||
* }</pre>
|
||||
*/
|
||||
BASIC,
|
||||
/**
|
||||
* Logs request and response lines and their respective headers.
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1
|
||||
* Host: example.com
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 3
|
||||
* --> END POST
|
||||
*
|
||||
* <-- 200 OK (22ms)
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 6
|
||||
* <-- END HTTP
|
||||
* }</pre>
|
||||
*/
|
||||
HEADERS,
|
||||
/**
|
||||
* Logs request and response lines and their respective headers and bodies (if present).
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1
|
||||
* Host: example.com
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 3
|
||||
*
|
||||
* Hi?
|
||||
* --> END POST
|
||||
*
|
||||
* <-- 200 OK (22ms)
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 6
|
||||
*
|
||||
* Hello!
|
||||
* <-- END HTTP
|
||||
* }</pre>
|
||||
*/
|
||||
BODY
|
||||
}
|
||||
private final Logger logger;
|
||||
private volatile BladeLogLevel level = BladeLogLevel.NONE;
|
||||
|
||||
public interface Logger {
|
||||
/**
|
||||
* log
|
||||
*
|
||||
* @param message message
|
||||
*/
|
||||
void log(String message);
|
||||
|
||||
/**
|
||||
* A {@link Logger} defaults output appropriate for the current platform.
|
||||
*/
|
||||
Logger DEFAULT = message -> Platform.get().log(message, INFO, null);
|
||||
}
|
||||
|
||||
public HttpLoggingInterceptor() {
|
||||
this(Logger.DEFAULT);
|
||||
}
|
||||
|
||||
public HttpLoggingInterceptor(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
private volatile Level level = Level.NONE;
|
||||
|
||||
/**
|
||||
* Change the level at which this interceptor logs.
|
||||
*
|
||||
* @param level log Level
|
||||
* @return HttpLoggingInterceptor
|
||||
*/
|
||||
public HttpLoggingInterceptor setLevel(Level level) {
|
||||
Objects.requireNonNull(level, "level == null. Use Level.NONE instead.");
|
||||
this.level = level;
|
||||
public HttpLoggingInterceptor setLevel(BladeLogLevel level) {
|
||||
this.level = Objects.requireNonNull(level, "level == null. Use Level.NONE instead.");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Level getLevel() {
|
||||
public BladeLogLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
private String gzip = "gzip";
|
||||
private String contentEncoding = "Content-Encoding";
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Level level = this.level;
|
||||
BladeLogLevel level = this.level;
|
||||
|
||||
Request request = chain.request();
|
||||
if (level == Level.NONE) {
|
||||
if (level == BladeLogLevel.NONE) {
|
||||
return chain.proceed(request);
|
||||
}
|
||||
|
||||
boolean logBody = level == Level.BODY;
|
||||
boolean logHeaders = logBody || level == Level.HEADERS;
|
||||
boolean logBody = level == BladeLogLevel.BODY;
|
||||
boolean logHeaders = logBody || level == BladeLogLevel.HEADERS;
|
||||
|
||||
RequestBody requestBody = request.body();
|
||||
boolean hasRequestBody = requestBody != null;
|
||||
@ -239,7 +162,8 @@ public final class HttpLoggingInterceptor implements Interceptor {
|
||||
|
||||
if (logHeaders) {
|
||||
Headers headers = response.headers();
|
||||
for (int i = 0, count = headers.size(); i < count; i++) {
|
||||
int count = headers.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
logger.log(headers.name(i) + ": " + headers.value(i));
|
||||
}
|
||||
|
||||
@ -251,10 +175,10 @@ public final class HttpLoggingInterceptor implements Interceptor {
|
||||
BufferedSource source = responseBody.source();
|
||||
// Buffer the entire body.
|
||||
source.request(Long.MAX_VALUE);
|
||||
Buffer buffer = source.buffer();
|
||||
Buffer buffer = source.getBuffer();
|
||||
|
||||
Long gzippedLength = null;
|
||||
if (gzip.equalsIgnoreCase(headers.get(contentEncoding))) {
|
||||
if ("gzip".equalsIgnoreCase(headers.get("Content-Encoding"))) {
|
||||
gzippedLength = buffer.size();
|
||||
GzipSource gzippedResponseBody = null;
|
||||
try {
|
||||
@ -301,14 +225,12 @@ public final class HttpLoggingInterceptor implements Interceptor {
|
||||
* Returns true if the body in question probably contains human readable text. Uses a small sample
|
||||
* of code points to detect unicode control characters commonly used in binary file signatures.
|
||||
*/
|
||||
private static int plainCnt = 16;
|
||||
|
||||
private static boolean isPlaintext(Buffer buffer) {
|
||||
try {
|
||||
Buffer prefix = new Buffer();
|
||||
long byteCount = buffer.size() < 64 ? buffer.size() : 64;
|
||||
buffer.copyTo(prefix, 0, byteCount);
|
||||
for (int i = 0; i < plainCnt; i++) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (prefix.exhausted()) {
|
||||
break;
|
||||
}
|
||||
|
@ -17,29 +17,38 @@ package org.springblade.core.cloud.http;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springblade.core.cloud.header.BladeFeignAccountGetter;
|
||||
import org.springblade.core.cloud.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springblade.core.cloud.props.BladeFeignHeadersProperties;
|
||||
import org.springblade.core.tool.ssl.DisableValidationTrustManager;
|
||||
import org.springblade.core.tool.ssl.TrustAllHostNames;
|
||||
import org.springblade.core.tool.utils.Charsets;
|
||||
import org.springblade.core.tool.utils.Holder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
|
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -48,84 +57,53 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@AutoConfiguration
|
||||
@AllArgsConstructor
|
||||
@ConditionalOnClass(okhttp3.OkHttpClient.class)
|
||||
@EnableConfigurationProperties(BladeFeignHeadersProperties.class)
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
@ConditionalOnProperty(value = "blade.http.enabled", matchIfMissing = true)
|
||||
public class RestTemplateConfiguration {
|
||||
private final ObjectMapper objectMapper;
|
||||
private final BladeHttpProperties properties;
|
||||
|
||||
/**
|
||||
* dev, test 环境打印出BODY
|
||||
* okhttp3 请求日志拦截器
|
||||
*
|
||||
* @return HttpLoggingInterceptor
|
||||
*/
|
||||
@Bean("httpLoggingInterceptor")
|
||||
@Profile({"dev", "test"})
|
||||
public HttpLoggingInterceptor testLoggingInterceptor() {
|
||||
@Bean
|
||||
public HttpLoggingInterceptor loggingInterceptor() {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new OkHttpSlf4jLogger());
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* ontest 环境 打印 请求头
|
||||
* @return HttpLoggingInterceptor
|
||||
*/
|
||||
@Bean("httpLoggingInterceptor")
|
||||
@Profile("ontest")
|
||||
public HttpLoggingInterceptor onTestLoggingInterceptor() {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new OkHttpSlf4jLogger());
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* prod 环境只打印请求url
|
||||
* @return HttpLoggingInterceptor
|
||||
*/
|
||||
@Bean("httpLoggingInterceptor")
|
||||
@Profile("prod")
|
||||
public HttpLoggingInterceptor prodLoggingInterceptor() {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new OkHttpSlf4jLogger());
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
|
||||
interceptor.setLevel(properties.getLevel());
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* okhttp3 链接池配置
|
||||
* @param connectionPoolFactory 链接池配置
|
||||
* @param httpClientProperties httpClient配置
|
||||
*
|
||||
* @return okhttp3.ConnectionPool
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(okhttp3.ConnectionPool.class)
|
||||
public okhttp3.ConnectionPool httpClientConnectionPool(
|
||||
FeignHttpClientProperties httpClientProperties,
|
||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
||||
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||
Long timeToLive = httpClientProperties.getTimeToLive();
|
||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
||||
return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
|
||||
@ConditionalOnMissingBean
|
||||
public ConnectionPool httpClientConnectionPool() {
|
||||
int maxTotalConnections = properties.getMaxConnections();
|
||||
long timeToLive = properties.getTimeToLive();
|
||||
TimeUnit ttlUnit = properties.getTimeUnit();
|
||||
return new ConnectionPool(maxTotalConnections, timeToLive, ttlUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置OkHttpClient
|
||||
* @param httpClientFactory httpClient 工厂
|
||||
*
|
||||
* @param connectionPool 链接池配置
|
||||
* @param httpClientProperties httpClient配置
|
||||
* @param interceptor 拦截器
|
||||
* @param interceptor 拦截器
|
||||
* @return OkHttpClient
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
|
||||
public okhttp3.OkHttpClient httpClient(
|
||||
OkHttpClientFactory httpClientFactory,
|
||||
okhttp3.ConnectionPool connectionPool,
|
||||
FeignHttpClientProperties httpClientProperties,
|
||||
HttpLoggingInterceptor interceptor) {
|
||||
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||
return httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation())
|
||||
@ConditionalOnMissingBean
|
||||
public OkHttpClient okHttpClient(ConnectionPool connectionPool, HttpLoggingInterceptor interceptor) {
|
||||
boolean followRedirects = properties.isFollowRedirects();
|
||||
int connectTimeout = properties.getConnectionTimeout();
|
||||
return this.createBuilder(properties.isDisableSslValidation())
|
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
@ -135,6 +113,24 @@ public class RestTemplateConfiguration {
|
||||
.build();
|
||||
}
|
||||
|
||||
private OkHttpClient.Builder createBuilder(boolean disableSslValidation) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
if (disableSslValidation) {
|
||||
try {
|
||||
X509TrustManager disabledTrustManager = DisableValidationTrustManager.INSTANCE;
|
||||
TrustManager[] trustManagers = new TrustManager[]{disabledTrustManager};
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustManagers, Holder.SECURE_RANDOM);
|
||||
SSLSocketFactory disabledSslSocketFactory = sslContext.getSocketFactory();
|
||||
builder.sslSocketFactory(disabledSslSocketFactory, disabledTrustManager);
|
||||
builder.hostnameVerifier(TrustAllHostNames.INSTANCE);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
log.warn("Error setting SSLSocketFactory in OKHttpClient", e);
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplateHeaderInterceptor requestHeaderInterceptor(
|
||||
@Autowired(required = false) @Nullable BladeFeignAccountGetter accountGetter,
|
||||
@ -142,38 +138,57 @@ public class RestTemplateConfiguration {
|
||||
return new RestTemplateHeaderInterceptor(accountGetter,properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通的 RestTemplate,不透传请求头,一般只做外部 http 调用
|
||||
* @param httpClient OkHttpClient
|
||||
* @return RestTemplate
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(RestTemplate.class)
|
||||
public RestTemplate restTemplate(okhttp3.OkHttpClient httpClient) {
|
||||
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory(httpClient));
|
||||
configMessageConverters(restTemplate.getMessageConverters());
|
||||
return restTemplate;
|
||||
@AutoConfiguration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
@ConditionalOnProperty(value = "blade.http.rest-template.enable")
|
||||
public static class RestTemplateAutoConfiguration {
|
||||
private final ApplicationContext context;
|
||||
|
||||
/**
|
||||
* 普通的 RestTemplate,不透传请求头,一般只做外部 http 调用
|
||||
*
|
||||
* @param okHttpClient OkHttpClient
|
||||
* @return RestTemplate
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) {
|
||||
restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient));
|
||||
RestTemplate restTemplate = restTemplateBuilder.build();
|
||||
configMessageConverters(context, restTemplate.getMessageConverters());
|
||||
return restTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持负载均衡的 LbRestTemplate
|
||||
* @param httpClient OkHttpClient
|
||||
* @param interceptor RestTemplateHeaderInterceptor
|
||||
* @return LbRestTemplate
|
||||
*/
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
@ConditionalOnMissingBean(LbRestTemplate.class)
|
||||
public LbRestTemplate lbRestTemplate(okhttp3.OkHttpClient httpClient, RestTemplateHeaderInterceptor interceptor) {
|
||||
LbRestTemplate lbRestTemplate = new LbRestTemplate(new OkHttp3ClientHttpRequestFactory(httpClient));
|
||||
lbRestTemplate.setInterceptors(Collections.singletonList(interceptor));
|
||||
configMessageConverters(lbRestTemplate.getMessageConverters());
|
||||
return lbRestTemplate;
|
||||
@AutoConfiguration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
@ConditionalOnProperty(value = "blade.http.lb-rest-template.enable")
|
||||
public static class LbRestTemplateAutoConfiguration {
|
||||
private final ApplicationContext context;
|
||||
|
||||
/**
|
||||
* 支持负载均衡的 LbRestTemplate
|
||||
*
|
||||
* @param okHttpClient OkHttpClient
|
||||
* @return LbRestTemplate
|
||||
*/
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
@ConditionalOnMissingBean
|
||||
public LbRestTemplate lbRestTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) {
|
||||
restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient));
|
||||
LbRestTemplate restTemplate = restTemplateBuilder.build(LbRestTemplate.class);
|
||||
restTemplate.getInterceptors().add(context.getBean(RestTemplateHeaderInterceptor.class));
|
||||
configMessageConverters(context, restTemplate.getMessageConverters());
|
||||
return restTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
private void configMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
private static void configMessageConverters(ApplicationContext context, List<HttpMessageConverter<?>> converters) {
|
||||
converters.removeIf(x -> x instanceof StringHttpMessageConverter || x instanceof MappingJackson2HttpMessageConverter);
|
||||
converters.add(new StringHttpMessageConverter(Charsets.UTF_8));
|
||||
converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
|
||||
converters.add(new MappingJackson2HttpMessageConverter(context.getBean(ObjectMapper.class)));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springblade.core.cloud.http.client;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.StreamingHttpOutputMessage;
|
||||
import org.springframework.http.client.AbstractClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract base for {@link ClientHttpRequest} that also implement
|
||||
* {@link StreamingHttpOutputMessage}. Ensures that headers and
|
||||
* body are not written multiple times.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 6.1
|
||||
*/
|
||||
public abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequest
|
||||
implements StreamingHttpOutputMessage {
|
||||
|
||||
@Nullable
|
||||
private Body body;
|
||||
|
||||
@Nullable
|
||||
private FastByteArrayOutputStream bodyStream;
|
||||
|
||||
|
||||
@Override
|
||||
protected final OutputStream getBodyInternal(HttpHeaders headers) {
|
||||
Assert.state(this.body == null, "Invoke either getBody or setBody; not both");
|
||||
|
||||
if (this.bodyStream == null) {
|
||||
this.bodyStream = new FastByteArrayOutputStream(1024);
|
||||
}
|
||||
return this.bodyStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setBody(Body body) {
|
||||
Assert.notNull(body, "Body must not be null");
|
||||
assertNotExecuted();
|
||||
Assert.state(this.bodyStream == null, "Invoke either getBody or setBody; not both");
|
||||
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
||||
if (this.body == null && this.bodyStream != null) {
|
||||
this.body = outputStream -> this.bodyStream.writeTo(outputStream);
|
||||
}
|
||||
return executeInternal(headers, this.body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract template method that writes the given headers and content to the HTTP request.
|
||||
*
|
||||
* @param headers the HTTP headers
|
||||
* @param body the HTTP body, may be {@code null} if no body was {@linkplain #setBody(Body) set}
|
||||
* @return the response object for the executed request
|
||||
* @since 6.1
|
||||
*/
|
||||
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException;
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springblade.core.cloud.http.client;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okio.BufferedSink;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequest} implementation based on OkHttp 3.x.
|
||||
*
|
||||
* <p>Created via the {@link OkHttp3ClientHttpRequestFactory}.
|
||||
*
|
||||
* @author Luciano Leggieri
|
||||
* @author Arjen Poutsma
|
||||
* @author Roy Clarkson
|
||||
* @since 4.3
|
||||
*/
|
||||
public class OkHttp3ClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
|
||||
private final OkHttpClient client;
|
||||
|
||||
private final URI uri;
|
||||
|
||||
private final HttpMethod method;
|
||||
|
||||
|
||||
public OkHttp3ClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
|
||||
this.client = client;
|
||||
this.uri = uri;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException {
|
||||
|
||||
RequestBody requestBody;
|
||||
if (body != null) {
|
||||
requestBody = new BodyRequestBody(headers, body);
|
||||
} else if (okhttp3.internal.http.HttpMethod.requiresRequestBody(getMethod().name())) {
|
||||
String header = headers.getFirst(HttpHeaders.CONTENT_TYPE);
|
||||
MediaType contentType = (header != null) ? MediaType.parse(header) : null;
|
||||
requestBody = RequestBody.create(contentType, new byte[0]);
|
||||
} else {
|
||||
requestBody = null;
|
||||
}
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(this.uri.toURL());
|
||||
builder.method(this.method.name(), requestBody);
|
||||
headers.forEach((headerName, headerValues) -> {
|
||||
for (String headerValue : headerValues) {
|
||||
builder.addHeader(headerName, headerValue);
|
||||
}
|
||||
});
|
||||
Request request = builder.build();
|
||||
return new OkHttp3ClientHttpResponse(this.client.newCall(request).execute());
|
||||
}
|
||||
|
||||
|
||||
private static class BodyRequestBody extends RequestBody {
|
||||
|
||||
private final HttpHeaders headers;
|
||||
|
||||
private final Body body;
|
||||
|
||||
|
||||
public BodyRequestBody(HttpHeaders headers, Body body) {
|
||||
this.headers = headers;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() {
|
||||
return this.headers.getContentLength();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MediaType contentType() {
|
||||
String contentType = this.headers.getFirst(HttpHeaders.CONTENT_TYPE);
|
||||
if (StringUtils.hasText(contentType)) {
|
||||
return MediaType.parse(contentType);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) throws IOException {
|
||||
this.body.writeTo(sink.outputStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOneShot() {
|
||||
return !this.body.repeatable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springblade.core.cloud.http.client;
|
||||
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} implementation that uses
|
||||
* <a href="https://square.github.io/okhttp/">OkHttp</a> 3.x to create requests.
|
||||
*
|
||||
* @author Luciano Leggieri
|
||||
* @author Arjen Poutsma
|
||||
* @author Roy Clarkson
|
||||
* @since 4.3
|
||||
*/
|
||||
public class OkHttp3ClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {
|
||||
|
||||
private OkHttpClient client;
|
||||
|
||||
private final boolean defaultClient;
|
||||
|
||||
|
||||
/**
|
||||
* Create a factory with a default {@link OkHttpClient} instance.
|
||||
*/
|
||||
public OkHttp3ClientHttpRequestFactory() {
|
||||
this.client = new OkHttpClient();
|
||||
this.defaultClient = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a factory with the given {@link OkHttpClient} instance.
|
||||
*
|
||||
* @param client the client to use
|
||||
*/
|
||||
public OkHttp3ClientHttpRequestFactory(OkHttpClient client) {
|
||||
Assert.notNull(client, "OkHttpClient must not be null");
|
||||
this.client = client;
|
||||
this.defaultClient = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the underlying read timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*/
|
||||
public void setReadTimeout(int readTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying read timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setReadTimeout(Duration readTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.readTimeout(readTimeout)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying write timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*/
|
||||
public void setWriteTimeout(int writeTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying write timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setWriteTimeout(Duration writeTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.writeTimeout(writeTimeout)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying connect timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*/
|
||||
public void setConnectTimeout(int connectTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying connect timeout in milliseconds.
|
||||
* A value of 0 specifies an infinite timeout.
|
||||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setConnectTimeout(Duration connectTimeout) {
|
||||
this.client = this.client.newBuilder()
|
||||
.connectTimeout(connectTimeout)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
|
||||
return new OkHttp3ClientHttpRequest(this.client, uri, httpMethod);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() throws IOException {
|
||||
if (this.defaultClient) {
|
||||
// Clean up the client if we created it in the constructor
|
||||
Cache cache = this.client.cache();
|
||||
if (cache != null) {
|
||||
cache.close();
|
||||
}
|
||||
this.client.dispatcher().executorService().shutdown();
|
||||
this.client.connectionPool().evictAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springblade.core.cloud.http.client;
|
||||
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpResponse} implementation based on OkHttp 3.x.
|
||||
*
|
||||
* @author Luciano Leggieri
|
||||
* @author Arjen Poutsma
|
||||
* @author Roy Clarkson
|
||||
* @since 4.3
|
||||
*/
|
||||
public class OkHttp3ClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private final Response response;
|
||||
|
||||
@Nullable
|
||||
private volatile HttpHeaders headers;
|
||||
|
||||
|
||||
public OkHttp3ClientHttpResponse(Response response) {
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpStatusCode getStatusCode() throws IOException {
|
||||
return HttpStatusCode.valueOf(this.response.code());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() {
|
||||
return this.response.message();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
ResponseBody body = this.response.body();
|
||||
return (body != null ? body.byteStream() : InputStream.nullInputStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
HttpHeaders headers = this.headers;
|
||||
if (headers == null) {
|
||||
headers = new HttpHeaders();
|
||||
for (String headerName : this.response.headers().names()) {
|
||||
for (String headerValue : this.response.headers(headerName)) {
|
||||
headers.add(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
this.headers = headers;
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
ResponseBody body = this.response.body();
|
||||
if (body != null) {
|
||||
body.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -7,8 +7,8 @@ import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Sentinel统一限流策略
|
||||
|
@ -20,6 +20,7 @@ import lombok.NoArgsConstructor;
|
||||
import org.springblade.core.datascope.constant.DataScopeConstant;
|
||||
import org.springblade.core.datascope.enums.DataScopeEnum;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
@ -31,6 +32,7 @@ import java.io.Serializable;
|
||||
@NoArgsConstructor
|
||||
public class DataScopeModel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -23,12 +23,10 @@
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId>
|
||||
<version>${mybatis.plus.generator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
<!--Velocity-->
|
||||
<dependency>
|
||||
|
@ -15,12 +15,12 @@
|
||||
*/
|
||||
package $!{package.Controller};
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import lombok.AllArgsConstructor;
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.springblade.core.mp.support.Condition;
|
||||
import org.springblade.core.mp.support.Query;
|
||||
@ -54,7 +54,7 @@ import $!{superControllerClassPackage};
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("#if($!{hasServiceName})/$!{serviceName}#end/$!{entityKey}")
|
||||
@Api(value = "$!{table.comment}", tags = "$!{table.comment}接口")
|
||||
@Tag(name = "$!{table.comment}", tags = "$!{table.comment}接口")
|
||||
#if($!{superControllerClass})
|
||||
public class $!{table.controllerName} extends $!{superControllerClass} {
|
||||
#else
|
||||
@ -69,7 +69,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@GetMapping("/detail")
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "详情", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "详情", description = "传入$!{table.entityPath}")
|
||||
public R<$!{entity}VO> detail($!{entity} $!{table.entityPath}) {
|
||||
$!{entity} detail = $!{table.entityPath}Service.getOne(Condition.getQueryWrapper($!{table.entityPath}));
|
||||
return R.data($!{entity}Wrapper.build().entityVO(detail));
|
||||
@ -80,7 +80,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "分页", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "分页", description = "传入$!{table.entityPath}")
|
||||
public R<IPage<$!{entity}VO>> list($!{entity} $!{table.entityPath}, Query query) {
|
||||
IPage<$!{entity}> pages = $!{table.entityPath}Service.page(Condition.getPage(query), Condition.getQueryWrapper($!{table.entityPath}));
|
||||
return R.data($!{entity}Wrapper.build().pageVO(pages));
|
||||
@ -92,7 +92,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@GetMapping("/detail")
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "详情", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "详情", description = "传入$!{table.entityPath}")
|
||||
public R<$!{entity}> detail($!{entity} $!{table.entityPath}) {
|
||||
$!{entity} detail = $!{table.entityPath}Service.getOne(Condition.getQueryWrapper($!{table.entityPath}));
|
||||
return R.data(detail);
|
||||
@ -103,7 +103,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "分页", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "分页", description = "传入$!{table.entityPath}")
|
||||
public R<IPage<$!{entity}>> list($!{entity} $!{table.entityPath}, Query query) {
|
||||
IPage<$!{entity}> pages = $!{table.entityPath}Service.page(Condition.getPage(query), Condition.getQueryWrapper($!{table.entityPath}));
|
||||
return R.data(pages);
|
||||
@ -115,7 +115,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
@ApiOperationSupport(order = 3)
|
||||
@ApiOperation(value = "分页", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "分页", description = "传入$!{table.entityPath}")
|
||||
public R<IPage<$!{entity}VO>> page($!{entity}VO $!{table.entityPath}, Query query) {
|
||||
IPage<$!{entity}VO> pages = $!{table.entityPath}Service.select$!{entity}Page(Condition.getPage(query), $!{table.entityPath});
|
||||
return R.data(pages);
|
||||
@ -126,7 +126,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@PostMapping("/save")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@ApiOperation(value = "新增", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "新增", description = "传入$!{table.entityPath}")
|
||||
public R save(@Valid @RequestBody $!{entity} $!{table.entityPath}) {
|
||||
return R.status($!{table.entityPath}Service.save($!{table.entityPath}));
|
||||
}
|
||||
@ -136,7 +136,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation(value = "修改", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "修改", description = "传入$!{table.entityPath}")
|
||||
public R update(@Valid @RequestBody $!{entity} $!{table.entityPath}) {
|
||||
return R.status($!{table.entityPath}Service.updateById($!{table.entityPath}));
|
||||
}
|
||||
@ -146,7 +146,7 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@PostMapping("/submit")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@ApiOperation(value = "新增或修改", notes = "传入$!{table.entityPath}")
|
||||
@Operation(summary = "新增或修改", description = "传入$!{table.entityPath}")
|
||||
public R submit(@Valid @RequestBody $!{entity} $!{table.entityPath}) {
|
||||
return R.status($!{table.entityPath}Service.saveOrUpdate($!{table.entityPath}));
|
||||
}
|
||||
@ -158,8 +158,8 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@PostMapping("/remove")
|
||||
@ApiOperationSupport(order = 7)
|
||||
@ApiOperation(value = "逻辑删除", notes = "传入ids")
|
||||
public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
|
||||
@Operation(summary = "逻辑删除", description = "传入ids")
|
||||
public R remove(@Parameter(name = "主键集合", required = true) @RequestParam String ids) {
|
||||
return R.status($!{table.entityPath}Service.deleteLogic(Func.toLongList(ids)));
|
||||
}
|
||||
|
||||
@ -170,8 +170,8 @@ public class $!{table.controllerName} {
|
||||
*/
|
||||
@PostMapping("/remove")
|
||||
@ApiOperationSupport(order = 8)
|
||||
@ApiOperation(value = "删除", notes = "传入ids")
|
||||
public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
|
||||
@Operation(summary = "删除", description = "传入ids")
|
||||
public R remove(@Parameter(name = "主键集合", required = true) @RequestParam String ids) {
|
||||
return R.status($!{table.entityPath}Service.removeByIds(Func.toLongList(ids)));
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,9 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
#end
|
||||
#if($!{swagger})
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
#end
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* $!{table.comment}实体类
|
||||
@ -43,7 +43,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
#end
|
||||
#if($!{swagger})
|
||||
@ApiModel(value = "$!{entity}对象", description = #if ("$!{table.comment}"=="")"$!{entity}对象"#else"$!{table.comment}"#end)
|
||||
@Schema(description = #if ("$!{table.comment}"=="")"$!{entity}对象"#else"$!{table.comment}"#end)
|
||||
#end
|
||||
#if($!{superEntityClass})
|
||||
public class $!{entity} extends $!{superEntityClass}#if($!{activeRecord})<$!{entity}>#end {
|
||||
@ -54,7 +54,8 @@ public class $!{entity} extends Model<$!{entity}> {
|
||||
public class $!{entity} implements Serializable {
|
||||
#end
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
## ---------- BEGIN 字段循环遍历 ----------
|
||||
#foreach($field in $!{table.fields})
|
||||
@ -67,7 +68,7 @@ public class $!{entity} implements Serializable {
|
||||
* $!{field.comment}
|
||||
*/
|
||||
#if($!{swagger})
|
||||
@ApiModelProperty(value = "$!{field.comment}")
|
||||
@Schema(description = "$!{field.comment}")
|
||||
#end
|
||||
#end
|
||||
#if($!{field.keyFlag})
|
||||
|
@ -21,6 +21,7 @@ import $!{package.Entity}.$!{entity};
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
#end
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* $!{table.comment}数据传输对象实体类
|
||||
@ -33,6 +34,7 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
#end
|
||||
public class $!{entity}DTO extends $!{entity} {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
@ -22,8 +22,9 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
#end
|
||||
#if($!{swagger})
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
#end
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* $!{table.comment}视图实体类
|
||||
@ -36,9 +37,10 @@ import io.swagger.annotations.ApiModel;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
#end
|
||||
#if($!{swagger})
|
||||
@ApiModel(value = "$!{entity}VO对象", description = #if ("$!{table.comment}"=="")"$!{entity}VO对象"#else"$!{table.comment}"#end)
|
||||
@Schema(description = #if ("$!{table.comment}"=="")"$!{entity}VO对象"#else"$!{table.comment}"#end)
|
||||
#end
|
||||
public class $!{entity}VO extends $!{entity} {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public class $!{entity}Wrapper extends BaseEntityWrapper<$!{entity}, $!{entity}V
|
||||
|
||||
@Override
|
||||
public $!{entity}VO entityVO($!{entity} $!{table.entityPath}) {
|
||||
$!{entity}VO $!{table.entityPath}VO = BeanUtil.copy($!{table.entityPath}, $!{entity}VO.class);
|
||||
$!{entity}VO $!{table.entityPath}VO = BeanUtil.copyProperties($!{table.entityPath}, $!{entity}VO.class);
|
||||
|
||||
return $!{table.entityPath}VO;
|
||||
}
|
||||
|
@ -30,6 +30,28 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<!-- jakarta -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
</dependency>
|
||||
<!-- javax -->
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2029, DreamLu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.launch.config;
|
||||
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.props.BladePropertySourcePostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* blade property config
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
@EnableConfigurationProperties(BladeProperties.class)
|
||||
public class BladePropertyConfiguration {
|
||||
|
||||
@Bean
|
||||
public BladePropertySourcePostProcessor bladePropertySourcePostProcessor() {
|
||||
return new BladePropertySourcePostProcessor();
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ public interface AppConstant {
|
||||
/**
|
||||
* 应用版本
|
||||
*/
|
||||
String APPLICATION_VERSION = "3.7.2";
|
||||
String APPLICATION_VERSION = "4.0.0";
|
||||
|
||||
/**
|
||||
* 基础包
|
||||
|
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.launch.log;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 请求日志级别,来源 okHttp
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum BladeLogLevel {
|
||||
/**
|
||||
* No logs.
|
||||
*/
|
||||
NONE(0),
|
||||
|
||||
/**
|
||||
* Logs request and response lines.
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1 (3-byte body)
|
||||
*
|
||||
* <-- 200 OK (22ms, 6-byte body)
|
||||
* }</pre>
|
||||
*/
|
||||
BASIC(1),
|
||||
|
||||
/**
|
||||
* Logs request and response lines and their respective headers.
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1
|
||||
* Host: example.com
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 3
|
||||
* --> END POST
|
||||
*
|
||||
* <-- 200 OK (22ms)
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 6
|
||||
* <-- END HTTP
|
||||
* }</pre>
|
||||
*/
|
||||
HEADERS(2),
|
||||
|
||||
/**
|
||||
* Logs request and response lines and their respective headers and bodies (if present).
|
||||
*
|
||||
* <p>Example:
|
||||
* <pre>{@code
|
||||
* --> POST /greeting http/1.1
|
||||
* Host: example.com
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 3
|
||||
*
|
||||
* Hi?
|
||||
* --> END POST
|
||||
*
|
||||
* <-- 200 OK (22ms)
|
||||
* Content-Type: plain/text
|
||||
* Content-Length: 6
|
||||
*
|
||||
* Hello!
|
||||
* <-- END HTTP
|
||||
* }</pre>
|
||||
*/
|
||||
BODY(3);
|
||||
|
||||
/**
|
||||
* 请求日志配置前缀
|
||||
*/
|
||||
public static final String REQ_LOG_PROPS_PREFIX = "blade.log.request";
|
||||
/**
|
||||
* 控制台日志是否启用
|
||||
*/
|
||||
public static final String CONSOLE_LOG_ENABLED_PROP = "blade.log.console.enabled";
|
||||
|
||||
/**
|
||||
* 级别
|
||||
*/
|
||||
private final int level;
|
||||
|
||||
/**
|
||||
* 当前版本 小于和等于 比较的版本
|
||||
*
|
||||
* @param level LogLevel
|
||||
* @return 是否小于和等于
|
||||
*/
|
||||
public boolean lte(BladeLogLevel level) {
|
||||
return this.level <= level.level;
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ package org.springblade.core.launch.props;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springblade.core.launch.constant.AppConstant;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
@ -200,6 +201,33 @@ public class BladeProperties implements EnvironmentAware, EnvironmentCapable {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是开发环境
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isDev() {
|
||||
return AppConstant.DEV_CODE.equals(getEnv());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是生产环境
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isProd() {
|
||||
return AppConstant.PROD_CODE.equals(getEnv());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是测试环境
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isTest() {
|
||||
return AppConstant.TEST_CODE.equals(getEnv());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在key
|
||||
*
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2029, DreamLu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.launch.props;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义资源文件读取,优先级最低
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface BladePropertySource {
|
||||
|
||||
/**
|
||||
* Indicate the resource location(s) of the properties file to be loaded.
|
||||
* for example, {@code "classpath:/com/example/app.yml"}
|
||||
*
|
||||
* @return location(s)
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* load app-{activeProfile}.yml
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
boolean loadActiveProfile() default true;
|
||||
|
||||
/**
|
||||
* Get the order value of this resource.
|
||||
*
|
||||
* @return order
|
||||
*/
|
||||
int order() default Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2029, DreamLu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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 org.springblade.core.launch.props;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 自定义资源文件读取,优先级最低
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Slf4j
|
||||
public class BladePropertySourcePostProcessor implements BeanFactoryPostProcessor, InitializingBean, Ordered {
|
||||
private final ResourceLoader resourceLoader;
|
||||
private final List<PropertySourceLoader> propertySourceLoaders;
|
||||
|
||||
public BladePropertySourcePostProcessor() {
|
||||
this.resourceLoader = new DefaultResourceLoader();
|
||||
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
log.info("BladePropertySourcePostProcessor process @BladePropertySource bean.");
|
||||
Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(BladePropertySource.class);
|
||||
Set<Map.Entry<String, Object>> beanEntrySet = beansWithAnnotation.entrySet();
|
||||
// 没有 @YmlPropertySource 注解,跳出
|
||||
if (beanEntrySet.isEmpty()) {
|
||||
log.warn("Not found @BladePropertySource on spring bean class.");
|
||||
return;
|
||||
}
|
||||
// 组装资源
|
||||
List<PropertyFile> propertyFileList = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> entry : beanEntrySet) {
|
||||
Class<?> beanClass = ClassUtils.getUserClass(entry.getValue());
|
||||
BladePropertySource propertySource = AnnotationUtils.getAnnotation(beanClass, BladePropertySource.class);
|
||||
if (propertySource == null) {
|
||||
continue;
|
||||
}
|
||||
int order = propertySource.order();
|
||||
boolean loadActiveProfile = propertySource.loadActiveProfile();
|
||||
String location = propertySource.value();
|
||||
propertyFileList.add(new PropertyFile(order, location, loadActiveProfile));
|
||||
}
|
||||
|
||||
// 装载 PropertySourceLoader
|
||||
Map<String, PropertySourceLoader> loaderMap = new HashMap<>(16);
|
||||
for (PropertySourceLoader loader : propertySourceLoaders) {
|
||||
String[] loaderExtensions = loader.getFileExtensions();
|
||||
for (String extension : loaderExtensions) {
|
||||
loaderMap.put(extension, loader);
|
||||
}
|
||||
}
|
||||
// 去重,排序
|
||||
List<PropertyFile> sortedPropertyList = propertyFileList.stream()
|
||||
.distinct()
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
ConfigurableEnvironment environment = beanFactory.getBean(ConfigurableEnvironment.class);
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
|
||||
// 只支持 activeProfiles,没有必要支持 spring.profiles.include。
|
||||
String[] activeProfiles = environment.getActiveProfiles();
|
||||
ArrayList<PropertySource> propertySourceList = new ArrayList<>();
|
||||
for (String profile : activeProfiles) {
|
||||
for (PropertyFile propertyFile : sortedPropertyList) {
|
||||
// 不加载 ActiveProfile 的配置文件
|
||||
if (!propertyFile.loadActiveProfile) {
|
||||
continue;
|
||||
}
|
||||
String extension = propertyFile.getExtension();
|
||||
PropertySourceLoader loader = loaderMap.get(extension);
|
||||
if (loader == null) {
|
||||
throw new IllegalArgumentException("Can't find PropertySourceLoader for PropertySource extension:" + extension);
|
||||
}
|
||||
String location = propertyFile.getLocation();
|
||||
String filePath = StringUtils.stripFilenameExtension(location);
|
||||
String profiledLocation = filePath + "-" + profile + "." + extension;
|
||||
Resource resource = resourceLoader.getResource(profiledLocation);
|
||||
loadPropertySource(profiledLocation, resource, loader, propertySourceList);
|
||||
}
|
||||
}
|
||||
// 本身的 Resource
|
||||
for (PropertyFile propertyFile : sortedPropertyList) {
|
||||
String extension = propertyFile.getExtension();
|
||||
PropertySourceLoader loader = loaderMap.get(extension);
|
||||
String location = propertyFile.getLocation();
|
||||
Resource resource = resourceLoader.getResource(location);
|
||||
loadPropertySource(location, resource, loader, propertySourceList);
|
||||
}
|
||||
// 转存
|
||||
for (PropertySource propertySource : propertySourceList) {
|
||||
propertySources.addLast(propertySource);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadPropertySource(String location, Resource resource,
|
||||
PropertySourceLoader loader,
|
||||
List<PropertySource> sourceList) {
|
||||
if (resource.exists()) {
|
||||
String name = "bladePropertySource: [" + location + "]";
|
||||
try {
|
||||
sourceList.addAll(loader.load(name, resource));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
log.info("BladePropertySourcePostProcessor init.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
private static class PropertyFile implements Comparable<PropertyFile> {
|
||||
private final int order;
|
||||
private final String location;
|
||||
private final String extension;
|
||||
private final boolean loadActiveProfile;
|
||||
|
||||
PropertyFile(int order, String location, boolean loadActiveProfile) {
|
||||
this.order = order;
|
||||
this.location = location;
|
||||
this.loadActiveProfile = loadActiveProfile;
|
||||
this.extension = Objects.requireNonNull(StringUtils.getFilenameExtension(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PropertyFile other) {
|
||||
return Integer.compare(this.order, other.order);
|
||||
}
|
||||
}
|
||||
}
|
@ -55,7 +55,6 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
<version>${alibaba.nacos.version}</version>
|
||||
</dependency>
|
||||
<!-- Web -->
|
||||
<dependency>
|
||||
|
@ -28,11 +28,15 @@
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-cloud</artifactId>
|
||||
</dependency>
|
||||
<!-- validator -->
|
||||
<dependency>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
</dependency>
|
||||
<!--Mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -36,7 +36,7 @@ import org.springframework.boot.web.servlet.error.ErrorController;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
/**
|
||||
* 统一异常处理
|
||||
|
@ -42,8 +42,8 @@ public class BladeErrorAttributes extends DefaultErrorAttributes {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
|
||||
String requestUri = this.getAttr(webRequest, "javax.servlet.error.request_uri");
|
||||
Integer status = this.getAttr(webRequest, "javax.servlet.error.status_code");
|
||||
String requestUri = this.getAttr(webRequest, "jakarta.servlet.error.request_uri");
|
||||
Integer status = this.getAttr(webRequest, "jakarta.servlet.error.status_code");
|
||||
Throwable error = getError(webRequest);
|
||||
R result;
|
||||
if (error == null) {
|
||||
|
@ -25,8 +25,8 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ package org.springblade.core.log.error;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.validator.internal.engine.path.PathImpl;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.log.props.BladeLogProperties;
|
||||
import org.springblade.core.log.publisher.ErrorLogPublisher;
|
||||
@ -46,9 +47,9 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchExcep
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import jakarta.servlet.Servlet;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -64,6 +65,7 @@ import java.util.Set;
|
||||
@RequiredArgsConstructor
|
||||
public class BladeRestExceptionTranslator {
|
||||
|
||||
private final BladeProperties bladeProperties;
|
||||
private final BladeLogProperties bladeLogProperties;
|
||||
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
@ -163,6 +165,10 @@ public class BladeRestExceptionTranslator {
|
||||
if (bladeLogProperties.getError()) {
|
||||
ErrorLogPublisher.publishEvent(e, UrlUtil.getPath(WebUtil.getRequest().getRequestURI()));
|
||||
}
|
||||
// 生产环境屏蔽具体异常信息返回
|
||||
if (bladeProperties.isProd()) {
|
||||
return R.fail(ResultCode.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return R.fail(ResultCode.INTERNAL_SERVER_ERROR, (Func.isEmpty(e.getMessage()) ? ResultCode.INTERNAL_SERVER_ERROR.getMessage() : e.getMessage()));
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.feign.ILogClient;
|
||||
import org.springblade.core.log.model.LogAbstract;
|
||||
import org.springblade.core.log.model.LogError;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springframework.context.event.EventListener;
|
||||
@ -48,10 +47,14 @@ public class ErrorLogListener {
|
||||
@Order
|
||||
@EventListener(ErrorLogEvent.class)
|
||||
public void saveErrorLog(ErrorLogEvent event) {
|
||||
Map<String, Object> source = (Map<String, Object>) event.getSource();
|
||||
LogError logError = (LogError) source.get(EventConstant.EVENT_LOG);
|
||||
LogAbstractUtil.addOtherInfoToLog(logError, bladeProperties, serverInfo);
|
||||
logService.saveErrorLog(logError);
|
||||
try {
|
||||
Map<String, Object> source = (Map<String, Object>) event.getSource();
|
||||
LogError logError = (LogError) source.get(EventConstant.EVENT_LOG);
|
||||
LogAbstractUtil.addOtherInfoToLog(logError, bladeProperties, serverInfo);
|
||||
logService.saveErrorLog(logError);
|
||||
} catch (Exception e) {
|
||||
log.error("保存错误日志失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package org.springblade.core.log.model;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
@ -30,6 +31,7 @@ import java.io.Serializable;
|
||||
@TableName("blade_log_api")
|
||||
public class LogApi extends LogAbstract implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,8 @@ package org.springblade.core.log.model;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* LogApi视图实体类
|
||||
*
|
||||
@ -26,6 +28,7 @@ import lombok.EqualsAndHashCode;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogApiVo extends LogApi {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String strId;
|
||||
|
@ -19,6 +19,7 @@ package org.springblade.core.log.model;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
@ -30,6 +31,7 @@ import java.io.Serializable;
|
||||
@TableName("blade_log_error")
|
||||
public class LogError extends LogAbstract implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,8 @@ package org.springblade.core.log.model;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* LogError视图实体类
|
||||
*
|
||||
@ -26,6 +28,7 @@ import lombok.EqualsAndHashCode;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogErrorVo extends LogError {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String strId;
|
||||
|
@ -19,6 +19,7 @@ package org.springblade.core.log.model;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
@ -31,6 +32,7 @@ import java.io.Serializable;
|
||||
@TableName("blade_log_usual")
|
||||
public class LogUsual extends LogAbstract implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,8 @@ package org.springblade.core.log.model;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* LogUsual视图实体类
|
||||
*
|
||||
@ -26,6 +28,7 @@ import lombok.EqualsAndHashCode;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogUsualVo extends LogUsual {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String strId;
|
||||
|
@ -28,7 +28,7 @@ import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -26,7 +26,7 @@ import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -24,7 +24,7 @@ import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -22,7 +22,7 @@ import org.springblade.core.log.model.LogAbstract;
|
||||
import org.springblade.core.secure.utils.SecureUtil;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Log 相关工具
|
||||
|
@ -19,17 +19,18 @@
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>${mybatis.spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-typehandlers-jsr310</artifactId>
|
||||
</dependency>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
|
@ -22,7 +22,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
@ -41,7 +41,7 @@ public class BaseEntity implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ApiModelProperty(value = "主键")
|
||||
@Schema(description = "主键")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
@ -50,14 +50,14 @@ public class BaseEntity implements Serializable {
|
||||
* 创建人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty(value = "创建人")
|
||||
@Schema(description = "创建人")
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建部门
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty(value = "创建部门")
|
||||
@Schema(description = "创建部门")
|
||||
private Long createDept;
|
||||
|
||||
/**
|
||||
@ -65,14 +65,14 @@ public class BaseEntity implements Serializable {
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty(value = "更新人")
|
||||
@Schema(description = "更新人")
|
||||
private Long updateUser;
|
||||
|
||||
/**
|
||||
@ -80,19 +80,19 @@ public class BaseEntity implements Serializable {
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@Schema(description = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 状态[1:正常]
|
||||
*/
|
||||
@ApiModelProperty(value = "业务状态")
|
||||
@Schema(description = "业务状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态[0:未删除,1:删除]
|
||||
*/
|
||||
@TableLogic
|
||||
@ApiModelProperty(value = "是否已删除")
|
||||
@Schema(description = "是否已删除")
|
||||
private Integer isDeleted;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package org.springblade.core.mp.base;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,7 @@ import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -16,7 +16,7 @@
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ -32,7 +32,7 @@ public class TenantEntity extends BaseEntity {
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@ApiModelProperty(value = "租户ID")
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
|
||||
}
|
||||
|
@ -15,11 +15,12 @@
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
|
||||
|
||||
/**
|
||||
* 分页工具
|
||||
*
|
||||
@ -27,31 +28,31 @@ import lombok.experimental.Accessors;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(description = "查询条件")
|
||||
@Schema(description = "查询条件")
|
||||
public class Query {
|
||||
|
||||
/**
|
||||
* 当前页
|
||||
*/
|
||||
@ApiModelProperty(value = "当前页")
|
||||
@Schema(description = "当前页")
|
||||
private Integer current;
|
||||
|
||||
/**
|
||||
* 每页的数量
|
||||
*/
|
||||
@ApiModelProperty(value = "每页的数量")
|
||||
@Schema(description = "每页的数量")
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 排序的字段名
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String ascs;
|
||||
|
||||
/**
|
||||
* 排序方式
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String descs;
|
||||
|
||||
}
|
||||
|
@ -21,8 +21,35 @@
|
||||
<dependency>
|
||||
<groupId>com.bstek.ureport</groupId>
|
||||
<artifactId>ureport2-console</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<version>2.2.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.bstek.ureport</groupId>
|
||||
<artifactId>ureport2-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<version>2.2.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.build;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年6月19日
|
||||
*/
|
||||
public class Splash {
|
||||
public void doPrint() {
|
||||
String sb = "\n" +
|
||||
" ___ ___ ________ _______ ________ ________ ________ _________ ________ \n" +
|
||||
"|\\ \\|\\ \\|\\ __ \\|\\ ___ \\ |\\ __ \\|\\ __ \\|\\ __ \\|\\___ ___\\ |\\_____ \\ \n" +
|
||||
"\\ \\ \\\\\\ \\ \\ \\|\\ \\ \\ __/|\\ \\ \\|\\ \\ \\ \\|\\ \\ \\ \\|\\ \\|___ \\ \\_| \\|____|\\ /_ \n" +
|
||||
" \\ \\ \\\\\\ \\ \\ _ _\\ \\ \\_|/_\\ \\ ____\\ \\ \\\\\\ \\ \\ _ _\\ \\ \\ \\ \\|\\ \\ \n" +
|
||||
" \\ \\ \\\\\\ \\ \\ \\\\ \\\\ \\ \\_|\\ \\ \\ \\___|\\ \\ \\\\\\ \\ \\ \\\\ \\| \\ \\ \\ __\\_\\ \\ \n" +
|
||||
" \\ \\_______\\ \\__\\\\ _\\\\ \\_______\\ \\__\\ \\ \\_______\\ \\__\\\\ _\\ \\ \\__\\ |\\_______\\\n" +
|
||||
" \\|_______|\\|__|\\|__|\\|_______|\\|__| \\|_______|\\|__|\\|__| \\|__| \\|_______|\n" +
|
||||
"........................................................................................................" +
|
||||
"\n" +
|
||||
". uReport, is a Chinese style report engine" +
|
||||
" licensed under the Apache License 2.0, ." +
|
||||
"\n" +
|
||||
". which is opensource, easy to use,high-performance, with browser-based-designer, ." +
|
||||
"\n" +
|
||||
". it has now been upgraded by BladeX to support jdk 17 and spring boot 3. ." +
|
||||
"\n" +
|
||||
"........................................................................................................" +
|
||||
"\n";
|
||||
System.out.println(sb);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.build.compute;
|
||||
|
||||
import com.bstek.ureport.build.BindData;
|
||||
import com.bstek.ureport.build.Context;
|
||||
import com.bstek.ureport.definition.value.Source;
|
||||
import com.bstek.ureport.definition.value.ValueType;
|
||||
import com.bstek.ureport.definition.value.ZxingValue;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.expression.model.Expression;
|
||||
import com.bstek.ureport.expression.model.data.BindDataListExpressionData;
|
||||
import com.bstek.ureport.expression.model.data.ExpressionData;
|
||||
import com.bstek.ureport.expression.model.data.ObjectExpressionData;
|
||||
import com.bstek.ureport.expression.model.data.ObjectListExpressionData;
|
||||
import com.bstek.ureport.model.Cell;
|
||||
import com.bstek.ureport.model.Image;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springblade.core.tool.utils.Base64Util;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月27日
|
||||
*/
|
||||
public class ZxingValueCompute implements ValueCompute {
|
||||
private static final int BLACK = 0xff000000;
|
||||
private static final int WHITE = 0xFFFFFFFF;
|
||||
@Override
|
||||
public List<BindData> compute(Cell cell, Context context) {
|
||||
List<BindData> list=new ArrayList<BindData>();
|
||||
ZxingValue value=(ZxingValue)cell.getValue();
|
||||
String format=value.getFormat();
|
||||
BarcodeFormat barcodeForamt=BarcodeFormat.QR_CODE;
|
||||
if(StringUtils.isNotBlank(format)){
|
||||
barcodeForamt=BarcodeFormat.valueOf(format);
|
||||
}
|
||||
int w=value.getWidth();
|
||||
int h=value.getHeight();
|
||||
Source source=value.getSource();
|
||||
if(source.equals(Source.text)){
|
||||
String data=value.getValue();
|
||||
Image image=buildImage(barcodeForamt,data,w,h);
|
||||
list.add(new BindData(image));
|
||||
}else{
|
||||
Expression expression=value.getExpression();
|
||||
ExpressionData<?> data=expression.execute(cell,cell, context);
|
||||
if(data instanceof BindDataListExpressionData){
|
||||
BindDataListExpressionData listData=(BindDataListExpressionData)data;
|
||||
List<BindData> bindDataList=listData.getData();
|
||||
for(BindData bindData:bindDataList){
|
||||
Object obj=bindData.getValue();
|
||||
if(obj==null)obj="";
|
||||
Image image=buildImage(barcodeForamt,obj.toString(),w,h);
|
||||
list.add(new BindData(image));
|
||||
}
|
||||
}else if(data instanceof ObjectExpressionData){
|
||||
ObjectExpressionData exprData=(ObjectExpressionData)data;
|
||||
Object obj=exprData.getData();
|
||||
if(obj==null){
|
||||
obj="";
|
||||
}else if(obj instanceof String){
|
||||
String text=obj.toString();
|
||||
if(text.startsWith("\"") && text.endsWith("\"")){
|
||||
text=text.substring(1,text.length()-1);
|
||||
}
|
||||
obj=text;
|
||||
}
|
||||
Image image=buildImage(barcodeForamt,obj.toString(),w,h);
|
||||
list.add(new BindData(image));
|
||||
}else if(data instanceof ObjectListExpressionData){
|
||||
ObjectListExpressionData listExprData=(ObjectListExpressionData)data;
|
||||
List<?> listData=listExprData.getData();
|
||||
for(Object obj:listData){
|
||||
if(obj==null){
|
||||
obj="";
|
||||
}else if(obj instanceof String){
|
||||
String text=obj.toString();
|
||||
if(text.startsWith("\"") && text.endsWith("\"")){
|
||||
text=text.substring(1,text.length()-1);
|
||||
}
|
||||
obj=text;
|
||||
}
|
||||
Image image=buildImage(barcodeForamt,obj.toString(),w,h);
|
||||
list.add(new BindData(image));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Image buildImage(BarcodeFormat format,String data,int w,int h){
|
||||
try{
|
||||
Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
|
||||
hints.put(EncodeHintType.MARGIN,0);
|
||||
if(format.equals(BarcodeFormat.QR_CODE)){
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
||||
}
|
||||
BitMatrix matrix = new MultiFormatWriter().encode(data,format, w, h,hints);
|
||||
int width = matrix.getWidth();
|
||||
int height = matrix.getHeight();
|
||||
BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_ARGB);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", outputStream);
|
||||
byte[] bytes=outputStream.toByteArray();
|
||||
String base64Data= Base64Util.encodeToString(bytes);
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
return new Image(base64Data,w,h);
|
||||
}catch(Exception ex){
|
||||
throw new ReportComputeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType type() {
|
||||
return ValueType.zxing;
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2016年6月3日
|
||||
*/
|
||||
public abstract class BaseServletAction implements ServletAction {
|
||||
protected Throwable buildRootException(Throwable throwable) {
|
||||
if (throwable.getCause() == null) {
|
||||
return throwable;
|
||||
}
|
||||
return buildRootException(throwable.getCause());
|
||||
}
|
||||
|
||||
protected String decode(String value) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
value = URLDecoder.decode(value, "utf-8");
|
||||
value = URLDecoder.decode(value, "utf-8");
|
||||
return value;
|
||||
} catch (Exception ex) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
protected String decodeContent(String content) {
|
||||
if (content == null) {
|
||||
return content;
|
||||
}
|
||||
try {
|
||||
content = URLDecoder.decode(content, "utf-8");
|
||||
return content;
|
||||
} catch (Exception ex) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Object> buildParameters(HttpServletRequest req) {
|
||||
Map<String, Object> parameters = new HashMap<String, Object>();
|
||||
Enumeration<?> enumeration = req.getParameterNames();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Object obj = enumeration.nextElement();
|
||||
if (obj == null) {
|
||||
continue;
|
||||
}
|
||||
String name = obj.toString();
|
||||
String value = req.getParameter(name);
|
||||
if (name == null || value == null || name.startsWith("_")) {
|
||||
continue;
|
||||
}
|
||||
parameters.put(name, decode(value));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
protected void invokeMethod(String methodName, HttpServletRequest req, HttpServletResponse resp) throws ServletException {
|
||||
try {
|
||||
Method method = this.getClass().getMethod(methodName, new Class<?>[]{HttpServletRequest.class, HttpServletResponse.class});
|
||||
method.invoke(this, new Object[]{req, resp});
|
||||
} catch (Exception ex) {
|
||||
throw new ServletException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected String retriveMethod(HttpServletRequest req) throws ServletException {
|
||||
String path = req.getContextPath() + UReportServlet.URL;
|
||||
String uri = req.getRequestURI();
|
||||
String targetUrl = uri.substring(path.length());
|
||||
int slashPos = targetUrl.indexOf("/", 1);
|
||||
if (slashPos > -1) {
|
||||
String methodName = targetUrl.substring(slashPos + 1).trim();
|
||||
return methodName.length() > 0 ? methodName : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String buildDownloadFileName(String reportFileName, String fileName, String extName) {
|
||||
if (StringUtils.isNotBlank(fileName)) {
|
||||
fileName = decode(fileName);
|
||||
if (!fileName.toLowerCase().endsWith(extName)) {
|
||||
fileName = fileName + extName;
|
||||
}
|
||||
return fileName;
|
||||
} else {
|
||||
int pos = reportFileName.indexOf(":");
|
||||
if (pos > 0) {
|
||||
reportFileName = reportFileName.substring(pos + 1, reportFileName.length());
|
||||
}
|
||||
pos = reportFileName.toLowerCase().indexOf(".ureport.xml");
|
||||
if (pos > 0) {
|
||||
reportFileName = reportFileName.substring(0, pos);
|
||||
}
|
||||
return "ureport-" + reportFileName + extName;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年10月11日
|
||||
*/
|
||||
public class MobileUtils {
|
||||
private static String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i"
|
||||
+ "|windows (phone|ce)|blackberry"
|
||||
+ "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
|
||||
+ "|laystation portable)|nokia|fennec|htc[-_]"
|
||||
+ "|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
|
||||
private static String tableReg = "\\b(ipad|tablet|(Nexus 7)|up.browser"
|
||||
+ "|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
|
||||
private static Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern tablePat = Pattern.compile(tableReg, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static boolean isMobile(HttpServletRequest req) {
|
||||
String userAgent = req.getHeader("USER-AGENT");
|
||||
if (userAgent == null) {
|
||||
userAgent = "";
|
||||
}
|
||||
userAgent = userAgent.toLowerCase();
|
||||
Matcher matcherPhone = phonePat.matcher(userAgent);
|
||||
Matcher matcherTable = tablePat.matcher(userAgent);
|
||||
if (matcherPhone.find() || matcherTable.find()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月8日
|
||||
*/
|
||||
public class RequestHolder {
|
||||
private static final ThreadLocal<HttpServletRequest> requestThreadLocal = new ThreadLocal<HttpServletRequest>();
|
||||
|
||||
public static void setRequest(HttpServletRequest request) {
|
||||
requestThreadLocal.set(request);
|
||||
}
|
||||
|
||||
public static HttpServletRequest getRequest() {
|
||||
return requestThreadLocal.get();
|
||||
}
|
||||
|
||||
public static void clean() {
|
||||
requestThreadLocal.remove();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年1月25日
|
||||
*/
|
||||
public interface ServletAction {
|
||||
public static final String PREVIEW_KEY = "p";
|
||||
|
||||
void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
|
||||
|
||||
String url();
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.ServletConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年1月25日
|
||||
*/
|
||||
public class UReportServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 533049461276487971L;
|
||||
public static final String URL = "/ureport";
|
||||
private Map<String, ServletAction> actionMap = new HashMap<String, ServletAction>();
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
WebApplicationContext applicationContext = getWebApplicationContext(config);
|
||||
Collection<ServletAction> handlers = applicationContext.getBeansOfType(ServletAction.class).values();
|
||||
for (ServletAction handler : handlers) {
|
||||
String url = handler.url();
|
||||
if (actionMap.containsKey(url)) {
|
||||
throw new RuntimeException("Handler [" + url + "] already exist.");
|
||||
}
|
||||
actionMap.put(url, handler);
|
||||
}
|
||||
}
|
||||
|
||||
protected WebApplicationContext getWebApplicationContext(ServletConfig config) {
|
||||
return WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String path = req.getContextPath() + URL;
|
||||
String uri = req.getRequestURI();
|
||||
String targetUrl = uri.substring(path.length());
|
||||
if (targetUrl.length() < 1) {
|
||||
outContent(resp, "Welcome to use ureport,please specify target url.");
|
||||
return;
|
||||
}
|
||||
int slashPos = targetUrl.indexOf("/", 1);
|
||||
if (slashPos > -1) {
|
||||
targetUrl = targetUrl.substring(0, slashPos);
|
||||
}
|
||||
ServletAction targetHandler = actionMap.get(targetUrl);
|
||||
if (targetHandler == null) {
|
||||
outContent(resp, "Handler [" + targetUrl + "] not exist.");
|
||||
return;
|
||||
}
|
||||
RequestHolder.setRequest(req);
|
||||
try {
|
||||
targetHandler.execute(req, resp);
|
||||
} catch (Exception ex) {
|
||||
resp.setCharacterEncoding("UTF-8");
|
||||
PrintWriter pw = resp.getWriter();
|
||||
Throwable e = buildRootException(ex);
|
||||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
String errorMsg = e.getMessage();
|
||||
if (StringUtils.isBlank(errorMsg)) {
|
||||
errorMsg = e.getClass().getName();
|
||||
}
|
||||
pw.write(errorMsg);
|
||||
pw.close();
|
||||
throw new ServletException(ex);
|
||||
} finally {
|
||||
RequestHolder.clean();
|
||||
}
|
||||
}
|
||||
|
||||
private Throwable buildRootException(Throwable throwable) {
|
||||
if (throwable.getCause() == null) {
|
||||
return throwable;
|
||||
}
|
||||
return buildRootException(throwable.getCause());
|
||||
}
|
||||
|
||||
private void outContent(HttpServletResponse resp, String msg) throws IOException {
|
||||
resp.setContentType("text/html");
|
||||
PrintWriter pw = resp.getWriter();
|
||||
pw.write("<html>");
|
||||
pw.write("<header><title>UReport Console</title></header>");
|
||||
pw.write("<body>");
|
||||
pw.write(msg);
|
||||
pw.write("</body>");
|
||||
pw.write("</html>");
|
||||
pw.flush();
|
||||
pw.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.SerializationConfig;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2016年5月23日
|
||||
*/
|
||||
public abstract class WriteJsonServletAction extends BaseServletAction {
|
||||
protected void writeObjectToJson(HttpServletResponse resp, Object obj) throws ServletException, IOException {
|
||||
resp.setContentType("text/json");
|
||||
resp.setCharacterEncoding("UTF-8");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setSerializationInclusion(Inclusion.NON_NULL);
|
||||
mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
OutputStream out = resp.getOutputStream();
|
||||
try {
|
||||
mapper.writeValue(out, obj);
|
||||
} finally {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
85
blade-core-report/src/main/java/com/bstek/ureport/console/cache/HttpSessionReportCache.java
vendored
Normal file
85
blade-core-report/src/main/java/com/bstek/ureport/console/cache/HttpSessionReportCache.java
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.cache;
|
||||
|
||||
import com.bstek.ureport.cache.ReportCache;
|
||||
import com.bstek.ureport.console.RequestHolder;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月8日
|
||||
*/
|
||||
public class HttpSessionReportCache implements ReportCache {
|
||||
private Map<String, ObjectMap> sessionReportMap = new HashMap<String, ObjectMap>();
|
||||
private boolean disabled;
|
||||
|
||||
@Override
|
||||
public Object getObject(String file) {
|
||||
HttpServletRequest req = RequestHolder.getRequest();
|
||||
if (req == null) {
|
||||
return null;
|
||||
}
|
||||
ObjectMap objMap = getObjectMap(req);
|
||||
return objMap.get(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeObject(String file, Object object) {
|
||||
HttpServletRequest req = RequestHolder.getRequest();
|
||||
if (req == null) {
|
||||
return;
|
||||
}
|
||||
ObjectMap map = getObjectMap(req);
|
||||
map.put(file, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
private ObjectMap getObjectMap(HttpServletRequest req) {
|
||||
List<String> expiredList = new ArrayList<String>();
|
||||
for (String key : sessionReportMap.keySet()) {
|
||||
ObjectMap reportObj = sessionReportMap.get(key);
|
||||
if (reportObj.isExpired()) {
|
||||
expiredList.add(key);
|
||||
}
|
||||
}
|
||||
for (String key : expiredList) {
|
||||
sessionReportMap.remove(key);
|
||||
}
|
||||
String sessionId = req.getSession().getId();
|
||||
ObjectMap obj = sessionReportMap.get(sessionId);
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
} else {
|
||||
ObjectMap objMap = new ObjectMap();
|
||||
sessionReportMap.put(sessionId, objMap);
|
||||
return objMap;
|
||||
}
|
||||
}
|
||||
}
|
97
blade-core-report/src/main/java/com/bstek/ureport/console/cache/TempObjectCache.java
vendored
Normal file
97
blade-core-report/src/main/java/com/bstek/ureport/console/cache/TempObjectCache.java
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.cache;
|
||||
|
||||
import com.bstek.ureport.console.RequestHolder;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年9月6日
|
||||
*/
|
||||
public class TempObjectCache {
|
||||
private static TempObjectCache tempObjectCache = new TempObjectCache();
|
||||
private Map<String, ObjectMap> sessionMap = new HashMap<String, ObjectMap>();
|
||||
|
||||
public static Object getObject(String key) {
|
||||
return tempObjectCache.get(key);
|
||||
}
|
||||
|
||||
public static void putObject(String key, Object obj) {
|
||||
tempObjectCache.store(key, obj);
|
||||
}
|
||||
|
||||
public static void removeObject(String key) {
|
||||
tempObjectCache.remove(key);
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
HttpServletRequest req = RequestHolder.getRequest();
|
||||
if (req == null) {
|
||||
return;
|
||||
}
|
||||
ObjectMap mapObject = getReportMap(req);
|
||||
if (mapObject != null) {
|
||||
mapObject.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
HttpServletRequest req = RequestHolder.getRequest();
|
||||
if (req == null) {
|
||||
return null;
|
||||
}
|
||||
ObjectMap mapObject = getReportMap(req);
|
||||
return mapObject.get(key);
|
||||
}
|
||||
|
||||
public void store(String key, Object obj) {
|
||||
HttpServletRequest req = RequestHolder.getRequest();
|
||||
if (req == null) {
|
||||
return;
|
||||
}
|
||||
ObjectMap mapObject = getReportMap(req);
|
||||
mapObject.put(key, obj);
|
||||
}
|
||||
|
||||
private ObjectMap getReportMap(HttpServletRequest req) {
|
||||
List<String> expiredList = new ArrayList<String>();
|
||||
for (String key : sessionMap.keySet()) {
|
||||
ObjectMap reportObj = sessionMap.get(key);
|
||||
if (reportObj.isExpired()) {
|
||||
expiredList.add(key);
|
||||
}
|
||||
}
|
||||
for (String key : expiredList) {
|
||||
sessionMap.remove(key);
|
||||
}
|
||||
String sessionId = req.getSession().getId();
|
||||
ObjectMap obj = sessionMap.get(sessionId);
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
} else {
|
||||
ObjectMap mapObject = new ObjectMap();
|
||||
sessionMap.put(sessionId, mapObject);
|
||||
return mapObject;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.chart;
|
||||
|
||||
import com.bstek.ureport.cache.CacheUtils;
|
||||
import com.bstek.ureport.chart.ChartData;
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import com.bstek.ureport.utils.UnitUtils;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年6月30日
|
||||
*/
|
||||
public class ChartServletAction extends RenderPageServletAction {
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
public void storeData(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
String chartId = req.getParameter("_chartId");
|
||||
ChartData chartData = CacheUtils.getChartData(chartId);
|
||||
if (chartData == null) {
|
||||
return;
|
||||
}
|
||||
String base64Data = req.getParameter("_base64Data");
|
||||
String prefix = "data:image/png;base64,";
|
||||
if (base64Data != null) {
|
||||
if (base64Data.startsWith(prefix)) {
|
||||
base64Data = base64Data.substring(prefix.length(), base64Data.length());
|
||||
}
|
||||
}
|
||||
chartData.setBase64Data(base64Data);
|
||||
String width = req.getParameter("_width");
|
||||
String height = req.getParameter("_height");
|
||||
chartData.setHeight(UnitUtils.pixelToPoint(Integer.valueOf(height)));
|
||||
chartData.setWidth(UnitUtils.pixelToPoint(Integer.valueOf(width)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/chart";
|
||||
}
|
||||
}
|
@ -0,0 +1,385 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.designer;
|
||||
|
||||
import com.bstek.ureport.Utils;
|
||||
import com.bstek.ureport.build.Context;
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.dataset.Field;
|
||||
import com.bstek.ureport.definition.datasource.BuildinDatasource;
|
||||
import com.bstek.ureport.definition.datasource.DataType;
|
||||
import com.bstek.ureport.expression.ExpressionUtils;
|
||||
import com.bstek.ureport.expression.model.Expression;
|
||||
import com.bstek.ureport.expression.model.data.ExpressionData;
|
||||
import com.bstek.ureport.expression.model.data.ObjectExpressionData;
|
||||
import com.bstek.ureport.utils.ProcedureUtils;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.PreparedStatementCallback;
|
||||
import org.springframework.jdbc.core.PreparedStatementCreator;
|
||||
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.core.namedparam.*;
|
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.*;
|
||||
import java.util.Date;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年2月6日
|
||||
*/
|
||||
public class DatasourceServletAction extends RenderPageServletAction {
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBuildinDatasources(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
List<String> datasources = new ArrayList<String>();
|
||||
for (BuildinDatasource datasource : Utils.getBuildinDatasources()) {
|
||||
datasources.add(datasource.name());
|
||||
}
|
||||
writeObjectToJson(resp, datasources);
|
||||
}
|
||||
|
||||
public void loadMethods(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String beanId = req.getParameter("beanId");
|
||||
Object obj = applicationContext.getBean(beanId);
|
||||
Class<?> clazz = obj.getClass();
|
||||
Method[] methods = clazz.getMethods();
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (Method method : methods) {
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
if (types.length != 3) {
|
||||
continue;
|
||||
}
|
||||
Class<?> typeClass1 = types[0];
|
||||
Class<?> typeClass2 = types[1];
|
||||
Class<?> typeClass3 = types[2];
|
||||
if (!String.class.isAssignableFrom(typeClass1)) {
|
||||
continue;
|
||||
}
|
||||
if (!String.class.isAssignableFrom(typeClass2)) {
|
||||
continue;
|
||||
}
|
||||
if (!Map.class.isAssignableFrom(typeClass3)) {
|
||||
continue;
|
||||
}
|
||||
result.add(method.getName());
|
||||
}
|
||||
writeObjectToJson(resp, result);
|
||||
}
|
||||
|
||||
public void buildClass(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String clazz = req.getParameter("clazz");
|
||||
List<Field> result = new ArrayList<Field>();
|
||||
try {
|
||||
Class<?> targetClass = Class.forName(clazz);
|
||||
PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(targetClass);
|
||||
for (PropertyDescriptor pd : propertyDescriptors) {
|
||||
String name = pd.getName();
|
||||
if ("class".equals(name)) {
|
||||
continue;
|
||||
}
|
||||
result.add(new Field(name));
|
||||
}
|
||||
writeObjectToJson(resp, result);
|
||||
} catch (Exception ex) {
|
||||
throw new ReportDesignException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildDatabaseTables(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
Connection conn = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
conn = buildConnection(req);
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
String url = metaData.getURL();
|
||||
String schema = null;
|
||||
if (url.toLowerCase().contains("oracle")) {
|
||||
schema = metaData.getUserName();
|
||||
}
|
||||
List<Map<String, String>> tables = new ArrayList<Map<String, String>>();
|
||||
rs = metaData.getTables(null, schema, "%", new String[]{"TABLE", "VIEW"});
|
||||
while (rs.next()) {
|
||||
Map<String, String> table = new HashMap<String, String>();
|
||||
table.put("name", rs.getString("TABLE_NAME"));
|
||||
table.put("type", rs.getString("TABLE_TYPE"));
|
||||
tables.add(table);
|
||||
}
|
||||
writeObjectToJson(resp, tables);
|
||||
} catch (Exception ex) {
|
||||
throw new ServletException(ex);
|
||||
} finally {
|
||||
JdbcUtils.closeResultSet(rs);
|
||||
JdbcUtils.closeConnection(conn);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildFields(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String sql = req.getParameter("sql");
|
||||
String parameters = req.getParameter("parameters");
|
||||
Connection conn = null;
|
||||
final List<Field> fields = new ArrayList<Field>();
|
||||
try {
|
||||
conn = buildConnection(req);
|
||||
Map<String, Object> map = buildParameters(parameters);
|
||||
sql = parseSql(sql, map);
|
||||
if (ProcedureUtils.isProcedure(sql)) {
|
||||
List<Field> fieldsList = ProcedureUtils.procedureColumnsQuery(sql, map, conn);
|
||||
fields.addAll(fieldsList);
|
||||
} else {
|
||||
DataSource dataSource = new SingleConnectionDataSource(conn, false);
|
||||
NamedParameterJdbcTemplate jdbc = new NamedParameterJdbcTemplate(dataSource);
|
||||
PreparedStatementCreator statementCreator = getPreparedStatementCreator(sql, new MapSqlParameterSource(map));
|
||||
jdbc.getJdbcOperations().execute(statementCreator, new PreparedStatementCallback<Object>() {
|
||||
@Override
|
||||
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
rs = ps.executeQuery();
|
||||
ResultSetMetaData metadata = rs.getMetaData();
|
||||
int columnCount = metadata.getColumnCount();
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
String columnName = metadata.getColumnLabel(i + 1);
|
||||
fields.add(new Field(columnName));
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
JdbcUtils.closeResultSet(rs);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
writeObjectToJson(resp, fields);
|
||||
} catch (Exception ex) {
|
||||
throw new ReportDesignException(ex);
|
||||
} finally {
|
||||
JdbcUtils.closeConnection(conn);
|
||||
}
|
||||
}
|
||||
|
||||
protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
|
||||
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
|
||||
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
|
||||
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
|
||||
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
|
||||
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
|
||||
return pscf.newPreparedStatementCreator(params);
|
||||
}
|
||||
|
||||
public void previewData(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String sql = req.getParameter("sql");
|
||||
String parameters = req.getParameter("parameters");
|
||||
Map<String, Object> map = buildParameters(parameters);
|
||||
sql = parseSql(sql, map);
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = buildConnection(req);
|
||||
List<Map<String, Object>> list = null;
|
||||
if (ProcedureUtils.isProcedure(sql)) {
|
||||
list = ProcedureUtils.procedureQuery(sql, map, conn);
|
||||
} else {
|
||||
DataSource dataSource = new SingleConnectionDataSource(conn, false);
|
||||
NamedParameterJdbcTemplate jdbc = new NamedParameterJdbcTemplate(dataSource);
|
||||
list = jdbc.queryForList(sql, map);
|
||||
}
|
||||
int size = list.size();
|
||||
int currentTotal = size;
|
||||
if (currentTotal > 500) {
|
||||
currentTotal = 500;
|
||||
}
|
||||
List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>();
|
||||
for (int i = 0; i < currentTotal; i++) {
|
||||
ls.add(list.get(i));
|
||||
}
|
||||
DataResult result = new DataResult();
|
||||
List<String> fields = new ArrayList<String>();
|
||||
if (size > 0) {
|
||||
Map<String, Object> item = list.get(0);
|
||||
for (String name : item.keySet()) {
|
||||
fields.add(name);
|
||||
}
|
||||
}
|
||||
result.setFields(fields);
|
||||
result.setCurrentTotal(currentTotal);
|
||||
result.setData(ls);
|
||||
result.setTotal(size);
|
||||
writeObjectToJson(resp, result);
|
||||
} catch (Exception ex) {
|
||||
throw new ServletException(ex);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String parseSql(String sql, Map<String, Object> parameters) {
|
||||
sql = sql.trim();
|
||||
Context context = new Context(applicationContext, parameters);
|
||||
if (sql.startsWith(ExpressionUtils.EXPR_PREFIX) && sql.endsWith(ExpressionUtils.EXPR_SUFFIX)) {
|
||||
sql = sql.substring(2, sql.length() - 1);
|
||||
Expression expr = ExpressionUtils.parseExpression(sql);
|
||||
sql = executeSqlExpr(expr, context);
|
||||
return sql;
|
||||
} else {
|
||||
String sqlForUse = sql;
|
||||
Pattern pattern = Pattern.compile("\\$\\{.*?\\}");
|
||||
Matcher matcher = pattern.matcher(sqlForUse);
|
||||
while (matcher.find()) {
|
||||
String substr = matcher.group();
|
||||
String sqlExpr = substr.substring(2, substr.length() - 1);
|
||||
Expression expr = ExpressionUtils.parseExpression(sqlExpr);
|
||||
String result = executeSqlExpr(expr, context);
|
||||
sqlForUse = sqlForUse.replace(substr, result);
|
||||
}
|
||||
Utils.logToConsole("DESIGN SQL:" + sqlForUse);
|
||||
return sqlForUse;
|
||||
}
|
||||
}
|
||||
|
||||
private String executeSqlExpr(Expression sqlExpr, Context context) {
|
||||
String sqlForUse = null;
|
||||
ExpressionData<?> exprData = sqlExpr.execute(null, null, context);
|
||||
if (exprData instanceof ObjectExpressionData) {
|
||||
ObjectExpressionData data = (ObjectExpressionData) exprData;
|
||||
Object obj = data.getData();
|
||||
if (obj != null) {
|
||||
String s = obj.toString();
|
||||
s = s.replaceAll("\\\\", "");
|
||||
sqlForUse = s;
|
||||
}
|
||||
}
|
||||
return sqlForUse;
|
||||
}
|
||||
|
||||
public void testConnection(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String username = req.getParameter("username");
|
||||
String password = req.getParameter("password");
|
||||
String driver = req.getParameter("driver");
|
||||
String url = req.getParameter("url");
|
||||
Connection conn = null;
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
try {
|
||||
Class.forName(driver);
|
||||
conn = DriverManager.getConnection(url, username, password);
|
||||
map.put("result", true);
|
||||
} catch (Exception ex) {
|
||||
map.put("error", ex.toString());
|
||||
map.put("result", false);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
writeObjectToJson(resp, map);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> buildParameters(String parameters) throws IOException, JsonParseException, JsonMappingException {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
if (StringUtils.isBlank(parameters)) {
|
||||
return map;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
List<Map<String, Object>> list = mapper.readValue(parameters, ArrayList.class);
|
||||
for (Map<String, Object> param : list) {
|
||||
String name = param.get("name").toString();
|
||||
DataType type = DataType.valueOf(param.get("type").toString());
|
||||
String defaultValue = (String) param.get("defaultValue");
|
||||
if (defaultValue == null || defaultValue.isEmpty()) {
|
||||
switch (type) {
|
||||
case Boolean:
|
||||
map.put(name, false);
|
||||
case Date:
|
||||
map.put(name, new Date());
|
||||
case Float:
|
||||
map.put(name, (float) 0);
|
||||
case Integer:
|
||||
map.put(name, 0);
|
||||
case String:
|
||||
if (defaultValue != null) {
|
||||
map.put(name, "");
|
||||
} else {
|
||||
map.put(name, "null");
|
||||
}
|
||||
break;
|
||||
case List:
|
||||
map.put(name, new ArrayList<>());
|
||||
}
|
||||
} else {
|
||||
map.put(name, type.parse(defaultValue));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private Connection buildConnection(HttpServletRequest req) throws Exception {
|
||||
String type = req.getParameter("type");
|
||||
if (type.equals("jdbc")) {
|
||||
String username = req.getParameter("username");
|
||||
String password = req.getParameter("password");
|
||||
String driver = req.getParameter("driver");
|
||||
String url = req.getParameter("url");
|
||||
|
||||
Class.forName(driver);
|
||||
return DriverManager.getConnection(url, username, password);
|
||||
} else {
|
||||
String name = req.getParameter("name");
|
||||
Connection conn = Utils.getBuildinConnection(name);
|
||||
if (conn == null) {
|
||||
throw new ReportDesignException("Buildin datasource [" + name + "] not exist.");
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/datasource";
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.designer;
|
||||
|
||||
import com.bstek.ureport.cache.CacheUtils;
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.dsl.ReportParserLexer;
|
||||
import com.bstek.ureport.dsl.ReportParserParser;
|
||||
import com.bstek.ureport.dsl.ReportParserParser.DatasetContext;
|
||||
import com.bstek.ureport.export.ReportRender;
|
||||
import com.bstek.ureport.expression.ErrorInfo;
|
||||
import com.bstek.ureport.expression.ScriptErrorListener;
|
||||
import com.bstek.ureport.parser.ReportParser;
|
||||
import com.bstek.ureport.provider.report.ReportProvider;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年1月25日
|
||||
*/
|
||||
public class DesignerServletAction extends RenderPageServletAction {
|
||||
private ReportRender reportRender;
|
||||
private ReportParser reportParser;
|
||||
private List<ReportProvider> reportProviders = new ArrayList<ReportProvider>();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("contextPath", req.getContextPath());
|
||||
resp.setContentType("text/html");
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
Template template = ve.getTemplate("ureport-html/designer.html", "utf-8");
|
||||
PrintWriter writer = resp.getWriter();
|
||||
template.merge(context, writer);
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void scriptValidation(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String content = req.getParameter("content");
|
||||
ANTLRInputStream antlrInputStream = new ANTLRInputStream(content);
|
||||
ReportParserLexer lexer = new ReportParserLexer(antlrInputStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
ReportParserParser parser = new ReportParserParser(tokenStream);
|
||||
ScriptErrorListener errorListener = new ScriptErrorListener();
|
||||
parser.removeErrorListeners();
|
||||
parser.addErrorListener(errorListener);
|
||||
parser.expression();
|
||||
List<ErrorInfo> infos = errorListener.getInfos();
|
||||
writeObjectToJson(resp, infos);
|
||||
}
|
||||
|
||||
public void conditionScriptValidation(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String content = req.getParameter("content");
|
||||
ANTLRInputStream antlrInputStream = new ANTLRInputStream(content);
|
||||
ReportParserLexer lexer = new ReportParserLexer(antlrInputStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
ReportParserParser parser = new ReportParserParser(tokenStream);
|
||||
ScriptErrorListener errorListener = new ScriptErrorListener();
|
||||
parser.removeErrorListeners();
|
||||
parser.addErrorListener(errorListener);
|
||||
parser.expr();
|
||||
List<ErrorInfo> infos = errorListener.getInfos();
|
||||
writeObjectToJson(resp, infos);
|
||||
}
|
||||
|
||||
|
||||
public void parseDatasetName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String expr = req.getParameter("expr");
|
||||
ANTLRInputStream antlrInputStream = new ANTLRInputStream(expr);
|
||||
ReportParserLexer lexer = new ReportParserLexer(antlrInputStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
ReportParserParser parser = new ReportParserParser(tokenStream);
|
||||
parser.removeErrorListeners();
|
||||
DatasetContext ctx = parser.dataset();
|
||||
String datasetName = ctx.Identifier().getText();
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
result.put("datasetName", datasetName);
|
||||
writeObjectToJson(resp, result);
|
||||
}
|
||||
|
||||
public void savePreviewData(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String content = req.getParameter("content");
|
||||
content = decodeContent(content);
|
||||
InputStream inputStream = IOUtils.toInputStream(content, "utf-8");
|
||||
ReportDefinition reportDef = reportParser.parse(inputStream, "p");
|
||||
reportRender.rebuildReportDefinition(reportDef);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
TempObjectCache.putObject(PREVIEW_KEY, reportDef);
|
||||
}
|
||||
|
||||
public void loadReport(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("file");
|
||||
if (file == null) {
|
||||
throw new ReportDesignException("Report file can not be null.");
|
||||
}
|
||||
file = ReportUtils.decodeFileName(file);
|
||||
Object obj = TempObjectCache.getObject(file);
|
||||
if (obj != null && obj instanceof ReportDefinition) {
|
||||
ReportDefinition reportDef = (ReportDefinition) obj;
|
||||
TempObjectCache.removeObject(file);
|
||||
writeObjectToJson(resp, new ReportDefinitionWrapper(reportDef));
|
||||
} else {
|
||||
ReportDefinition reportDef = reportRender.parseReport(file);
|
||||
writeObjectToJson(resp, new ReportDefinitionWrapper(reportDef));
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteReportFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("file");
|
||||
if (file == null) {
|
||||
throw new ReportDesignException("Report file can not be null.");
|
||||
}
|
||||
ReportProvider targetReportProvider = null;
|
||||
for (ReportProvider provider : reportProviders) {
|
||||
if (file.startsWith(provider.getPrefix())) {
|
||||
targetReportProvider = provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetReportProvider == null) {
|
||||
throw new ReportDesignException("File [" + file + "] not found available report provider.");
|
||||
}
|
||||
targetReportProvider.deleteReport(file);
|
||||
}
|
||||
|
||||
|
||||
public void saveReportFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("file");
|
||||
file = ReportUtils.decodeFileName(file);
|
||||
String content = req.getParameter("content");
|
||||
content = decodeContent(content);
|
||||
ReportProvider targetReportProvider = null;
|
||||
for (ReportProvider provider : reportProviders) {
|
||||
if (file.startsWith(provider.getPrefix())) {
|
||||
targetReportProvider = provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetReportProvider == null) {
|
||||
throw new ReportDesignException("File [" + file + "] not found available report provider.");
|
||||
}
|
||||
targetReportProvider.saveReport(file, content);
|
||||
InputStream inputStream = IOUtils.toInputStream(content, "utf-8");
|
||||
ReportDefinition reportDef = reportParser.parse(inputStream, file);
|
||||
reportRender.rebuildReportDefinition(reportDef);
|
||||
CacheUtils.cacheReportDefinition(file, reportDef);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
|
||||
public void loadReportProviders(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
writeObjectToJson(resp, reportProviders);
|
||||
}
|
||||
|
||||
public void setReportRender(ReportRender reportRender) {
|
||||
this.reportRender = reportRender;
|
||||
}
|
||||
|
||||
public void setReportParser(ReportParser reportParser) {
|
||||
this.reportParser = reportParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
super.setApplicationContext(applicationContext);
|
||||
Collection<ReportProvider> providers = applicationContext.getBeansOfType(ReportProvider.class).values();
|
||||
for (ReportProvider provider : providers) {
|
||||
if (provider.disabled() || provider.getName() == null) {
|
||||
continue;
|
||||
}
|
||||
reportProviders.add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/designer";
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.designer;
|
||||
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年10月24日
|
||||
*/
|
||||
public class SearchFormDesignerAction extends RenderPageServletAction {
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("contextPath", req.getContextPath());
|
||||
resp.setContentType("text/html");
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
Template template = ve.getTemplate("ureport-html/searchform.html", "utf-8");
|
||||
PrintWriter writer = resp.getWriter();
|
||||
template.merge(context, writer);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/searchFormDesigner";
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.excel;
|
||||
|
||||
import com.bstek.ureport.build.ReportBuilder;
|
||||
import com.bstek.ureport.console.BaseServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.export.ExportConfigure;
|
||||
import com.bstek.ureport.export.ExportConfigureImpl;
|
||||
import com.bstek.ureport.export.ExportManager;
|
||||
import com.bstek.ureport.export.excel.low.Excel97Producer;
|
||||
import com.bstek.ureport.model.Report;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年7月3日
|
||||
*/
|
||||
public class ExportExcel97ServletAction extends BaseServletAction {
|
||||
private ReportBuilder reportBuilder;
|
||||
private ExportManager exportManager;
|
||||
private Excel97Producer excelProducer = new Excel97Producer();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
buildExcel(req, resp, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void paging(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
buildExcel(req, resp, true, false);
|
||||
}
|
||||
|
||||
public void sheet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
buildExcel(req, resp, false, true);
|
||||
}
|
||||
|
||||
public void buildExcel(HttpServletRequest req, HttpServletResponse resp, boolean withPage, boolean withSheet) throws IOException {
|
||||
String file = req.getParameter("_u");
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
String fileName = req.getParameter("_n");
|
||||
if (StringUtils.isNotBlank(fileName)) {
|
||||
fileName = decode(fileName);
|
||||
} else {
|
||||
fileName = "ureport.xls";
|
||||
}
|
||||
resp.setContentType("application/octet-stream;charset=ISO8859-1");
|
||||
resp.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
OutputStream outputStream = resp.getOutputStream();
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export excel.");
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
if (withPage) {
|
||||
excelProducer.produceWithPaging(report, outputStream);
|
||||
} else if (withSheet) {
|
||||
excelProducer.produceWithSheet(report, outputStream);
|
||||
} else {
|
||||
excelProducer.produce(report, outputStream);
|
||||
}
|
||||
} else {
|
||||
ExportConfigure configure = new ExportConfigureImpl(file, parameters, outputStream);
|
||||
if (withPage) {
|
||||
exportManager.exportExcelWithPaging(configure);
|
||||
} else if (withSheet) {
|
||||
exportManager.exportExcelWithPagingSheet(configure);
|
||||
} else {
|
||||
exportManager.exportExcel(configure);
|
||||
}
|
||||
}
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
public void setReportBuilder(ReportBuilder reportBuilder) {
|
||||
this.reportBuilder = reportBuilder;
|
||||
}
|
||||
|
||||
public void setExportManager(ExportManager exportManager) {
|
||||
this.exportManager = exportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/excel97";
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.excel;
|
||||
|
||||
import com.bstek.ureport.build.ReportBuilder;
|
||||
import com.bstek.ureport.console.BaseServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.exception.ReportException;
|
||||
import com.bstek.ureport.export.ExportConfigure;
|
||||
import com.bstek.ureport.export.ExportConfigureImpl;
|
||||
import com.bstek.ureport.export.ExportManager;
|
||||
import com.bstek.ureport.export.excel.high.ExcelProducer;
|
||||
import com.bstek.ureport.model.Report;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年4月17日
|
||||
*/
|
||||
public class ExportExcelServletAction extends BaseServletAction {
|
||||
private ReportBuilder reportBuilder;
|
||||
private ExportManager exportManager;
|
||||
private ExcelProducer excelProducer = new ExcelProducer();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
buildExcel(req, resp, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void paging(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
buildExcel(req, resp, true, false);
|
||||
}
|
||||
|
||||
public void sheet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
buildExcel(req, resp, false, true);
|
||||
}
|
||||
|
||||
public void buildExcel(HttpServletRequest req, HttpServletResponse resp, boolean withPage, boolean withSheet) throws IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
OutputStream outputStream = resp.getOutputStream();
|
||||
try {
|
||||
String fileName = req.getParameter("_n");
|
||||
fileName = buildDownloadFileName(file, fileName, ".xlsx");
|
||||
resp.setContentType("application/octet-stream;charset=ISO8859-1");
|
||||
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
|
||||
resp.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export excel.");
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
if (withPage) {
|
||||
excelProducer.produceWithPaging(report, outputStream);
|
||||
} else if (withSheet) {
|
||||
excelProducer.produceWithSheet(report, outputStream);
|
||||
} else {
|
||||
excelProducer.produce(report, outputStream);
|
||||
}
|
||||
} else {
|
||||
ExportConfigure configure = new ExportConfigureImpl(file, parameters, outputStream);
|
||||
if (withPage) {
|
||||
exportManager.exportExcelWithPaging(configure);
|
||||
} else if (withSheet) {
|
||||
exportManager.exportExcelWithPagingSheet(configure);
|
||||
} else {
|
||||
exportManager.exportExcel(configure);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new ReportException(ex);
|
||||
} finally {
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void setReportBuilder(ReportBuilder reportBuilder) {
|
||||
this.reportBuilder = reportBuilder;
|
||||
}
|
||||
|
||||
public void setExportManager(ExportManager exportManager) {
|
||||
this.exportManager = exportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/excel";
|
||||
}
|
||||
}
|
@ -0,0 +1,365 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.html;
|
||||
|
||||
import com.bstek.ureport.build.Context;
|
||||
import com.bstek.ureport.build.ReportBuilder;
|
||||
import com.bstek.ureport.build.paging.Page;
|
||||
import com.bstek.ureport.cache.CacheUtils;
|
||||
import com.bstek.ureport.chart.ChartData;
|
||||
import com.bstek.ureport.console.MobileUtils;
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.Paper;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.definition.searchform.FormPosition;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.export.*;
|
||||
import com.bstek.ureport.export.html.HtmlProducer;
|
||||
import com.bstek.ureport.export.html.HtmlReport;
|
||||
import com.bstek.ureport.export.html.SearchFormData;
|
||||
import com.bstek.ureport.model.Report;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年2月15日
|
||||
*/
|
||||
public class HtmlPreviewServletAction extends RenderPageServletAction {
|
||||
private ExportManager exportManager;
|
||||
private ReportBuilder reportBuilder;
|
||||
private ReportRender reportRender;
|
||||
private HtmlProducer htmlProducer = new HtmlProducer();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
VelocityContext context = new VelocityContext();
|
||||
HtmlReport htmlReport = null;
|
||||
String errorMsg = null;
|
||||
try {
|
||||
htmlReport = loadReport(req);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ReportDesignException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
errorMsg = buildExceptionMessage(ex);
|
||||
}
|
||||
String title = buildTitle(req);
|
||||
context.put("title", title);
|
||||
if (htmlReport == null) {
|
||||
context.put("content", "<div style='color:red'><strong>报表计算出错,错误信息如下:</strong><br><div style=\"margin:10px\">" + errorMsg + "</div></div>");
|
||||
context.put("error", true);
|
||||
context.put("searchFormJs", "");
|
||||
context.put("downSearchFormHtml", "");
|
||||
context.put("upSearchFormHtml", "");
|
||||
} else {
|
||||
SearchFormData formData = htmlReport.getSearchFormData();
|
||||
if (formData != null) {
|
||||
context.put("searchFormJs", formData.getJs());
|
||||
if (formData.getFormPosition().equals(FormPosition.up)) {
|
||||
context.put("upSearchFormHtml", formData.getHtml());
|
||||
context.put("downSearchFormHtml", "");
|
||||
} else {
|
||||
context.put("downSearchFormHtml", formData.getHtml());
|
||||
context.put("upSearchFormHtml", "");
|
||||
}
|
||||
} else {
|
||||
context.put("searchFormJs", "");
|
||||
context.put("downSearchFormHtml", "");
|
||||
context.put("upSearchFormHtml", "");
|
||||
}
|
||||
context.put("content", htmlReport.getContent());
|
||||
context.put("style", htmlReport.getStyle());
|
||||
context.put("reportAlign", htmlReport.getReportAlign());
|
||||
context.put("totalPage", htmlReport.getTotalPage());
|
||||
context.put("totalPageWithCol", htmlReport.getTotalPageWithCol());
|
||||
context.put("pageIndex", htmlReport.getPageIndex());
|
||||
context.put("chartDatas", convertJson(htmlReport.getChartDatas()));
|
||||
context.put("error", false);
|
||||
context.put("file", req.getParameter("_u"));
|
||||
context.put("intervalRefreshValue", htmlReport.getHtmlIntervalRefreshValue());
|
||||
String customParameters = buildCustomParameters(req);
|
||||
context.put("customParameters", customParameters);
|
||||
context.put("_t", "");
|
||||
Tools tools = null;
|
||||
if (MobileUtils.isMobile(req)) {
|
||||
tools = new Tools(false);
|
||||
tools.setShow(false);
|
||||
} else {
|
||||
String toolsInfo = req.getParameter("_t");
|
||||
if (StringUtils.isNotBlank(toolsInfo)) {
|
||||
tools = new Tools(false);
|
||||
if (toolsInfo.equals("0")) {
|
||||
tools.setShow(false);
|
||||
} else {
|
||||
String[] infos = toolsInfo.split(",");
|
||||
for (String name : infos) {
|
||||
tools.doInit(name);
|
||||
}
|
||||
}
|
||||
context.put("_t", toolsInfo);
|
||||
context.put("hasTools", true);
|
||||
} else {
|
||||
tools = new Tools(true);
|
||||
}
|
||||
}
|
||||
context.put("tools", tools);
|
||||
}
|
||||
context.put("contextPath", req.getContextPath());
|
||||
resp.setContentType("text/html");
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
Template template = ve.getTemplate("ureport-html/html-preview.html", "utf-8");
|
||||
PrintWriter writer = resp.getWriter();
|
||||
template.merge(context, writer);
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String buildTitle(HttpServletRequest req) {
|
||||
String title = req.getParameter("_title");
|
||||
if (StringUtils.isBlank(title)) {
|
||||
title = req.getParameter("_u");
|
||||
title = decode(title);
|
||||
int point = title.lastIndexOf(".ureport.xml");
|
||||
if (point > -1) {
|
||||
title = title.substring(0, point);
|
||||
}
|
||||
if (title.equals("p")) {
|
||||
title = "设计中报表";
|
||||
}
|
||||
} else {
|
||||
title = decode(title);
|
||||
}
|
||||
return title + "-ureport";
|
||||
}
|
||||
|
||||
private String convertJson(Collection<ChartData> data) {
|
||||
if (data == null || data.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
String json = mapper.writeValueAsString(data);
|
||||
return json;
|
||||
} catch (Exception e) {
|
||||
throw new ReportComputeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadData(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
HtmlReport htmlReport = loadReport(req);
|
||||
writeObjectToJson(resp, htmlReport);
|
||||
}
|
||||
|
||||
public void loadPrintPages(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
ReportDefinition reportDefinition = null;
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export excel.");
|
||||
}
|
||||
} else {
|
||||
reportDefinition = reportRender.getReportDefinition(file);
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
Map<String, ChartData> chartMap = report.getContext().getChartDataMap();
|
||||
if (chartMap.size() > 0) {
|
||||
CacheUtils.storeChartDataMap(chartMap);
|
||||
}
|
||||
FullPageData pageData = PageBuilder.buildFullPageData(report);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<List<Page>> list = pageData.getPageList();
|
||||
Context context = report.getContext();
|
||||
if (list.size() > 0) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
List<Page> columnPages = list.get(i);
|
||||
if (i == 0) {
|
||||
String html = htmlProducer.produce(context, columnPages, pageData.getColumnMargin(), false);
|
||||
sb.append(html);
|
||||
} else {
|
||||
String html = htmlProducer.produce(context, columnPages, pageData.getColumnMargin(), false);
|
||||
sb.append(html);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Page> pages = report.getPages();
|
||||
for (int i = 0; i < pages.size(); i++) {
|
||||
Page page = pages.get(i);
|
||||
if (i == 0) {
|
||||
String html = htmlProducer.produce(context, page, false);
|
||||
sb.append(html);
|
||||
} else {
|
||||
String html = htmlProducer.produce(context, page, true);
|
||||
sb.append(html);
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("html", sb.toString());
|
||||
writeObjectToJson(resp, map);
|
||||
}
|
||||
|
||||
public void loadPagePaper(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
ReportDefinition report = null;
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
report = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (report == null) {
|
||||
throw new ReportDesignException("Report data has expired.");
|
||||
}
|
||||
} else {
|
||||
report = reportRender.getReportDefinition(file);
|
||||
}
|
||||
Paper paper = report.getPaper();
|
||||
writeObjectToJson(resp, paper);
|
||||
}
|
||||
|
||||
private HtmlReport loadReport(HttpServletRequest req) {
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
HtmlReport htmlReport = null;
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
String pageIndex = req.getParameter("_i");
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do preview.");
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
Map<String, ChartData> chartMap = report.getContext().getChartDataMap();
|
||||
if (chartMap.size() > 0) {
|
||||
CacheUtils.storeChartDataMap(chartMap);
|
||||
}
|
||||
htmlReport = new HtmlReport();
|
||||
String html = null;
|
||||
if (StringUtils.isNotBlank(pageIndex) && !pageIndex.equals("0")) {
|
||||
Context context = report.getContext();
|
||||
int index = Integer.valueOf(pageIndex);
|
||||
SinglePageData pageData = PageBuilder.buildSinglePageData(index, report);
|
||||
List<Page> pages = pageData.getPages();
|
||||
if (pages.size() == 1) {
|
||||
Page page = pages.get(0);
|
||||
html = htmlProducer.produce(context, page, false);
|
||||
} else {
|
||||
html = htmlProducer.produce(context, pages, pageData.getColumnMargin(), false);
|
||||
}
|
||||
htmlReport.setTotalPage(pageData.getTotalPages());
|
||||
htmlReport.setPageIndex(index);
|
||||
} else {
|
||||
html = htmlProducer.produce(report);
|
||||
}
|
||||
if (report.getPaper().isColumnEnabled()) {
|
||||
htmlReport.setColumn(report.getPaper().getColumnCount());
|
||||
}
|
||||
htmlReport.setChartDatas(report.getContext().getChartDataMap().values());
|
||||
htmlReport.setContent(html);
|
||||
htmlReport.setTotalPage(report.getPages().size());
|
||||
htmlReport.setStyle(reportDefinition.getStyle());
|
||||
htmlReport.setSearchFormData(reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(), parameters));
|
||||
htmlReport.setReportAlign(report.getPaper().getHtmlReportAlign().name());
|
||||
htmlReport.setHtmlIntervalRefreshValue(report.getPaper().getHtmlIntervalRefreshValue());
|
||||
} else {
|
||||
if (StringUtils.isNotBlank(pageIndex) && !pageIndex.equals("0")) {
|
||||
int index = Integer.valueOf(pageIndex);
|
||||
htmlReport = exportManager.exportHtml(file, req.getContextPath(), parameters, index);
|
||||
} else {
|
||||
htmlReport = exportManager.exportHtml(file, req.getContextPath(), parameters);
|
||||
}
|
||||
}
|
||||
return htmlReport;
|
||||
}
|
||||
|
||||
|
||||
private String buildCustomParameters(HttpServletRequest req) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Enumeration<?> enumeration = req.getParameterNames();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Object obj = enumeration.nextElement();
|
||||
if (obj == null) {
|
||||
continue;
|
||||
}
|
||||
String name = obj.toString();
|
||||
String value = req.getParameter(name);
|
||||
if (name == null || value == null || (name.startsWith("_") && !name.equals("_n"))) {
|
||||
continue;
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.append("&");
|
||||
}
|
||||
sb.append(name);
|
||||
sb.append("=");
|
||||
sb.append(value);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String buildExceptionMessage(Throwable throwable) {
|
||||
Throwable root = buildRootException(throwable);
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
root.printStackTrace(pw);
|
||||
String trace = sw.getBuffer().toString();
|
||||
trace = trace.replaceAll("\n", "<br>");
|
||||
pw.close();
|
||||
return trace;
|
||||
}
|
||||
|
||||
public void setExportManager(ExportManager exportManager) {
|
||||
this.exportManager = exportManager;
|
||||
}
|
||||
|
||||
public void setReportBuilder(ReportBuilder reportBuilder) {
|
||||
this.reportBuilder = reportBuilder;
|
||||
}
|
||||
|
||||
public void setReportRender(ReportRender reportRender) {
|
||||
this.reportRender = reportRender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/preview";
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.image;
|
||||
|
||||
import com.bstek.ureport.cache.ResourceCache;
|
||||
import com.bstek.ureport.console.ServletAction;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2016年6月6日
|
||||
*/
|
||||
public class ImageServletAction implements ServletAction {
|
||||
public static final String URL = "/image";
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String key = req.getParameter("_key");
|
||||
if (StringUtils.isNotBlank(key)) {
|
||||
byte[] bytes = (byte[]) ResourceCache.getObject(key);
|
||||
InputStream input = new ByteArrayInputStream(bytes);
|
||||
OutputStream output = resp.getOutputStream();
|
||||
resp.setContentType("image/png");
|
||||
try {
|
||||
IOUtils.copy(input, output);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
IOUtils.closeQuietly(output);
|
||||
}
|
||||
} else {
|
||||
//processImage(req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return URL;
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.importexcel;
|
||||
|
||||
import com.bstek.ureport.console.RenderPageServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springblade.core.tool.utils.MultipartUtil;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年5月25日
|
||||
*/
|
||||
public class ImportExcelServletAction extends RenderPageServletAction {
|
||||
private List<ExcelParser> excelParsers = new ArrayList<ExcelParser>();
|
||||
|
||||
public ImportExcelServletAction() {
|
||||
excelParsers.add(new HSSFExcelParser());
|
||||
excelParsers.add(new XSSFExcelParser());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String errorInfo;
|
||||
ReportDefinition report = null;
|
||||
try {
|
||||
List<MultipartFile> items = MultipartUtil.extractMultipartFiles(req);
|
||||
for (MultipartFile item : items) {
|
||||
String fieldName = item.getName();
|
||||
String name = Objects.requireNonNull(item.getOriginalFilename()).toLowerCase();
|
||||
if (fieldName.equals("_excel_file") && (name.endsWith(".xls") || name.endsWith(".xlsx"))) {
|
||||
InputStream inputStream = item.getInputStream();
|
||||
for (ExcelParser parser : excelParsers) {
|
||||
if (parser.support(name)) {
|
||||
report = parser.parse(inputStream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inputStream.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
errorInfo = "请选择一个合法的Excel导入";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
errorInfo = e.getMessage();
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
if (report != null) {
|
||||
result.put("result", true);
|
||||
TempObjectCache.putObject("classpath:template/template.ureport.xml", report);
|
||||
} else {
|
||||
result.put("result", false);
|
||||
if (errorInfo != null) {
|
||||
result.put("errorInfo", errorInfo);
|
||||
}
|
||||
}
|
||||
writeObjectToJson(resp, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/import";
|
||||
}
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.pdf;
|
||||
|
||||
import com.bstek.ureport.build.ReportBuilder;
|
||||
import com.bstek.ureport.console.BaseServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.Paper;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.exception.ReportException;
|
||||
import com.bstek.ureport.export.ExportConfigure;
|
||||
import com.bstek.ureport.export.ExportConfigureImpl;
|
||||
import com.bstek.ureport.export.ExportManager;
|
||||
import com.bstek.ureport.export.ReportRender;
|
||||
import com.bstek.ureport.export.pdf.PdfProducer;
|
||||
import com.bstek.ureport.model.Report;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月20日
|
||||
*/
|
||||
public class ExportPdfServletAction extends BaseServletAction {
|
||||
private ReportBuilder reportBuilder;
|
||||
private ExportManager exportManager;
|
||||
private ReportRender reportRender;
|
||||
private PdfProducer pdfProducer = new PdfProducer();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
buildPdf(req, resp, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void show(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
buildPdf(req, resp, true);
|
||||
}
|
||||
|
||||
public void buildPdf(HttpServletRequest req, HttpServletResponse resp, boolean forPrint) throws IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
String fileName = req.getParameter("_n");
|
||||
fileName = buildDownloadFileName(file, fileName, ".pdf");
|
||||
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
|
||||
if (forPrint) {
|
||||
resp.setContentType("application/pdf");
|
||||
resp.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
|
||||
} else {
|
||||
resp.setContentType("application/octet-stream;charset=ISO8859-1");
|
||||
resp.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
|
||||
}
|
||||
outputStream = resp.getOutputStream();
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export pdf.");
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
pdfProducer.produce(report, outputStream);
|
||||
} else {
|
||||
ExportConfigure configure = new ExportConfigureImpl(file, parameters, outputStream);
|
||||
exportManager.exportPdf(configure);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new ReportException(ex);
|
||||
} finally {
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void newPaging(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String file = req.getParameter("_u");
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
Report report = null;
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export pdf.");
|
||||
}
|
||||
report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
} else {
|
||||
ReportDefinition reportDefinition = reportRender.getReportDefinition(file);
|
||||
report = reportRender.render(reportDefinition, parameters);
|
||||
}
|
||||
String paper = req.getParameter("_paper");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Paper newPaper = mapper.readValue(paper, Paper.class);
|
||||
report.rePaging(newPaper);
|
||||
}
|
||||
|
||||
public void setReportRender(ReportRender reportRender) {
|
||||
this.reportRender = reportRender;
|
||||
}
|
||||
|
||||
public void setExportManager(ExportManager exportManager) {
|
||||
this.exportManager = exportManager;
|
||||
}
|
||||
|
||||
public void setReportBuilder(ReportBuilder reportBuilder) {
|
||||
this.reportBuilder = reportBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/pdf";
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.res;
|
||||
|
||||
import com.bstek.ureport.console.ServletAction;
|
||||
import com.bstek.ureport.console.UReportServlet;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2016年6月6日
|
||||
*/
|
||||
public class ResourceLoaderServletAction implements ServletAction, ApplicationContextAware {
|
||||
public static final String URL = "/res";
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String path = req.getContextPath() + UReportServlet.URL + URL;
|
||||
String uri = req.getRequestURI();
|
||||
String resPath = uri.substring(path.length() + 1);
|
||||
String p = "classpath:" + resPath;
|
||||
if (p.endsWith(".js")) {
|
||||
resp.setContentType("text/javascript");
|
||||
} else if (p.endsWith(".css")) {
|
||||
resp.setContentType("text/css");
|
||||
} else if (p.endsWith(".png")) {
|
||||
resp.setContentType("image/png");
|
||||
} else if (p.endsWith(".jpg")) {
|
||||
resp.setContentType("image/jpeg");
|
||||
} else if (p.endsWith(".svg")) {
|
||||
resp.setContentType("image/svg+xml");
|
||||
} else {
|
||||
resp.setContentType("application/octet-stream");
|
||||
}
|
||||
InputStream input = applicationContext.getResource(p).getInputStream();
|
||||
OutputStream output = resp.getOutputStream();
|
||||
try {
|
||||
IOUtils.copy(input, output);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
IOUtils.closeQuietly(output);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return URL;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.console.word;
|
||||
|
||||
import com.bstek.ureport.build.ReportBuilder;
|
||||
import com.bstek.ureport.console.BaseServletAction;
|
||||
import com.bstek.ureport.console.cache.TempObjectCache;
|
||||
import com.bstek.ureport.console.exception.ReportDesignException;
|
||||
import com.bstek.ureport.definition.ReportDefinition;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.exception.ReportException;
|
||||
import com.bstek.ureport.export.ExportConfigure;
|
||||
import com.bstek.ureport.export.ExportConfigureImpl;
|
||||
import com.bstek.ureport.export.ExportManager;
|
||||
import com.bstek.ureport.export.word.high.WordProducer;
|
||||
import com.bstek.ureport.model.Report;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年4月17日
|
||||
*/
|
||||
public class ExportWordServletAction extends BaseServletAction {
|
||||
private ReportBuilder reportBuilder;
|
||||
private ExportManager exportManager;
|
||||
private WordProducer wordProducer = new WordProducer();
|
||||
|
||||
@Override
|
||||
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String method = retriveMethod(req);
|
||||
if (method != null) {
|
||||
invokeMethod(method, req, resp);
|
||||
} else {
|
||||
buildWord(req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildWord(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String file = req.getParameter("_u");
|
||||
file = decode(file);
|
||||
if (StringUtils.isBlank(file)) {
|
||||
throw new ReportComputeException("Report file can not be null.");
|
||||
}
|
||||
OutputStream outputStream = resp.getOutputStream();
|
||||
try {
|
||||
String fileName = req.getParameter("_n");
|
||||
fileName = buildDownloadFileName(file, fileName, ".docx");
|
||||
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
|
||||
resp.setContentType("application/octet-stream;charset=ISO8859-1");
|
||||
resp.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
|
||||
Map<String, Object> parameters = buildParameters(req);
|
||||
if (file.equals(PREVIEW_KEY)) {
|
||||
ReportDefinition reportDefinition = (ReportDefinition) TempObjectCache.getObject(PREVIEW_KEY);
|
||||
if (reportDefinition == null) {
|
||||
throw new ReportDesignException("Report data has expired,can not do export word.");
|
||||
}
|
||||
Report report = reportBuilder.buildReport(reportDefinition, parameters);
|
||||
wordProducer.produce(report, outputStream);
|
||||
} else {
|
||||
ExportConfigure configure = new ExportConfigureImpl(file, parameters, outputStream);
|
||||
exportManager.exportWord(configure);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new ReportException(ex);
|
||||
} finally {
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void setReportBuilder(ReportBuilder reportBuilder) {
|
||||
this.reportBuilder = reportBuilder;
|
||||
}
|
||||
|
||||
public void setExportManager(ExportManager exportManager) {
|
||||
this.exportManager = exportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return "/word";
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.definition;
|
||||
|
||||
import com.bstek.ureport.export.pdf.font.FontBuilder;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年1月18日
|
||||
*/
|
||||
public class CellStyle implements Serializable {
|
||||
private static final long serialVersionUID = 8327688051735343849L;
|
||||
private String bgcolor;
|
||||
private String forecolor;
|
||||
private int fontSize;
|
||||
private String fontFamily;
|
||||
private String format;
|
||||
private float lineHeight;
|
||||
private Alignment align;
|
||||
private Alignment valign;
|
||||
private Boolean bold;
|
||||
private Boolean italic;
|
||||
private Boolean underline;
|
||||
private Boolean wrapCompute;
|
||||
private Border leftBorder;
|
||||
private Border rightBorder;
|
||||
private Border topBorder;
|
||||
private Border bottomBorder;
|
||||
|
||||
private Font font;
|
||||
|
||||
public Border getLeftBorder() {
|
||||
return leftBorder;
|
||||
}
|
||||
|
||||
public void setLeftBorder(Border leftBorder) {
|
||||
this.leftBorder = leftBorder;
|
||||
}
|
||||
|
||||
public Border getRightBorder() {
|
||||
return rightBorder;
|
||||
}
|
||||
|
||||
public void setRightBorder(Border rightBorder) {
|
||||
this.rightBorder = rightBorder;
|
||||
}
|
||||
|
||||
public Border getTopBorder() {
|
||||
return topBorder;
|
||||
}
|
||||
|
||||
public void setTopBorder(Border topBorder) {
|
||||
this.topBorder = topBorder;
|
||||
}
|
||||
|
||||
public Border getBottomBorder() {
|
||||
return bottomBorder;
|
||||
}
|
||||
|
||||
public void setBottomBorder(Border bottomBorder) {
|
||||
this.bottomBorder = bottomBorder;
|
||||
}
|
||||
|
||||
public String getBgcolor() {
|
||||
return bgcolor;
|
||||
}
|
||||
|
||||
public void setBgcolor(String bgcolor) {
|
||||
this.bgcolor = bgcolor;
|
||||
}
|
||||
|
||||
public String getForecolor() {
|
||||
return forecolor;
|
||||
}
|
||||
|
||||
public void setForecolor(String forecolor) {
|
||||
this.forecolor = forecolor;
|
||||
}
|
||||
|
||||
public int getFontSize() {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
public void setFontSize(int fontSize) {
|
||||
this.fontSize = fontSize;
|
||||
}
|
||||
|
||||
public String getFontFamily() {
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
public void setFontFamily(String fontFamily) {
|
||||
this.fontFamily = fontFamily;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public Alignment getAlign() {
|
||||
return align;
|
||||
}
|
||||
|
||||
public void setAlign(Alignment align) {
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
public Alignment getValign() {
|
||||
return valign;
|
||||
}
|
||||
|
||||
public void setValign(Alignment valign) {
|
||||
this.valign = valign;
|
||||
}
|
||||
|
||||
public Boolean getBold() {
|
||||
return bold;
|
||||
}
|
||||
|
||||
public void setBold(Boolean bold) {
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public Boolean getItalic() {
|
||||
return italic;
|
||||
}
|
||||
|
||||
public void setItalic(Boolean italic) {
|
||||
this.italic = italic;
|
||||
}
|
||||
|
||||
public Boolean getUnderline() {
|
||||
return underline;
|
||||
}
|
||||
|
||||
public void setUnderline(Boolean underline) {
|
||||
this.underline = underline;
|
||||
}
|
||||
|
||||
public Boolean getWrapCompute() {
|
||||
return wrapCompute;
|
||||
}
|
||||
|
||||
public void setWrapCompute(Boolean wrapCompute) {
|
||||
this.wrapCompute = wrapCompute;
|
||||
}
|
||||
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
public float getLineHeight() {
|
||||
return lineHeight;
|
||||
}
|
||||
|
||||
public void setLineHeight(float lineHeight) {
|
||||
this.lineHeight = lineHeight;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Font getFont() {
|
||||
if (this.font == null) {
|
||||
int fontStyle = Font.PLAIN;
|
||||
if ((bold != null && bold) && (italic != null && italic)) {
|
||||
fontStyle = Font.BOLD | Font.ITALIC;
|
||||
} else if (bold != null && bold) {
|
||||
fontStyle = Font.BOLD;
|
||||
} else if (italic != null && italic) {
|
||||
fontStyle = Font.ITALIC;
|
||||
}
|
||||
String fontName = fontFamily;
|
||||
if (StringUtils.isBlank(fontName)) {
|
||||
fontName = "宋体";
|
||||
}
|
||||
this.font = FontBuilder.getAwtFont(fontName, fontStyle, (float) fontSize);
|
||||
}
|
||||
return this.font;
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.font;
|
||||
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.exception.ReportException;
|
||||
import com.bstek.ureport.export.pdf.font.FontRegister;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.Font;
|
||||
import com.itextpdf.text.FontFactory;
|
||||
import com.itextpdf.text.pdf.BaseFont;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2014年4月22日
|
||||
*/
|
||||
public class FontBuilder implements ApplicationContextAware {
|
||||
private static ApplicationContext applicationContext;
|
||||
private static final Map<String, BaseFont> fontMap = new HashMap<String, BaseFont>();
|
||||
public static final Map<String, String> fontPathMap = new HashMap<String, String>();
|
||||
private static List<String> systemFontNameList = new ArrayList<String>();
|
||||
|
||||
public static Font getFont(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean underLine) {
|
||||
BaseFont baseFont = fontMap.get(fontName);
|
||||
Font font = null;
|
||||
if (baseFont != null) {
|
||||
font = new Font(baseFont);
|
||||
} else {
|
||||
font = FontFactory.getFont(fontName);
|
||||
}
|
||||
font.setSize(fontSize);
|
||||
int fontStyle = Font.NORMAL;
|
||||
if (fontBold && fontItalic && underLine) {
|
||||
fontStyle = Font.BOLD | Font.ITALIC | Font.UNDERLINE;
|
||||
} else if (fontBold) {
|
||||
if (fontItalic) {
|
||||
fontStyle = Font.BOLD | Font.ITALIC;
|
||||
} else if (underLine) {
|
||||
fontStyle = Font.BOLD | Font.UNDERLINE;
|
||||
} else {
|
||||
fontStyle = Font.BOLD;
|
||||
}
|
||||
} else if (fontItalic) {
|
||||
if (underLine) {
|
||||
fontStyle = Font.ITALIC | Font.UNDERLINE;
|
||||
} else if (fontBold) {
|
||||
fontStyle = Font.ITALIC | Font.BOLD;
|
||||
} else {
|
||||
fontStyle = Font.ITALIC;
|
||||
}
|
||||
} else if (underLine) {
|
||||
fontStyle = Font.UNDERLINE;
|
||||
}
|
||||
font.setStyle(fontStyle);
|
||||
return font;
|
||||
}
|
||||
|
||||
public static java.awt.Font getAwtFont(String fontName, int fontStyle, float size) {
|
||||
if (systemFontNameList.contains(fontName)) {
|
||||
return new java.awt.Font(fontName, fontStyle, Integer.parseInt(String.valueOf(size)));
|
||||
}
|
||||
String fontPath = fontPathMap.get(fontName);
|
||||
if (fontPath == null) {
|
||||
fontName = "宋体";
|
||||
fontPath = fontPathMap.get(fontName);
|
||||
if (fontPath == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = applicationContext.getResource(fontPath).getInputStream();
|
||||
java.awt.Font font = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, inputStream);
|
||||
return font.deriveFont(fontStyle, size);
|
||||
} catch (Exception e) {
|
||||
throw new ReportException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
FontBuilder.applicationContext = applicationContext;
|
||||
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
String[] fontNames = environment.getAvailableFontFamilyNames();
|
||||
for (String name : fontNames) {
|
||||
systemFontNameList.add(name);
|
||||
}
|
||||
Collection<FontRegister> fontRegisters = applicationContext.getBeansOfType(FontRegister.class).values();
|
||||
for (FontRegister fontReg : fontRegisters) {
|
||||
String fontName = fontReg.getFontName();
|
||||
String fontPath = fontReg.getFontPath();
|
||||
if (StringUtils.isEmpty(fontPath) || StringUtils.isEmpty(fontName)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
BaseFont baseFont = getIdentityFont(fontName, fontPath, applicationContext);
|
||||
if (baseFont == null) {
|
||||
throw new ReportComputeException("Font " + fontPath + " does not exist");
|
||||
}
|
||||
fontMap.put(fontName, baseFont);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new ReportComputeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BaseFont getIdentityFont(String fontFamily, String fontPath, ApplicationContext applicationContext) throws DocumentException, IOException {
|
||||
if (!fontPath.startsWith(ApplicationContext.CLASSPATH_URL_PREFIX)) {
|
||||
fontPath = ApplicationContext.CLASSPATH_URL_PREFIX + fontPath;
|
||||
}
|
||||
String fontName = fontPath;
|
||||
int lastSlashPos = fontPath.lastIndexOf("/");
|
||||
if (lastSlashPos != -1) {
|
||||
fontName = fontPath.substring(lastSlashPos + 1, fontPath.length());
|
||||
}
|
||||
if (fontName.toLowerCase().endsWith(".ttc")) {
|
||||
fontName = fontName + ",0";
|
||||
}
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
fontPathMap.put(fontFamily, fontPath);
|
||||
inputStream = applicationContext.getResource(fontPath).getInputStream();
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
BaseFont baseFont = BaseFont.createFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, bytes, null);
|
||||
baseFont.setSubset(true);
|
||||
return baseFont;
|
||||
} finally {
|
||||
if (inputStream != null) inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.parser;
|
||||
|
||||
import com.bstek.ureport.cache.ResourceCache;
|
||||
import com.bstek.ureport.definition.*;
|
||||
import com.bstek.ureport.definition.value.Slash;
|
||||
import com.bstek.ureport.definition.value.SlashValue;
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.utils.UnitUtils;
|
||||
import org.springblade.core.tool.utils.Base64Util;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月17日
|
||||
*/
|
||||
public class SlashBuilder {
|
||||
public void buildSlashImage(CellDefinition cell, ReportDefinition report) {
|
||||
int rowNumber = cell.getRowNumber();
|
||||
int colNumber = cell.getColumnNumber();
|
||||
int rowSpan = cell.getRowSpan();
|
||||
int colSpan = cell.getColSpan();
|
||||
int verticalBorderWidth = 0, horizontalBorderWidth = 0;
|
||||
CellStyle cellStyle = cell.getCellStyle();
|
||||
if (cellStyle.getLeftBorder() != null) {
|
||||
verticalBorderWidth += cellStyle.getLeftBorder().getWidth();
|
||||
}
|
||||
if (cellStyle.getRightBorder() != null) {
|
||||
verticalBorderWidth += cellStyle.getRightBorder().getWidth();
|
||||
}
|
||||
if (cellStyle.getTopBorder() != null) {
|
||||
horizontalBorderWidth = cellStyle.getTopBorder().getWidth();
|
||||
}
|
||||
if (cellStyle.getBottomBorder() != null) {
|
||||
horizontalBorderWidth = cellStyle.getBottomBorder().getWidth();
|
||||
}
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
if (rowSpan == 0) {
|
||||
rowSpan = 1;
|
||||
}
|
||||
if (colSpan == 0) {
|
||||
colSpan = 1;
|
||||
}
|
||||
List<ColumnDefinition> columns = report.getColumns();
|
||||
List<RowDefinition> rows = report.getRows();
|
||||
for (int i = colNumber; i < (colNumber + colSpan); i++) {
|
||||
ColumnDefinition col = columns.get(i - 1);
|
||||
width += UnitUtils.pointToPixel(col.getWidth());
|
||||
}
|
||||
for (int i = rowNumber; i < (rowNumber + rowSpan); i++) {
|
||||
RowDefinition row = rows.get(i - 1);
|
||||
height += UnitUtils.pointToPixel(row.getHeight());
|
||||
}
|
||||
width -= horizontalBorderWidth;
|
||||
height -= verticalBorderWidth;
|
||||
SlashValue content = (SlashValue) cell.getValue();
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
|
||||
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
|
||||
Font font = cellStyle.getFont();
|
||||
g.setFont(font);
|
||||
g.setStroke(new BasicStroke(1f));
|
||||
String bgColor = cellStyle.getBgcolor();
|
||||
if (bgColor == null) {
|
||||
bgColor = "255,255,255";
|
||||
}
|
||||
g.setColor(getColor(bgColor));
|
||||
g.fillRect(0, 0, width, height);
|
||||
AffineTransform transform = g.getTransform();
|
||||
int allRowHeight = 0;
|
||||
int index = 0;
|
||||
String lc = cellStyle.getForecolor();
|
||||
if (lc == null) {
|
||||
lc = "0,0,0";
|
||||
}
|
||||
Color lineColor = getColor(lc);
|
||||
String fc = cellStyle.getForecolor();
|
||||
if (fc == null) {
|
||||
fc = "0,0,0";
|
||||
}
|
||||
Color fontColor = getColor(fc);
|
||||
for (int i = rowNumber; i < (rowNumber + rowSpan); i++) {
|
||||
Slash slash = getSlash(content, index);
|
||||
if (slash == null) {
|
||||
break;
|
||||
}
|
||||
String text = slash.getText();
|
||||
if (text == null) {
|
||||
break;
|
||||
}
|
||||
RowDefinition row = rows.get(i - 1);
|
||||
int rowHeight = UnitUtils.pointToPixel(row.getHeight());
|
||||
g.setColor(fontColor);
|
||||
int x = slash.getX();
|
||||
int y = slash.getY();
|
||||
g.rotate(Math.toRadians(slash.getDegree()), x, y);
|
||||
g.drawString(text, x, y);
|
||||
g.setTransform(transform);
|
||||
g.setColor(lineColor);
|
||||
int h = allRowHeight + rowHeight;
|
||||
if (i == (rowNumber + rowSpan - 1)) {
|
||||
h = allRowHeight + (rowHeight / 3) * 2;
|
||||
}
|
||||
g.drawLine(0, 0, width, h);
|
||||
allRowHeight += rowHeight;
|
||||
index++;
|
||||
}
|
||||
Slash slash = getSlash(content, index);
|
||||
if (slash != null) {
|
||||
String text = slash.getText();
|
||||
if (text != null) {
|
||||
int x = slash.getX();
|
||||
int y = slash.getY();
|
||||
g.rotate(Math.toRadians(slash.getDegree()), x, y);
|
||||
g.setColor(fontColor);
|
||||
g.drawString(text, x, y);
|
||||
g.setTransform(transform);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
if (colSpan > 0) {
|
||||
colSpan--;
|
||||
}
|
||||
int colNumberStart = colNumber + colSpan;
|
||||
for (int i = colNumberStart; i > (colNumber - 1); i--) {
|
||||
slash = getSlash(content, index);
|
||||
if (slash == null) {
|
||||
break;
|
||||
}
|
||||
String text = slash.getText();
|
||||
if (text == null) {
|
||||
break;
|
||||
}
|
||||
int x = slash.getX();
|
||||
int y = slash.getY();
|
||||
g.rotate(Math.toRadians(slash.getDegree()), x, y);
|
||||
g.setColor(fontColor);
|
||||
g.drawString(text, x, y);
|
||||
g.setTransform(transform);
|
||||
ColumnDefinition col = columns.get(i - 1);
|
||||
int colWidth = UnitUtils.pointToPixel(col.getWidth());
|
||||
int w = width;
|
||||
if (i == colNumberStart) {
|
||||
w = width - colWidth / 3;
|
||||
}
|
||||
g.setColor(lineColor);
|
||||
g.drawLine(0, 0, w, height);
|
||||
width -= colWidth;
|
||||
index++;
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
|
||||
MemoryCacheImageOutputStream memoryImage = new MemoryCacheImageOutputStream(byteOutput);
|
||||
try {
|
||||
ImageIO.write(image, "png", memoryImage);
|
||||
imageBytes = byteOutput.toByteArray();
|
||||
String base64Data = Base64Util.encodeToString(imageBytes);
|
||||
content.setBase64Data(base64Data);
|
||||
} catch (Exception ex) {
|
||||
throw new ReportComputeException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (memoryImage != null) {
|
||||
memoryImage.close();
|
||||
}
|
||||
if (byteOutput != null) {
|
||||
byteOutput.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
g.dispose();
|
||||
String imageByteKey = buildKey(report.getReportFullName(), cell.getName());
|
||||
ResourceCache.putObject(imageByteKey, imageBytes);
|
||||
}
|
||||
|
||||
private Slash getSlash(SlashValue content, int index) {
|
||||
List<Slash> slashes = content.getSlashes();
|
||||
if (index < slashes.size()) {
|
||||
return slashes.get(index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Color getColor(String text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
String[] str = text.split(",");
|
||||
return new Color(Integer.valueOf(str[0]), Integer.valueOf(str[1]), Integer.valueOf(str[2]));
|
||||
}
|
||||
|
||||
public static String buildKey(String reportFullName, String cellName) {
|
||||
return "slash-" + reportFullName + "-" + cellName;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.provider.image;
|
||||
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月6日
|
||||
*/
|
||||
public class DefaultImageProvider implements ImageProvider, ApplicationContextAware, ServletContextAware {
|
||||
private ApplicationContext applicationContext;
|
||||
private String baseWebPath;
|
||||
|
||||
@Override
|
||||
public InputStream getImage(String path) {
|
||||
try {
|
||||
if (path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) || path.startsWith("/WEB-INF")) {
|
||||
return applicationContext.getResource(path).getInputStream();
|
||||
} else {
|
||||
path = baseWebPath + path;
|
||||
return new FileInputStream(path);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ReportComputeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean support(String path) {
|
||||
if (path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
|
||||
return true;
|
||||
} else if (baseWebPath != null && (path.startsWith("/") || path.startsWith("/WEB-INF"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.baseWebPath = servletContext.getRealPath("/");
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.provider.report.file;
|
||||
|
||||
import com.bstek.ureport.exception.ReportException;
|
||||
import com.bstek.ureport.provider.report.ReportFile;
|
||||
import com.bstek.ureport.provider.report.ReportProvider;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年2月11日
|
||||
*/
|
||||
public class FileReportProvider implements ReportProvider, ApplicationContextAware {
|
||||
private String prefix = "file:";
|
||||
private String fileStoreDir;
|
||||
private boolean disabled;
|
||||
|
||||
@Override
|
||||
public InputStream loadReport(String file) {
|
||||
if (file.startsWith(prefix)) {
|
||||
file = file.substring(prefix.length(), file.length());
|
||||
}
|
||||
String fullPath = fileStoreDir + "/" + file;
|
||||
try {
|
||||
return new FileInputStream(fullPath);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new ReportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteReport(String file) {
|
||||
if (file.startsWith(prefix)) {
|
||||
file = file.substring(prefix.length(), file.length());
|
||||
}
|
||||
String fullPath = fileStoreDir + "/" + file;
|
||||
File f = new File(fullPath);
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReportFile> getReportFiles() {
|
||||
File file = new File(fileStoreDir);
|
||||
List<ReportFile> list = new ArrayList<ReportFile>();
|
||||
for (File f : file.listFiles()) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(f.lastModified());
|
||||
list.add(new ReportFile(f.getName(), calendar.getTime()));
|
||||
}
|
||||
Collections.sort(list, new Comparator<ReportFile>() {
|
||||
@Override
|
||||
public int compare(ReportFile f1, ReportFile f2) {
|
||||
return f2.getUpdateDate().compareTo(f1.getUpdateDate());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "服务器文件系统";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveReport(String file, String content) {
|
||||
if (file.startsWith(prefix)) {
|
||||
file = file.substring(prefix.length(), file.length());
|
||||
}
|
||||
String fullPath = fileStoreDir + "/" + file;
|
||||
FileOutputStream outStream = null;
|
||||
try {
|
||||
outStream = new FileOutputStream(new File(fullPath));
|
||||
IOUtils.write(content, outStream, "utf-8");
|
||||
} catch (Exception ex) {
|
||||
throw new ReportException(ex);
|
||||
} finally {
|
||||
if (outStream != null) {
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
public void setFileStoreDir(String fileStoreDir) {
|
||||
this.fileStoreDir = fileStoreDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
File file = new File(fileStoreDir);
|
||||
if (file.exists()) {
|
||||
return;
|
||||
}
|
||||
if (applicationContext instanceof WebApplicationContext) {
|
||||
WebApplicationContext context = (WebApplicationContext) applicationContext;
|
||||
ServletContext servletContext = context.getServletContext();
|
||||
String basePath = servletContext.getRealPath("/");
|
||||
fileStoreDir = basePath + fileStoreDir;
|
||||
file = new File(fileStoreDir);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2017 Bstek
|
||||
*
|
||||
* 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 com.bstek.ureport.utils;
|
||||
|
||||
import com.bstek.ureport.exception.ReportComputeException;
|
||||
import com.bstek.ureport.image.ChartImageProcessor;
|
||||
import com.bstek.ureport.image.ImageProcessor;
|
||||
import com.bstek.ureport.image.ImageType;
|
||||
import com.bstek.ureport.image.StaticImageProcessor;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springblade.core.tool.utils.Base64Util;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jacky.gao
|
||||
* @since 2017年3月20日
|
||||
*/
|
||||
public class ImageUtils {
|
||||
private static Map<ImageType, ImageProcessor<?>> imageProcessorMap = new HashMap<ImageType, ImageProcessor<?>>();
|
||||
|
||||
static {
|
||||
StaticImageProcessor staticImageProcessor = new StaticImageProcessor();
|
||||
imageProcessorMap.put(ImageType.image, staticImageProcessor);
|
||||
ChartImageProcessor chartImageProcessor = new ChartImageProcessor();
|
||||
imageProcessorMap.put(ImageType.chart, chartImageProcessor);
|
||||
}
|
||||
|
||||
public static InputStream base64DataToInputStream(String base64Data) {
|
||||
byte[] bytes = Base64Util.decodeFromString(base64Data);
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String getImageBase64Data(ImageType type, Object data, int width, int height) {
|
||||
ImageProcessor<Object> targetProcessor = (ImageProcessor<Object>) imageProcessorMap.get(type);
|
||||
if (targetProcessor == null) {
|
||||
throw new ReportComputeException("Unknow image type :" + type);
|
||||
}
|
||||
InputStream inputStream = targetProcessor.getImage(data);
|
||||
try {
|
||||
if (width > 0 && height > 0) {
|
||||
BufferedImage inputImage = ImageIO.read(inputStream);
|
||||
BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_565_RGB);
|
||||
Graphics2D g = outputImage.createGraphics();
|
||||
g.drawImage(inputImage, 0, 0, width, height, null);
|
||||
g.dispose();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(outputImage, "png", outputStream);
|
||||
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
}
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
return Base64Util.encodeToString(bytes);
|
||||
} catch (Exception ex) {
|
||||
throw new ReportComputeException(ex);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
/**
|
||||
* UReport配置类
|
||||
|
@ -19,14 +19,14 @@ import org.springblade.core.launch.constant.AppConstant;
|
||||
import org.springblade.core.report.service.IReportFileService;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
|
||||
/**
|
||||
* UReport Boot版 API端点
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@ApiIgnore
|
||||
@Hidden
|
||||
@RestController
|
||||
@RequestMapping(AppConstant.APPLICATION_REPORT_NAME + "/report/rest")
|
||||
public class ReportBootEndpoint extends ReportEndpoint {
|
||||
|
@ -24,7 +24,7 @@ import org.springblade.core.report.service.IReportFileService;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -33,7 +33,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@ApiIgnore
|
||||
@Hidden
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/report/rest")
|
||||
|
@ -21,6 +21,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@ -33,6 +34,7 @@ import java.util.Date;
|
||||
@TableName("blade_report_file")
|
||||
public class ReportFileEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -19,12 +19,10 @@
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.2</version>
|
||||
</dependency>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
|
@ -17,8 +17,7 @@ package org.springblade.core.secure;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -27,31 +26,31 @@ import lombok.Data;
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "认证信息")
|
||||
@Schema(description = "认证信息")
|
||||
public class AuthInfo {
|
||||
@ApiModelProperty(value = "令牌")
|
||||
@Schema(description = "令牌")
|
||||
private String accessToken;
|
||||
@ApiModelProperty(value = "令牌类型")
|
||||
@Schema(description = "令牌类型")
|
||||
private String tokenType;
|
||||
@ApiModelProperty(value = "刷新令牌")
|
||||
@Schema(description = "刷新令牌")
|
||||
private String refreshToken;
|
||||
@ApiModelProperty(value = "用户ID")
|
||||
@Schema(description = "用户ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long userId;
|
||||
@ApiModelProperty(value = "租户ID")
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
@ApiModelProperty(value = "第三方系统ID")
|
||||
@Schema(description = "第三方系统ID")
|
||||
private String oauthId;
|
||||
@ApiModelProperty(value = "头像")
|
||||
@Schema(description = "头像")
|
||||
private String avatar = "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png";
|
||||
@ApiModelProperty(value = "角色名")
|
||||
@Schema(description = "角色名")
|
||||
private String authority;
|
||||
@ApiModelProperty(value = "用户名")
|
||||
@Schema(description = "用户名")
|
||||
private String userName;
|
||||
@ApiModelProperty(value = "账号名")
|
||||
@Schema(description = "账号名")
|
||||
private String account;
|
||||
@ApiModelProperty(value = "过期时间")
|
||||
@Schema(description = "过期时间")
|
||||
private long expiresIn;
|
||||
@ApiModelProperty(value = "许可证")
|
||||
@Schema(description = "许可证")
|
||||
private String license = "powered by blade";
|
||||
}
|
||||
|
@ -15,11 +15,14 @@
|
||||
*/
|
||||
package org.springblade.core.secure;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
|
||||
|
||||
/**
|
||||
* 用户实体
|
||||
*
|
||||
@ -28,47 +31,48 @@ import java.io.Serializable;
|
||||
@Data
|
||||
public class BladeUser implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 客户端id
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private Long userId;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String tenantId;
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String deptId;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String userName;
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String account;
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String roleId;
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
@ApiModelProperty(hidden = true)
|
||||
@Schema(accessMode = READ_ONLY)
|
||||
private String roleName;
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -28,8 +28,8 @@ import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -26,8 +26,8 @@ import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springblade.core.secure.provider;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -29,23 +29,23 @@ public class ClientDetails implements IClientDetails {
|
||||
/**
|
||||
* 客户端id
|
||||
*/
|
||||
@ApiModelProperty(value = "客户端id")
|
||||
@Schema(description = "客户端id")
|
||||
private String clientId;
|
||||
/**
|
||||
* 客户端密钥
|
||||
*/
|
||||
@ApiModelProperty(value = "客户端密钥")
|
||||
@Schema(description = "客户端密钥")
|
||||
private String clientSecret;
|
||||
|
||||
/**
|
||||
* 令牌过期秒数
|
||||
*/
|
||||
@ApiModelProperty(value = "令牌过期秒数")
|
||||
@Schema(description = "令牌过期秒数")
|
||||
private Integer accessTokenValidity;
|
||||
/**
|
||||
* 刷新令牌过期秒数
|
||||
*/
|
||||
@ApiModelProperty(value = "刷新令牌过期秒数")
|
||||
@Schema(description = "刷新令牌过期秒数")
|
||||
private Integer refreshTokenValidity;
|
||||
|
||||
}
|
||||
|
@ -37,10 +37,10 @@ public class SecureRegistry {
|
||||
|
||||
public SecureRegistry() {
|
||||
this.defaultExcludePatterns.add("/actuator/health/**");
|
||||
this.defaultExcludePatterns.add("/v2/api-docs/**");
|
||||
this.defaultExcludePatterns.add("/v3/api-docs/**");
|
||||
this.defaultExcludePatterns.add("/swagger-ui/**");
|
||||
this.defaultExcludePatterns.add("/auth/**");
|
||||
this.defaultExcludePatterns.add("/token/**");
|
||||
this.defaultExcludePatterns.add("/log/**");
|
||||
this.defaultExcludePatterns.add("/user/user-info");
|
||||
this.defaultExcludePatterns.add("/user/user-info-by-id");
|
||||
this.defaultExcludePatterns.add("/menu/auth-routes");
|
||||
|
@ -32,7 +32,7 @@ import org.springblade.core.tool.constant.RoleConstant;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.security.Key;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.15.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
@ -60,7 +60,10 @@ public class SocialUtil {
|
||||
authRequest = new AuthWeChatOpenRequest(authConfig);
|
||||
break;
|
||||
case WECHAT_ENTERPRISE:
|
||||
authRequest = new AuthWeChatEnterpriseRequest(authConfig);
|
||||
authRequest = new AuthWeChatEnterpriseQrcodeRequest(authConfig);
|
||||
break;
|
||||
case WECHAT_ENTERPRISE_WEB:
|
||||
authRequest = new AuthWeChatEnterpriseWebRequest(authConfig);
|
||||
break;
|
||||
case WECHAT_MP:
|
||||
authRequest = new AuthWeChatMpRequest(authConfig);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user