提交 a8839722 authored 作者: 陈世营's avatar 陈世营

loit-file

上级 14c96b46
......@@ -24,7 +24,11 @@ public class LoitStrtupRunner implements ApplicationRunner {
public void run(ApplicationArguments args) throws Exception {
//此处因为在日志拦截器每次获取服务Ip,netAddress.getLocalHost()为同步代码会导致性能超低,将此代码移动到服务启动加载,设置全局变量以供使用
InetAddress address = InetAddress.getLocalHost();
Global.HOSTIP = address.getHostAddress();
logger.info("获取本服务ip地址为:{}",Global.HOSTIP);
String hostAddress = address.getHostAddress();
System.out.println(hostAddress);
Global.HOSTIP = hostAddress;
logger.info("获取本服务ip地址为:{}", Global.HOSTIP);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>loit-service</artifactId>
<groupId>com.loit</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-file</artifactId>
<name>loit-file</name>
<version>1.0.0</version>
<url>http://maven.apache.org</url>
<dependencies>
<!-- activemq内置消息中间件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>com.loit</groupId>
<artifactId>loit-core-boot</artifactId>
<version>${loit-core-boot}</version>
</dependency>
<!-- nacos 注册中心 -->
<dependency>
<groupId>com.timeloit.cloud</groupId>
<artifactId>spring-cloud-starter-timeloit-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.timeloit.cloud</groupId>
<artifactId>spring-cloud-starter-timeloit-nacos-config</artifactId>
</dependency>
<!-- tomcat 的支持.-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- 集成fastdfs -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.0.12</version>
</dependency>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
</dependencies>
<build>
<finalName>loit-file</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.loit.FileServerApplication</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-extdirs</arg>
<arg>${project.basedir}/src/main/resources/lib</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<!-- 打包时将jsp文件拷贝到META-INF目录下 -->
<resource>
<directory>${project.basedir}/src/main/resources/lib</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/**</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
\ No newline at end of file
package com.loit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jmx.support.RegistrationPolicy;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.github.tobato.fastdfs.FdfsClientConfig;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
@ServletComponentScan
@EnableFeignClients
@RestController
@EnableSwagger2
@EnableJms
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FileServerApplication extends SpringBootServletInitializer{
@Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(FileServerApplication.class);
}
public static void main(String[] args) {
long startTime=System.currentTimeMillis();
SpringApplication.run(FileServerApplication.class, args);
long endTime=System.currentTimeMillis();
float excTime=(float)(endTime-startTime)/1000;
System.out.println("############--- loit-file项目启动成功,执行用时:"+excTime+"秒 ---############");
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
package com.loit.common.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
*
* @ClassName: Test.java
* @Description: 该类的功能描述
*
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 下午2:24:30
*
* Modification History:
* Date Author Version Description
*---------------------------------------------------------*
* 2019年4月24日 gaodengyun v1.0.0 修改原因
*/
@Component
public class FastDFSConfigInfo {
@Value("${fastdfs.file_server_prefix}")
private String fileServerPrefix;
public String getFileServerPrefix() {
return fileServerPrefix;
}
public void setFileServerPrefix(String fileServerPrefix) {
this.fileServerPrefix = fileServerPrefix;
}
}
package com.loit.common.config;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 自定义Feign的隔离策略;
* 在转发Feign的请求头的时候,如果开启了Hystrix,Hystrix的默认隔离策略是Thread(线程隔离策略)
* ,因此转发拦截器内是无法获取到请求的请求头信息的
* ,可以修改默认隔离策略为信号量模式:hystrix.command.default.execution.isolation.strategy=SEMAPHORE
* ,这样的话转发线程和请求线程实际上是一个线程,这并不是最好的解决方法,信号量模式也不是官方最为推荐的隔离策略;
* 另一个解决方法就是自定义Hystrix的隔离策略,思路是将现有的并发策略作为新并发策略的成员变量
* ,在新并发策略中,返回现有并发策略的线程池、Queue;将策略加到Spring容器即可;
*
* @author mozping
* @version 1.0
* @date 2018/7/5 9:08
* @see FeignHystrixConcurrencyStrategyIntellif
* @since JDK1.8
*/
@Component
public class FeignHystrixConcurrencyStrategyIntellif extends HystrixConcurrencyStrategy {
private static final Logger log = LoggerFactory.getLogger(FeignHystrixConcurrencyStrategyIntellif.class);
private HystrixConcurrencyStrategy delegate;
public FeignHystrixConcurrencyStrategyIntellif() {
try {
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (this.delegate instanceof FeignHystrixConcurrencyStrategyIntellif) {
// Welcome to singleton hell...
return;
}
HystrixCommandExecutionHook commandExecutionHook =
HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy =
HystrixPlugins.getInstance().getPropertiesStrategy();
this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
} catch (Exception e) {
log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
}
}
private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) {
if (log.isDebugEnabled()) {
log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
+ this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
+ metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
}
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return new WrappedCallable<>(callable, requestAttributes);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,
HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
unit, workQueue);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixThreadPoolProperties threadPoolProperties) {
return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return this.delegate.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
return this.delegate.getRequestVariable(rv);
}
static class WrappedCallable<T> implements Callable<T> {
private final Callable<T> target;
private final RequestAttributes requestAttributes;
public WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
this.target = target;
this.requestAttributes = requestAttributes;
}
@Override
public T call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return target.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}
\ No newline at end of file
package com.loit.common.config;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.DefaultResourceLoader;
import com.google.common.collect.Maps;
/**
* 全局配置类
* @author loit
* @version 2014-06-25
*/
public class Global {
/**
* 当前对象实例
*/
private static Global global = new Global();
/**
* 保存全局属性值
*/
private static Map<String, String> map = Maps.newHashMap();
/**
* 属性文件加载对象
*/
private static PropertiesLoader loader = new PropertiesLoader("/config/custom.properties");
/**
* 显示/隐藏
*/
public static final String SHOW = "1";
public static final String HIDE = "0";
/**
* 是/否
*/
public static final String YES = "1";
public static final String NO = "0";
/**
* 对/错
*/
public static final String TRUE = "true";
public static final String FALSE = "false";
/**
* 上传文件基础虚拟路径
*/
public static final String USERFILES_BASE_URL = "/userfiles/";
public static String HOSTIP;
/**
* 获取当前对象实例
*/
public static Global getInstance() {
return global;
}
/**
* 获取配置
* @see ${fns:getConfig('adminPath')}
*/
public static String getConfig(String key) {
String value = map.get(key);
if (value == null){
value = loader.getProperty(key);
map.put(key, value != null ? value : StringUtils.EMPTY);
}
return value;
}
/**
* 获取管理端根路径
*/
public static String getAdminPath() {
return getConfig("adminPath");
}
/**
* 获取前端根路径
*/
public static String getFrontPath() {
return getConfig("frontPath");
}
/**
* 获取URL后缀
*/
public static String getUrlSuffix() {
return getConfig("urlSuffix");
}
/**
* 是否是演示模式,演示模式下不能修改用户、角色、密码、菜单、授权
*/
public static Boolean isDemoMode() {
String dm = getConfig("demoMode");
return "true".equals(dm) || "1".equals(dm);
}
/**
* 在修改系统用户和角色时是否同步到Activiti
*/
public static Boolean isSynActivitiIndetity() {
String dm = getConfig("activiti.isSynActivitiIndetity");
return "true".equals(dm) || "1".equals(dm);
}
/**
* 页面获取常量
* @see ${fns:getConst('YES')}
*/
public static Object getConst(String field) {
try {
return Global.class.getField(field).get(null);
} catch (Exception e) {
// 异常代表无配置,这里什么也不做
}
return null;
}
/**
* 获取上传文件的根目录
* @return
*/
public static String getUserfilesBaseDir() {
String dir = getConfig("userfiles.basedir");
if (StringUtils.isBlank(dir)){
try {
// dir = ServletContextFactory.getServletContext().getRealPath("/");
} catch (Exception e) {
return "";
}
}
if(!dir.endsWith("/")) {
dir += "/";
}
return dir;
}
/**
* 获取工程路径
* @return
*/
public static String getProjectPath(){
// 如果配置了工程路径,则直接返回,否则自动获取。
String projectPath = Global.getConfig("projectPath");
if (StringUtils.isNotBlank(projectPath)){
return projectPath;
}
try {
File file = new DefaultResourceLoader().getResource("").getFile();
if (file != null){
while(true){
File f = new File(file.getPath() + File.separator + "src" + File.separator + "main");
if (f == null || f.exists()){
break;
}
if (file.getParentFile() != null){
file = file.getParentFile();
}else{
break;
}
}
projectPath = file.toString();
}
} catch (IOException e) {
e.printStackTrace();
}
return projectPath;
}
}
/**
* Copyright (c) 2005-2011 springside.org.cn
*
* $Id: PropertiesLoader.java 1690 2012-02-22 13:42:00Z calvinxiu $
*/
package com.loit.common.config;
import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
/**
* Properties文件载入工具类. 可载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的值,但以System的Property优先.
* @author calvin
* @version 2013-05-15
*/
public class PropertiesLoader {
private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class);
private static ResourceLoader resourceLoader = new DefaultResourceLoader();
private final Properties properties;
public PropertiesLoader(String... resourcesPaths) {
properties = loadProperties(resourcesPaths);
}
public Properties getProperties() {
return properties;
}
/**
* 取出Property,但以System的Property优先,取不到返回空字符串.
*/
private String getValue(String key) {
String systemProperty = System.getProperty(key);
if (systemProperty != null) {
return systemProperty;
}
if (properties.containsKey(key)) {
return properties.getProperty(key);
}
return "";
}
/**
* 取出String类型的Property,但以System的Property优先,如果都为Null则抛出异常.
*/
public String getProperty(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return value;
}
/**
* 取出String类型的Property,但以System的Property优先.如果都为Null则返回Default值.
*/
public String getProperty(String key, String defaultValue) {
String value = getValue(key);
return value != null ? value : defaultValue;
}
/**
* 取出Integer类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常.
*/
public Integer getInteger(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Integer.valueOf(value);
}
/**
* 取出Integer类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常
*/
public Integer getInteger(String key, Integer defaultValue) {
String value = getValue(key);
return value != null ? Integer.valueOf(value) : defaultValue;
}
/**
* 取出Double类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常.
*/
public Double getDouble(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Double.valueOf(value);
}
/**
* 取出Double类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常
*/
public Double getDouble(String key, Integer defaultValue) {
String value = getValue(key);
return value != null ? Double.valueOf(value) : defaultValue;
}
/**
* 取出Boolean类型的Property,但以System的Property优先.如果都为Null抛出异常,如果内容不是true/false则返回false.
*/
public Boolean getBoolean(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Boolean.valueOf(value);
}
/**
* 取出Boolean类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容不为true/false则返回false.
*/
public Boolean getBoolean(String key, boolean defaultValue) {
String value = getValue(key);
return value != null ? Boolean.valueOf(value) : defaultValue;
}
/**
* 载入多个文件, 文件路径使用Spring Resource格式.
*/
private Properties loadProperties(String... resourcesPaths) {
Properties props = new Properties();
for (String location : resourcesPaths) {
// logger.debug("Loading properties file from:" + location);
InputStream is = null;
try {
Resource resource = resourceLoader.getResource(location);
is = resource.getInputStream();
props.load(is);
} catch (IOException ex) {
logger.info("Could not load properties from path:" + location + ", " + ex.getMessage());
} finally {
IOUtils.closeQuietly(is);
}
}
return props;
}
}
package com.loit.common.config;
import java.util.Locale;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
*
* @ClassName: SpringContextUtil
* @Description: SpringContext相关
* @author gaodengyun
* @date 2019年5月11日 上午11:59:02
*
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
@SuppressWarnings("static-access")
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
// 传入线程中
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
return (T) context.getBean(beanName);
}
// 国际化使用
public static String getMessage(String key) {
return context.getMessage(key, null, Locale.getDefault());
}
/// 获取当前环境
public static String getActiveProfile() {
return context.getEnvironment().getActiveProfiles()[0];
}
}
package com.loit.common.config;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger配置
* @author wbh
* @date 2018年12月15日
*/
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(Swagger2
.basePackage("com.loit.web")).paths(PathSelectors.any()).build();
}
/**
* Predicate that matches RequestHandler with given base package name for the class of the handler method.
* This predicate includes all request handlers matching the provided basePackage
*
* @param basePackage - base package of the classes
* @return this
*/
public static Predicate<RequestHandler> basePackage(final String basePackage) {
return new Predicate<RequestHandler>() {
@Override
public boolean apply(RequestHandler input) {
return declaringClass(input).transform(handlerPackage(basePackage)).or(true);
}
};
}
/**
* 处理包路径配置规则,支持多路径扫描匹配以逗号隔开
*
* @param basePackage 扫描包路径
* @return Function
*/
private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
return new Function<Class<?>, Boolean>() {
@Override
public Boolean apply(Class<?> input) {
for (String strPackage : basePackage.split(",")) {
boolean isMatch = input.getPackage().getName().startsWith(strPackage);
if (isMatch) {
return true;
}
}
return false;
}
};
}
/**
* @param input RequestHandler
* @return Optional
*/
@SuppressWarnings("deprecation")
private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
return Optional.fromNullable(input.declaringClass());
}
private ApiInfo apiInfo() {
InetAddress address;
String hostAddress=null;
try {
address = InetAddress.getLocalHost();
hostAddress = address.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}//获取的是本地的IP地址
String projectName = Global.getConfig("productName");
return new ApiInfoBuilder()
.title(projectName+"api文档")
.description("v1.0 add by gaoyanyun (2514917157@qq.com) \n"
+ "v1.1 update by wangbh (wbh1213@qq.com)")
.termsOfServiceUrl("http://"+hostAddress+":7002/api-demo/swagger-ui.html")
.version("1.0")
.build();
}
}
package com.loit.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截器配置
*
* @author wbh
* @date 2018年12月3日
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//和页面有关的静态目录都放在项目的static目录下
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
//上传的图片在D盘下的img目录下,访问路径如:http://localhost:7007/image/d3cf0281-bb7f-40e0-ab77-406db95ccf2c.jpg
//其中image表示访问的前缀。"file:E:/img/"是文件真实的存储路径
registry.addResourceHandler("/image/**");
}
/**
* 设置SpringBoot默认返回体Content-Type
*
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
}
}
package com.loit.common.json;
import java.io.Serializable;
import java.util.LinkedHashMap;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* $.ajax后需要接受的JSON
*
* @author
*
*/
public class AjaxJson implements Serializable{
public static final String CODE_COMMON_FAIL = LoitStatusCode.FAIL.statusCode;
/**
* @author wbh
* @date 2018年12月11日
*/
private static final long serialVersionUID = -7790919285662399570L;
private boolean success = true;// 是否成功
private String code = LoitStatusCode.SUCESS.statusCode;//返回码 100-成功,101失败,其他返回码参见LoitStatusCode
private String msg = "操作成功";// 提示信息
private LinkedHashMap<String, Object> body = new LinkedHashMap<String, Object>();//封装json的map
private String errorCode;
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public LinkedHashMap<String, Object> getBody() {
return body;
}
public void setBody(LinkedHashMap<String, Object> body) {
this.body = body;
}
public void put(String key, Object value){//向json中添加属性,在js中访问,请调用data.map.key
body.put(key, value);
}
public void remove(String key){
body.remove(key);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {//向json中添加属性,在js中访问,请调用data.msg
this.msg = msg;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@JsonIgnore//返回对象时忽略此属性
public String getJsonStr() {//返回json字符串数组,将访问msg和key的方式统一化,都使用data.key的方式直接访问。
String json = JsonMapper.getInstance().toJson(this);
return json;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return "AjaxJson [success=" + success + ", code=" + code + ", msg=" + msg + "]";
}
/**
* 返回普通异常信息。code=101
* @author wbh
* @date:2018年12月16日
* @param info
* @return
*/
public static AjaxJson returnExceptionInfo(String info) {
AjaxJson json = new AjaxJson();
json.setSuccess(false);
json.setCode(CODE_COMMON_FAIL);
json.setMsg(info);
return json;
}
/**
* 返回普通异常信息。code=101
* @author wbh
* @date:2018年12月16日
* @param info
* @return
*/
public static AjaxJson returnExceptionInfo(String info, AjaxJson json) {
json.setSuccess(false);
json.setCode(CODE_COMMON_FAIL);
json.setMsg(info);
return json;
}
/**
* 返回指定异常信息。
* @author wbh
* @date:2019年10月31日
* @param code 状态码
* @param info 返回信息
* @return
*/
public static AjaxJson returnExceptionInfo(LoitStatusCode info) {
AjaxJson json = new AjaxJson();
json.setSuccess(false);
json.setCode(info.statusCode);
json.setMsg(info.statusDesc);
return json;
}
/**
* 返回指定异常信息。
* @author wbh
* @date:2019年10月31日
* @param code 状态码
* @param info 返回信息
* @return
*/
public static AjaxJson returnExceptionInfo(LoitStatusCode info, AjaxJson json) {
json.setSuccess(false);
json.setCode(info.statusCode);
json.setMsg(info.statusDesc);
return json;
}
}
package com.loit.common.json;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/**
* 简单封装Jackson,实现JSON String<->Java Object的Mapper.
* 封装不同的输出风格, 使用不同的builder函数创建实例.
* @author loit
* @version 2013-11-15
*/
@SuppressWarnings("deprecation")
public class JsonMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(JsonMapper.class);
private static JsonMapper mapper;
public JsonMapper() {
//this(Include.NON_EMPTY);
}
public JsonMapper(Include include) {
// 设置输出时包含属性的风格
if (include != null) {
this.setSerializationInclusion(include);
}
// 允许单引号、允许不带引号的字段名称
this.enableSimple();
// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 空值处理为空串
this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString("");
}
});
// 进行HTML解码。
this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>(){
@Override
public void serialize(String value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
}
}));
// 设置时区
this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
}
/**
* 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用.
*/
public static JsonMapper getInstance() {
if (mapper == null){
mapper = new JsonMapper().enableSimple();
}
return mapper;
}
/**
* 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式,建议在内部接口中使用。
*/
public static JsonMapper nonDefaultMapper() {
if (mapper == null){
mapper = new JsonMapper(Include.NON_DEFAULT);
}
return mapper;
}
/**
* Object可以是POJO,也可以是Collection或数组。
* 如果对象为Null, 返回"null".
* 如果集合为空集合, 返回"[]".
*/
public String toJson(Object object) {
try {
return this.writeValueAsString(object);
} catch (IOException e) {
logger.warn("write to json string error:" + object, e);
return null;
}
}
/**
* 反序列化POJO或简单Collection如List<String>.
*
* 如果JSON字符串为Null或"null"字符串, 返回Null.
* 如果JSON字符串为"[]", 返回空集合.
*
* 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
* @see #fromJson(String, JavaType)
*/
public <T> T fromJson(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return this.readValue(jsonString, clazz);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 反序列化复杂Collection如List<Bean>, 先使用函數createCollectionType构造类型,然后调用本函数.
* @see #createCollectionType(Class, Class...)
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(String jsonString, JavaType javaType) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return (T) this.readValue(jsonString, javaType);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 構造泛型的Collection Type如:
* ArrayList<MyBean>, 则调用constructCollectionType(ArrayList.class,MyBean.class)
* HashMap<String,MyBean>, 则调用(HashMap.class,String.class, MyBean.class)
*/
public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
/**
* 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性.
*/
@SuppressWarnings("unchecked")
public <T> T update(String jsonString, T object) {
try {
return (T) this.readerForUpdating(object).readValue(jsonString);
} catch (JsonProcessingException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
} catch (IOException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
}
return null;
}
/**
* 輸出JSONP格式數據.
*/
public String toJsonP(String functionName, Object object) {
return toJson(new JSONPObject(functionName, object));
}
/**
* 設定是否使用Enum的toString函數來讀寫Enum,
* 為False時時使用Enum的name()函數來讀寫Enum, 默認為False.
* 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用.
*/
public JsonMapper enableEnumUseToString() {
this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return this;
}
/**
* 支持使用Jaxb的Annotation,使得POJO上的annotation不用与Jackson耦合。
* 默认会先查找jaxb的annotation,如果找不到再找jackson的。
*/
public JsonMapper enableJaxbAnnotation() {
JaxbAnnotationModule module = new JaxbAnnotationModule();
this.registerModule(module);
return this;
}
/**
* 允许单引号
* 允许不带引号的字段名称
*/
public JsonMapper enableSimple() {
this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
return this;
}
/**
* 取出Mapper做进一步的设置或使用其他序列化API.
*/
public ObjectMapper getMapper() {
return this;
}
/**
* 对象转换为JSON字符串
* @param object
* @return
*/
public static String toJsonString(Object object){
return JsonMapper.getInstance().toJson(object);
}
/**
* JSON字符串转换为对象
* @param jsonString
* @param clazz
* @return
*/
public static Object fromJsonString(String jsonString, Class<?> clazz){
return JsonMapper.getInstance().fromJson(jsonString, clazz);
}
/**
* 测试
*/
public static void main(String[] args) {
List<Map<String, Object>> list = Lists.newArrayList();
Map<String, Object> map = Maps.newHashMap();
map.put("id", 1);
map.put("pId", -1);
map.put("name", "根节点");
list.add(map);
map = Maps.newHashMap();
map.put("id", 2);
map.put("pId", 1);
map.put("name", "你好");
map.put("open", true);
list.add(map);
// String json = JsonMapper.getInstance().toJson(list);
}
}
package com.loit.common.json;
/**
* @ClassName LoitStatusCode
* @Description: 系统状态码 编码:3位状态码中,第一位代表一个应用
* @Author gzx
* @Date 2019-10-17
* @Version V1.0
**/
public enum LoitStatusCode {
SUCESS("100","成功"),
FAIL("101","失败"),
UNKNOWN_EXCEPTION("102","未知异常,请联系管理员"),
USER_UNREGISTERED("103","用户未注册"),
USER_FORBID("104","用户被禁止登录"),
USER_PASSWORD_FAIL("105","登录失败"),
USER_TOKEN_ERRO("106","TOKEN验证错误"),
USER_TOKEN_INVALID("107","TOKEN验证失效"),
USER_ILLEGAL_AUTH("109","非法授权"),
USER_SESSION_ERRO("110","session验证错误"),
USER_SESSION_INVALID("111","session验证失效"),
/**
* 单点登录相关 TODO DEMN cas statuscode 需要修改
*/
CAS_URI_RESOLVE_ERROR("101", "CAS AccessToken换取用户信息的回调URI解析错误"),
CAS_REDIRECT_URL_NOT_USERNAME_ERROR("101", "CAS AccessToken换取用户信息的回调URI没有用户登录名称"),
CAS_USER_AUTH_FAIL("101","用户认证失败, 用户未登录或登录过期"),
CAS_USER_TOKEN_NOT_FOUND("101", "AccessToken 头部参数没找到"),
CAS_AUTHENTICATION_FAIL("101", "无权限访问该资源"),
CAS_AUTHENTICATION_NOT_APPID_FAIL("101", "鉴权失败,缓存中没有当前用户操作的应用id"),
CAS_NOT_IN_APPOINT_AREA("101", "不在指定区域,无法登录"),
CAS_LOGIN_FAIL("101", "登录失败"),
/**
* 密码策略相关
*/
POLICY_PASSWORD_SUCCESS("101", "密码格式正确"),
POLICY_PASSWORD_LENGTH_ERR("101", "密码长度错误"),
POLICY_PASSWORD_MIXLEVEL_ERR("101", "密码格式错误"),
/**
* 服务相关
*/
SERVICE_NOT_ONLINE_FOR_LOIT_PORTAL_ERROR("190", "loit-portal服务未在线"),
APP_ORG_ASSIGN("114","应用组织权限已分配"),
PRIMARY_KEY_ISNULL("115","主键为空"),
APP_IS_EXIST("116", "保存失败,应用已存在"),
SAVE_EXCEPTION("117", "保存异常,请联系管理员"),
UPDATE_EXCEPTION("118", "修改异常,请联系管理员"),
DELETE_EXCEPTION("119", "删除异常,请联系管理员"),
DISTRIBUTE_RESOURCES_EXCEPTION("120", "分配资源异常,请联系管理员"),
APP_ID_ISNULL("121", "应用id为空"),
CONTEXT_IS_EXIST("122", "保存失败,上下文配置已存在"),
RESOURCETYPE_IS_EXIST("123", "保存失败,资源类别已存在"),
MENU_IS_EXIST("124", "保存失败,菜单已存在"),
DICT_IS_EXIST("125", "保存失败,字典已存在"),
DICTDATA_IS_EXIST("126", "保存失败,字典项已存在"),
MENULAYOUT_IS_EXIST("127", "保存失败,菜单布局已存在"),
SKIN_IS_EXIST("128", "保存失败,皮肤设置已存在"),
FILE_PATH_ISNULL("140", "文件路径为空"),
FILE_ISNULL("141", "文件为空"),
FILE_UPLOAD_FAILED("142", "文件上传失败"),
FILE_NOT_EXIST("143", "文件不存在"),
FILE_DOWNLOAD_FAILED("144", "文件下载失败"),
FILE_DELETE_FAILED("145", "删除文件失败"),
FILE_SERVER_CONNECTION_FAILED("146", "文件服务器连接失败"),
FILE_OUT_SIZE("147", "文件超过大小"),
FILE_TYPE_ERROR_IMAGE("148", "图片类型错误"),
FILE_TYPE_ERROR_DOC("149", "文档类型错误"),
FILE_TYPE_ERROR_VIDEO("140", "音频类型错误"),
FILE_TYPE_ERROR_COMPRESS("141", "压缩文件类型错误"),
FILE_TYPE_ERROR_ALLOW("142", "不是允许的文件类型"),
REDIS_LINK_FAIL("145","redis连接异常"),
GRP_ADD_ORG_FAIL("146","该组织已添加"),
GRP_ADD_PERSON_FAIL("147","该用户已添加"),
GRP_NOT_EXIST("148","用户组不存在")
;
/**
* 状态编码号
*/
public String statusCode;
/**
* 状态描述
*/
public String statusDesc;
/**
* 构造函数
* @param statusCode
* @param statusDesc
*/
LoitStatusCode(String statusCode,String statusDesc){
this.statusCode = statusCode;
this.statusDesc = statusDesc;
}
}
package com.loit.common.tool;
import java.io.Serializable;
/**
* 上传后返回信息数据
*/
public class ApiResult<T> implements Serializable{
/**
*
*/
private static final long serialVersionUID = -1653378788978311892L;
private String code;
private String msg;
private T data;
public ApiResult() {
this.code = Constants.kCode_Fail;
this.msg = "";
}
public ApiResult(String code, String msg) {
this.code = code;
this.msg = msg;
}
public ApiResult(String code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
// 默认方法
public static ApiResult success(){
return successMsg("请求成功");
}
public static ApiResult successMsg(String msg){
ApiResult apiBean = new ApiResult(Constants.kCode_Success, msg, null);
return apiBean;
}
public static ApiResult success(Object data, String msg){
ApiResult apiBean = new ApiResult(Constants.kCode_Success, msg, data);
return apiBean;
}
public static ApiResult success(Object data){
ApiResult apiBean = new ApiResult(Constants.kCode_Success, "", data);
return apiBean;
}
public static ApiResult fail(){
return fail("请求失败");
}
public static ApiResult fail(String msg){
ApiResult apiBean = new ApiResult(Constants.kCode_Fail, msg);
return apiBean;
}
public static ApiResult fail(String code, String msg){
ApiResult apiBean = new ApiResult(code, msg);
return apiBean;
}
public static ApiResult sessionError(){
ApiResult apiBean = new ApiResult(Constants.kCode_SessionError, "登陆超时");
return apiBean;
}
}
package com.loit.common.tool;
/**
* 上传前文件检测
* @author fangshiquan
*/
public class CheckFileResult {
private String fileMd5;
//0:锁未占用,1:锁占用
private Integer lock;
//文件分块数量
private Integer chunkNum;
//每块文件大小
private Integer chunkSize;
//当前已传输到第几块
private Integer chunkCurr;
//当前文件总大小
private Long totalSize;
//访问路径
private String viewPath;
public String getViewPath() {
return viewPath;
}
public void setViewPath(String viewPath) {
this.viewPath = viewPath;
}
public String getFileMd5() {
return fileMd5;
}
public void setFileMd5(String fileMd5) {
this.fileMd5 = fileMd5;
}
public Integer getLock() {
return lock;
}
public void setLock(Integer lock) {
this.lock = lock;
}
public Integer getChunkNum() {
return chunkNum;
}
public void setChunkNum(Integer chunkNum) {
this.chunkNum = chunkNum;
}
public Integer getChunkSize() {
return chunkSize;
}
public void setChunkSize(Integer chunkSize) {
this.chunkSize = chunkSize;
}
public Integer getChunkCurr() {
return chunkCurr;
}
public void setChunkCurr(Integer chunkCurr) {
this.chunkCurr = chunkCurr;
}
public Long getTotalSize() {
return totalSize;
}
public void setTotalSize(Long totalSize) {
this.totalSize = totalSize;
}
}
package com.loit.common.tool;
/**
* 通用常量配置
*/
public class Constants {
// 全局配置
public final static int False = 0;
public final static int True = 1;
public final static String kCode_Success = "0"; // 成功
public final static String kCode_Fail = "1"; // 失败
public final static String kCode_SessionError = "1000"; // 登陆超时
}
package com.loit.common.tool;
/**
* 文件基础信息
* @author fangshiquan
*
*/
public class FileResult {
//文件名
private String url;
//文件md5
private String md5;
//文件名称
private String name;
//文件大小
private Long lenght;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getLenght() {
return lenght;
}
public void setLenght(Long lenght) {
this.lenght = lenght;
}
}
package com.loit.common.tool;
import java.io.InputStream;
import java.util.Properties;
import com.loit.common.config.SpringContextUtil;
/**
* 读取配置信息
* @author fangshiquan
*
*/
public class ReadProper {
public static String getResourceValue(String key) {
try {
String activeMode = SpringContextUtil.getActiveProfile();
String fileNamePath="";
switch (activeMode) {
case "proc":
fileNamePath="/application-proc.properties";
break;
case "dev":
fileNamePath="/application-dev.properties";
break;
default:
fileNamePath="/application-test.properties";
}
InputStream input = ReadProper.class.getResourceAsStream(fileNamePath);
Properties p = new Properties();
p.load(input);
input.close();
if (!p.containsKey(key)) {
return null;
}
return p.getProperty(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//读取国际化
public static String getI18n(String key) {
try {
InputStream input = ReadProper.class
.getResourceAsStream("/i18n_zh_CN.properties");
Properties p = new Properties();
p.load(input);
input.close();
if (!p.containsKey(key)) {
return null;
}
return p.getProperty(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.loit.common.tool;
import java.util.HashMap;
import java.util.Map;
/**
* 模拟数据库
* @author fangshiquan
*
*/
public class Table {
private Table(){};
//用户表
public static Map<String,String> user=new HashMap<String,String>();
static {
//添加用户账号密码
user.put("admin","123456");
user.put("zhang","123456");
user.put("wang","123456");
}
}
package com.loit.common.tool;
/**
* 上传常量配置
* @author fangshiquan
*
*/
public class UpLoadConstant {
private UpLoadConstant() {
}
private final static String uploading="Uploading:";
private final static String lock=uploading+"lock:";
private final static String file=uploading+"file:";
//当前所有锁(用在不同用户的上传前或重传前对整个文件的锁)
public final static String currLocks=lock+"currLocks:";
//当前锁的拥有者
public final static String lockOwner=lock+"lockOwner:";
//当前文件传输到第几块
public final static String chunkCurr=file+"chunkCurr:";
//当前文件上传到fastdfs路径
public final static String fastDfsPath=file+"fastDfsPath:";
//默认分组
public final static String DEFAULT_GROUP = "group1";
//全部上传成功已完成
public final static String completedList=uploading+"completedList";
//文件块锁(解决同一个用户正在上传时并发解决,比如后端正在上传一个大文件块,前端页面点击删除按钮,
// 继续添加删除的文件,这时候要加锁来阻止其上传,否则会出现丢块问题,
// 因为fastdfs上传不像迅雷下载一样,下载时会创建一个完整的文件,如果上传第一块时,服务器能快速创建一个大文件0填充,那么这样可以支持并发乱序来下载文件块,上传速度会成倍提升,要实现乱序下载文件块,估计就得研究fastdfs源码了)
public final static String chunkLock=lock+"chunkLock:";
}
package com.loit.modules.fastdfs;
/**
*
*
* @ClassName: ErrorCode.java
* @Description: FastDFSErrorCode
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 上午9:00:25
*/
public enum ErrorCode {
FILE_PATH_ISNULL("error.fastdfs.file_path_isnull", "文件路径为空"),
FILE_ISNULL("error.fastdfs.file_isnull", "文件为空"),
FILE_UPLOAD_FAILED("error.fastdfs.file_upload_failed", "文件上传失败"),
FILE_NOT_EXIST("error.fastdfs.file_not_exist", "文件不存在"),
FILE_DOWNLOAD_FAILED("error.fastdfs.file_download_failed", "文件下载失败"),
FILE_DELETE_FAILED("error.fastdfs.file_delete_failed", "删除文件失败"),
FILE_SERVER_CONNECTION_FAILED("error.fastdfs.file_server_connection_failed", "文件服务器连接失败"),
FILE_OUT_SIZE("error.fastdfs.file_server_connection_failed", "文件超过大小"),
FILE_TYPE_ERROR_IMAGE("error.file.type.image", "图片类型错误"),
FILE_TYPE_ERROR_DOC("error.file.type.doc", "文档类型错误"),
FILE_TYPE_ERROR_VIDEO("error.file.type.video", "音频类型错误"),
FILE_TYPE_ERROR_COMPRESS("error.file.type.compress", "压缩文件类型错误"),
FILE_TYPE_ERROR_ALLOW("error.file.type.allow", "不是允许的文件类型");
public String CODE;
public String MESSAGE;
ErrorCode(String CODE, String MESSAGE){
this.CODE = CODE;
this.MESSAGE = MESSAGE;
}
}
package com.loit.modules.fastdfs;
/**
* FastDFS 上传下载时可能出现的一些异常信息
* <p>
*
* @author jiangzhou.bo@hand-china.com
* @version 1.0
* @name FastDFSException
* @date 2017-10-13 15:12
*/
public class FastDFSException extends Exception {
private static final long serialVersionUID = -7540424984113469133L;
/**
* 错误码
*/
private String code;
/**
* 错误消息
*/
private String message;
public FastDFSException(){}
public FastDFSException(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.loit.modules.fastdfs;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @ClassName: FileCheck.java
* @Description: 文件检查工具类
*
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 上午9:02:20
*
*/
public class FileCheck {
/**
* 图片类型
*/
private static final List<String> TYPE_IMAGE = new ArrayList<>();
/**
* 文档类型
*/
private static final List<String> TYPE_DOC = new ArrayList<>();
/**
* 音频类型
*/
private static final List<String> TYPE_VIDEO = new ArrayList<>();
/**
* 压缩文件类型
*/
private static final List<String> TYPE_COMPRESS = new ArrayList<>();
static {
TYPE_IMAGE.add("png");
TYPE_IMAGE.add("gif");
TYPE_IMAGE.add("jpeg");
TYPE_IMAGE.add("jpg");
TYPE_DOC.add("pdf");
TYPE_DOC.add("ppt");
TYPE_DOC.add("xls");
TYPE_DOC.add("xlsx");
TYPE_DOC.add("pptx");
TYPE_DOC.add("doc");
TYPE_DOC.add("docx");
TYPE_VIDEO.add("mp3");
TYPE_VIDEO.add("mp4");
TYPE_VIDEO.add("flv");
TYPE_COMPRESS.add("zip");
TYPE_COMPRESS.add("rar");
}
/**
* 检查图片类型. <br>
* 默认检查 ['png', 'gif', 'jpeg', 'jpg'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkImage(String filename){
return checkImage(null, filename);
}
/**
* 检查图片类型
* @param types 可自行传入文件的类型集合,默认检查 ['png', 'gif', 'jpeg', 'jpg'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkImage(List<String> types, String filename){
List<String> checkTypes = types;
if(types == null || types.size() == 0){
checkTypes = TYPE_IMAGE;
}
return checkType(checkTypes, filename);
}
/**
* 检查文档类型. <br>
* 默认检查 ['pdf', 'ppt', 'xls', 'xlsx', 'pptx', 'doc', 'docx'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkDoc(String filename){
return checkDoc(null, filename);
}
/**
* 检查文档类型
* @param types 可自行传入文件的类型集合,默认检查 ['pdf', 'ppt', 'xls', 'xlsx', 'pptx', 'doc', 'docx'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkDoc(List<String> types, String filename){
List<String> checkTypes = types;
if(types == null || types.size() == 0){
checkTypes = TYPE_DOC;
}
return checkType(checkTypes, filename);
}
/**
* 检查音频类型. <br>
* 默认检查 ['mp3', 'mp4', 'flv'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkVideo(String filename){
return checkVideo(null, filename);
}
/**
* 检查音频类型
* @param types 可自行传入文件的类型集合,默认检查 ['mp3', 'mp4', 'flv'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkVideo(List<String> types, String filename){
List<String> checkTypes = types;
if(types == null || types.size() == 0){
checkTypes = TYPE_VIDEO;
}
return checkType(checkTypes, filename);
}
/**
* 检查压缩文件类型. <br>
* 默认检查 ['zip', 'rar'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkCompress(String filename){
return checkCompress(null, filename);
}
/**
* 检查压缩文件类型
* @param types 可自行传入文件的类型集合,默认检查 ['zip', 'rar'] 几种类型
* @param filename 文件名称
* @return
*/
public static boolean checkCompress(List<String> types, String filename){
List<String> checkTypes = types;
if(types == null || types.size() == 0){
checkTypes = TYPE_COMPRESS;
}
return checkType(checkTypes, filename);
}
/**
* 检查类型通用方法
*/
private static boolean checkType(List<String> checkTypes, String filename){
return checkTypes.contains(getFilenameSuffix(filename));
}
/**
* 获取文件名称的后缀
*
* @param filename
* @return 文件后缀
*/
public static String getFilenameSuffix(String filename) {
String suffix = null;
if (StringUtils.isNotBlank(filename) && filename.contains(FastDFSClient.POINT)) {
suffix = filename.substring(filename.lastIndexOf(FastDFSClient.POINT) + 1).toLowerCase();
}
return suffix;
}
}
package com.loit.modules.fastdfs;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
/**
*
*
* @ClassName: FileResponseData.java
* @Description:上传文件后的数据返回对象,便于前台获取数据.
*
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 上午10:20:51
*/
public class FileResponseData {
/**
* 返回状态编码
*/
@JsonInclude(Include.NON_NULL)
private String code;
/**
* 返回信息
*/
@JsonInclude(Include.NON_NULL)
private String message;
/**
* 成功标识
*/
private boolean success = true;
/**
* 文件路径
*/
@JsonInclude(Include.NON_NULL)
private String filePath;
/**
* 文件名称
*/
@JsonInclude(Include.NON_NULL)
private String fileName;
/**
* 文件类型
*/
@JsonInclude(Include.NON_NULL)
private String fileType;
/**
* Http URL
*/
@JsonInclude(Include.NON_NULL)
private String httpUrl;
/**
* Http Token
*/
/* @JsonInclude(Include.NON_NULL)
private String token;
*/
public FileResponseData(){}
public FileResponseData(boolean success) {
this.success = success;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public String getHttpUrl() {
return httpUrl;
}
public void setHttpUrl(String httpUrl) {
this.httpUrl = httpUrl;
}
/*public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}*/
}
package com.loit.modules.fastdfs;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
/**
*
*
* @ClassName: TrackerServerFactory.java
* @Description: 工厂类,创建对象池需要 BasePooledObjectFactory 对象或子类.
*
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 上午9:04:13
*/
public class TrackerServerFactory extends BasePooledObjectFactory<TrackerServer> {
@Override
public TrackerServer create() throws Exception {
// TrackerClient
TrackerClient trackerClient = new TrackerClient();
// TrackerServer
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
@Override
public PooledObject<TrackerServer> wrap(TrackerServer trackerServer) {
return new DefaultPooledObject<TrackerServer>(trackerServer);
}
}
package com.loit.modules.fastdfs;
import java.io.IOException;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.loit.common.config.SpringContextUtil;
/**
*
*
* @ClassName: TrackerServerPool.java
* @Description: TrackerServer 对象池
* @version: v1.0.0
* @author: gaodengyun
* @date: 2019年4月24日 上午9:03:19
*/
@Component
public class TrackerServerPool {
/**
* org.slf4j.Logger
*/
private static Logger logger = LoggerFactory.getLogger(TrackerServerPool.class);
/**
* TrackerServer 配置文件路径
*/
private static final String FASTDFS_CONFIG_DEV_PATH ="config/config-dev.properties";
/**
* TrackerServer 配置文件路径
*/
private static final String FASTDFS_CONFIG_PROC_PATH ="config/config-proc.properties";
/**
* TrackerServer 配置文件路径
*/
private static final String FASTDFS_CONFIG_TESST_PATH ="config/config-test.properties";
/**
* 最大连接数 default 8.
*/
private static int maxStorageConnection;
@Value("${fastdfs.max_storage_connection}")
public void setMaxStorageConnection(int maxStorageConnection) {
TrackerServerPool.maxStorageConnection = maxStorageConnection;
}
/**
* TrackerServer 对象池.
* GenericObjectPool 没有无参构造
*/
private static GenericObjectPool<TrackerServer> trackerServerPool;
private TrackerServerPool(){};
private static synchronized GenericObjectPool<TrackerServer> getObjectPool(){
if(trackerServerPool == null){
try {
// 加载配置文件
String activeMode = SpringContextUtil.getActiveProfile();
System.out.println("activeMode:==="+activeMode);
System.out.println("maxStorageConnection:==="+maxStorageConnection);
switch (activeMode) {
case "proc":
ClientGlobal.initByProperties(FASTDFS_CONFIG_PROC_PATH);
break;
case "dev":
ClientGlobal.initByProperties(FASTDFS_CONFIG_DEV_PATH);
break;
default:
ClientGlobal.initByProperties(FASTDFS_CONFIG_TESST_PATH);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
if(logger.isDebugEnabled()){
logger.debug("ClientGlobal configInfo: {}", ClientGlobal.configInfo());
}
// Pool配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(2);
if(maxStorageConnection > 0){
poolConfig.setMaxTotal(maxStorageConnection);
}
trackerServerPool = new GenericObjectPool<>(new TrackerServerFactory(), poolConfig);
}
return trackerServerPool;
}
/**
* 获取 TrackerServer
* @return TrackerServer
* @throws FastDFSException
*/
public static TrackerServer borrowObject() throws FastDFSException {
TrackerServer trackerServer = null;
try {
trackerServer = getObjectPool().borrowObject();
System.out.println(trackerServerPool.getBorrowedCount()+","+trackerServerPool.getCreatedCount()+","+trackerServerPool.getDestroyedByBorrowValidationCount()+","+trackerServerPool.getDestroyedByEvictorCount()+","+trackerServerPool.getDestroyedCount()+","+trackerServerPool.getReturnedCount());
} catch (Exception e) {
e.printStackTrace();
if(e instanceof FastDFSException){
throw (FastDFSException) e;
}
}
return trackerServer;
}
/**
* 回收 TrackerServer
* @param trackerServer 需要回收的 TrackerServer
*/
public static void returnObject(TrackerServer trackerServer){
getObjectPool().returnObject(trackerServer);
}
}
package com.loit.web.file.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.loit.common.config.FastDFSConfigInfo;
import com.loit.common.json.AjaxJson;
import com.loit.common.json.LoitStatusCode;
import com.loit.modules.fastdfs.ErrorCode;
import com.loit.modules.fastdfs.FastDFSClient;
import com.loit.modules.fastdfs.FastDFSException;
import com.loit.modules.fastdfs.FileResponseData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
/**
* @description 文件上传下载管理Controller
* @author fangshiquan
* @date 2019-11-08
* @version V1.0
*/
@RestController
@RequestMapping(value = "api/file")
@Api(tags = "文件管理", value = "FileRestController")
public class FileRestController {
@Autowired
private FastDFSConfigInfo fastDFSConfigInfo;
private FastDFSClient fastDFSClient = new FastDFSClient();
@GetMapping(value = "demo")
public String demo(HttpServletRequest request) {
System.out.println("dedmo");
System.out.println(request.getHeader("a"));
return "demo";
}
/**
* @description 上传文件
* @param file 文件参数
* @param request 请求
* @return AjaxJson
*/
@PostMapping(value = "upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation(value="文件上传", notes="文件上传")
public AjaxJson fileUpload(@RequestParam(value = "file", required = true) MultipartFile file, HttpServletRequest request) {
AjaxJson json = new AjaxJson();
//文件保存
FileResponseData fileResponseData =uploadSample(file, request);
json.setSuccess(fileResponseData.isSuccess());
json.setMsg(fileResponseData.getMessage());
json.setErrorCode(fileResponseData.getCode());
json.put("fileResponseData", fileResponseData);
return json;
}
/**
* 以附件形式下载文件
*
* @param filePath 文件地址
* @param response
*/
@RequestMapping(value="/download", method=RequestMethod.GET)
@ApiImplicitParam(name = "filePath", value = "文件路径", required = true, dataType = "String",paramType = "query")
@ApiOperation(value="文件下载", notes="文件下载")
public void downloadFile(String filePath, HttpServletResponse response) throws FastDFSException {
try {
if (filePath.startsWith("http://")) {
filePath =filePath.replace(fastDFSConfigInfo.getFileServerPrefix(), "");
}
fastDFSClient.downloadFile(filePath, response);
} catch (FastDFSException e) {
e.printStackTrace();
throw e;
}
}
/**
* 根据指定的路径删除服务器文件,适用于没有保存数据库记录的文件
*
* @param filePath
*/
@ApiImplicitParam(name = "filePath", value = "filePath", required = true, dataType = "String",paramType = "query")
@ApiOperation(value="文件删除", notes="文件删除")
@RequestMapping(value="/delete", method=RequestMethod.DELETE)
public AjaxJson deleteFile(@RequestParam(value = "filePath") String filePath) {
AjaxJson json = new AjaxJson();
FileResponseData responseData = new FileResponseData();
try {
if (filePath.startsWith("http://")) {
filePath =filePath.replace(fastDFSConfigInfo.getFileServerPrefix(), "");
}
fastDFSClient.deleteFile(filePath);
} catch (FastDFSException e) {
e.printStackTrace();
responseData.setSuccess(false);
responseData.setCode(e.getCode());
responseData.setMessage(e.getMessage());
json.setSuccess(false);
json.setMsg(e.getMessage());
json.setErrorCode(LoitStatusCode.FILE_DELETE_FAILED.statusCode);
json.put("fileResponseData", responseData);
}
return json;
}
/**
* 上传通用方法,只上传到服务器,不保存记录到数据库
*
* @param file
* @param request
* @return
*/
@SuppressWarnings("static-access")
public FileResponseData uploadSample(MultipartFile file, HttpServletRequest request){
FileResponseData responseData = new FileResponseData();
try {
// 上传到服务器
String suffix =fastDFSClient.getFilenameSuffix(file.getOriginalFilename());
if(fastDFSClient.EXT_MAPS.get(suffix)!=null) {
String filepath = fastDFSClient.uploadFileWithMultipart(file);
responseData.setFileName(file.getOriginalFilename());
responseData.setFilePath(filepath);
responseData.setFileType(FastDFSClient.getFilenameSuffix(file.getOriginalFilename()));
// 设置访文件的Http地址. 有时效性.
/* String token = FastDFSClient.getToken(filepath, fastDFSHttpSecretKey);
responseData.setToken(token);*/
//responseData.setHttpUrl(fileServerAddr+"/"+filepath+"?"+token);
responseData.setHttpUrl(fastDFSConfigInfo.getFileServerPrefix()+"/"+filepath);
}else {
responseData.setSuccess(false);
responseData.setCode(ErrorCode.FILE_TYPE_ERROR_ALLOW.CODE);
responseData.setMessage(ErrorCode.FILE_TYPE_ERROR_ALLOW.MESSAGE);
}
} catch (FastDFSException e) {
responseData.setSuccess(false);
responseData.setCode(e.getCode());
responseData.setMessage(e.getMessage());
}
return responseData;
}
/**
* 并发接口测试
* @return
*/
@GetMapping("/getMapInfo")
public Map<String,Object> getMapInfo(){
Map<String,Object> map=new HashMap<String, Object>();
map.put("name","fangshiquan");
map.put("age","20");
map.put("sex","男");
map.put("where","datian");
map.put("daxia","令狐冲");
map.put("daxia2","令狐冲ee");
map.put("da6xia2","333令狐冲ee");
map.put("da6hhh","33kk狐冲ee");
map.put("da6hhh2","33kk狐冲ee");
map.put("da6hhh1","33kk狐冲ee");
map.put("da6hhh3","33kk狐冲ee");
map.put("da6hhh4","33kk狐冲ee");
map.put("da6hhh5","33kk狐冲ee");
map.put("da6hhh6","33kk狐冲ee");
map.put("da6hhh7","33kk狐冲ee");
map.put("da6哈哈ia2","333令狐冲ee");
map.put("d发给过hh","33kk狐冲ee");
map.put("da分为非h2","33kk狐冲ee");
map.put("da分为e非h1","33kk狐冲ee");
map.put("da6h发hh3","33kk狐冲ee");
map.put("da6hh分h4","33kk狐冲ee");
map.put("da6hh仍无法h5","33kk狐冲ee");
map.put("da6hh违法h6","33kk狐冲ee");
map.put("da6hhh7","33kk狐冲ee");
return map;
}
}
fastdfs:
file_server_prefix: http://39.100.254.140
max_storage_connection: 8
fdfs:
connect-timeout: 6000
pool:
jmx-name-base: 1
jmx-name-prefix: 1
max-wait-millis: 500
so-timeout: 6000
thumb-image:
height: 150
width: 150
tracker-list:
- 39.100.254.140:22122
pool:
max-total: 153
server:
port: 7003
tomcat:
basedir: D:\file\temp
spring:
application:
name: loit-file
freemarker:
allow-request-override: false
allow-session-override: false
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
order: 1
prefer-file-system-access: true
request-context-attribute: request
settings:
classic_compatible: true
datetime_format: yyyy-MM-dd HH:mm:ss
default_encoding: UTF-8
number_format: 0.##########
template_exception_handler: ignore
template_update_delay: 0
suffix: .ftl
template-loader-path: classpath:/templates/
redis:
host: 127.0.0.1
#password: portal2019
pool:
max-active: 1
max-idle: 8
max-wait: 20000
min-idle: 8
port: 6379
timeout: 20000
servlet:
multipart:
max-file-size: 2048MB
max-request-size: 2048MB
cloud:
nacos:
discovery:
# Nacos 注册中心地址
server-addr: 39.100.254.140:8103
namespace: 3ac84119-5558-4bf8-b309-034dd0e458e0
zwup:
maxSize: 102400
\ No newline at end of file
# 演示环境
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8003/eureka/
# instance:
# prefer-ip-address: true
# instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
# leaseRenewalIntervalInSeconds: 10
# health-check-url-path: /actuator/health
#权限配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
info:
name: '@project.name@'
description: '@project.description@'
fastdfs:
file_server_prefix: http://39.100.254.140
max_storage_connection: 8
fdfs:
connect-timeout: 6000
pool:
jmx-name-base: 1
jmx-name-prefix: 1
max-wait-millis: 500
so-timeout: 6000
thumb-image:
height: 150
width: 150
tracker-list:
- 39.100.254.140:22122
pool:
max-total: 153
server:
port: 6001
tomcat:
basedir: /var/www/tomcat/temp
spring:
application:
name: loit-file
freemarker:
allow-request-override: false
allow-session-override: false
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
order: 1
prefer-file-system-access: true
request-context-attribute: request
settings:
classic_compatible: true
datetime_format: yyyy-MM-dd HH:mm:ss
default_encoding: UTF-8
number_format: 0.##########
template_exception_handler: ignore
template_update_delay: 0
suffix: .ftl
template-loader-path: classpath:/templates/
http:
multipart:
maxFileSize: 2048mb
maxRequestSize: 2048mb
redis:
host: 127.0.0.1
password: portal2019
pool:
max-active: 1
max-idle: 8
max-wait: 20000
min-idle: 8
port: 6379
timeout: 20000
servlet:
multipart:
max-file-size: 2048mb
max-request-size: 2048mb
cloud:
nacos:
discovery:
#Nacos 注册中心地址
server-addr: 39.100.254.140:8103
namespace: 0e1abf19-be7e-4940-b6da-ff5f697a226c
zwup:
maxSize: 102400
\ No newline at end of file
# 南巨马河环境
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8003/eureka/
# instance:
# prefer-ip-address: true
# instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
# leaseRenewalIntervalInSeconds: 10
# health-check-url-path: /actuator/health
#权限配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
info:
name: '@project.name@'
description: '@project.description@'
fastdfs:
file_server_prefix: http://39.100.254.140
max_storage_connection: 8
fdfs:
connect-timeout: 6000
pool:
jmx-name-base: 1
jmx-name-prefix: 1
max-wait-millis: 500
so-timeout: 6000
thumb-image:
height: 150
width: 150
tracker-list:
- 39.100.254.140:22122
pool:
max-total: 153
server:
port: 6006
tomcat:
basedir: /var/www/tomcat/temp
spring:
application:
name: loit-file
freemarker:
allow-request-override: false
allow-session-override: false
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
order: 1
prefer-file-system-access: true
request-context-attribute: request
settings:
classic_compatible: true
datetime_format: yyyy-MM-dd HH:mm:ss
default_encoding: UTF-8
number_format: 0.##########
template_exception_handler: ignore
template_update_delay: 0
suffix: .ftl
template-loader-path: classpath:/templates/
http:
multipart:
maxFileSize: 2048mb
maxRequestSize: 2048mb
redis:
host: 127.0.0.1
password: portal2019
pool:
max-active: 1
max-idle: 8
max-wait: 20000
min-idle: 8
port: 6379
timeout: 20000
servlet:
multipart:
max-file-size: 2048mb
max-request-size: 2048mb
cloud:
nacos:
discovery:
#Nacos 注册中心地址
server-addr: 39.100.254.140:8103
namespace: 6c8fa2e5-a3b8-48a0-9ab6-c1097ecc0dc3
zwup:
maxSize: 102400
\ No newline at end of file
# 测试环境
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8003/eureka/
# instance:
# prefer-ip-address: true
# instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
# leaseRenewalIntervalInSeconds: 10
# health-check-url-path: /actuator/health
#权限配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
info:
name: '@project.name@'
description: '@project.description@'
fastdfs:
file_server_prefix: http://39.100.254.140
max_storage_connection: 8
fdfs:
connect-timeout: 6000
pool:
jmx-name-base: 1
jmx-name-prefix: 1
max-wait-millis: 500
so-timeout: 6000
thumb-image:
height: 150
width: 150
tracker-list:
- 39.100.254.140:22122
pool:
max-total: 153
server:
port: 7004
tomcat:
basedir: /var/www/tomcat/temp
spring:
application:
name: loit-file
freemarker:
allow-request-override: false
allow-session-override: false
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
order: 1
prefer-file-system-access: true
request-context-attribute: request
settings:
classic_compatible: true
datetime_format: yyyy-MM-dd HH:mm:ss
default_encoding: UTF-8
number_format: 0.##########
template_exception_handler: ignore
template_update_delay: 0
suffix: .ftl
template-loader-path: classpath:/templates/
http:
multipart:
maxFileSize: 2048mb
maxRequestSize: 2048mb
redis:
host: 127.0.0.1
password: portal2019
pool:
max-active: 1
max-idle: 8
max-wait: 20000
min-idle: 8
port: 6379
timeout: 20000
servlet:
multipart:
max-file-size: 2048mb
max-request-size: 2048mb
cloud:
nacos:
discovery:
#Nacos 注册中心地址
server-addr: 39.100.254.140:8103
namespace: 68bb4674-3664-4d81-966a-41118dd00905
zwup:
maxSize: 102400
\ No newline at end of file
spring:
profiles:
active: dev
\ No newline at end of file
spring.profiles.active=dev
spring.application.name=loit-file
# Nacos ĵַ
spring.cloud.nacos.config.server-addr=39.100.254.140:8103
spring.cloud.nacos.config.namespace=3ac84119-5558-4bf8-b309-034dd0e458e0
spring.cloud.nacos.config.file-extension=yaml
\ No newline at end of file
fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80
fastdfs.tracker_servers = 39.100.254.140:22122
\ No newline at end of file
fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80
fastdfs.tracker_servers = 39.100.254.140:22122
\ No newline at end of file
fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80
fastdfs.tracker_servers = 39.100.254.140:22122
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form id="form1" method="post" action="http://localhost:7003/api/file/upload" class="form box" enctype="multipart/form-data">
<input type="file" name="file" id="file"/>
<input type="submit" value="weweweewewe">
</form>
</body>
</html>
\ No newline at end of file
/*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */
;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'<h3 style="'+(e?n.title[1]:"")+'">'+(e?n.title[0]:n.title)+"</h3>":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type="1">'+n.btn[0]+"</span>",2===t&&(e='<span no type="0">'+n.btn[1]+"</span>"+e),'<div class="layui-m-layerbtn">'+e+"</div>"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='<i></i><i class="layui-m-layerload"></i><i></i><p>'+(n.content||"")+"</p>"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"<div "+("string"==typeof n.shade?'style="'+n.shade+'"':"")+' class="layui-m-layershade"></div>':"")+'<div class="layui-m-layermain" '+(n.fixed?"":'style="position:static;"')+'><div class="layui-m-layersection"><div class="layui-m-layerchild '+(n.skin?"layui-m-layer-"+n.skin+" ":"")+(n.className?n.className:"")+" "+(n.anim?"layui-m-anim-"+n.anim:"")+'" '+(n.style?'style="'+n.style+'"':"")+">"+l+'<div class="layui-m-layercont">'+n.content+"</div>"+c+"</div></div></div>",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i]("layui-m-layershade")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:"2.0",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a("#"+o[0]+e)[0];n&&(n.innerHTML="",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],"function"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute("index"))}},"function"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf("/")+1);n.getAttribute("merge")||document.head.appendChild(function(){var e=t.createElement("link");return e.href=a+"need/layer.css?2.0",e.type="text/css",e.rel="styleSheet",e.id="layermcss",e}())}()}(window);
\ No newline at end of file
.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}
\ No newline at end of file
.webuploader-container {
position: relative;
}
.webuploader-element-invisible {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px,1px,1px,1px);
}
.webuploader-pick {
position: relative;
display: inline-block;
cursor: pointer;
background: #00b7ee;
padding: 10px 15px;
color: #fff;
text-align: center;
border-radius: 3px;
overflow: hidden;
}
.webuploader-pick-hover {
background: #00a2d4;
}
.webuploader-pick-disable {
opacity: 0.6;
pointer-events:none;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论