Compare commits

...

8 Commits
3.2.2 ... 3.2.4

Author SHA1 Message Date
赵俊
4dd6cdb4b3 合并拉取请求 #348
fix: modify extract driveId regex in WebDavController
2022-05-03 21:16:40 +08:00
quericy
c6127c029f fix: modify extract driveId regex in WebDavController 2022-04-14 10:06:46 +08:00
zhaojun
e149039ecb 🔖 发布 3.2.3 版本 2022-04-13 00:03:49 +08:00
zhaojun
37688d83cf feature: 降低 webdav 日志级别 2022-04-13 00:03:28 +08:00
zhaojun
6692016642 feature: 新增 webdav 开关功能 2022-04-13 00:01:59 +08:00
zhaojun
3f41aeda9a fix(bug): 修复因字段名称修改升级后导致短链异常 bug 2022-04-12 23:38:49 +08:00
赵俊
de86d5c47d 合并拉取请求 #347
feat: support webdav
2022-04-11 09:56:11 +08:00
quericy
c89e072005 feat: support webdav
1, feat:config webDav and milton in configuration;
2, feat:add event handler in WebDavController;
3, feat:check auth by admin in systemConfig;
4, feat:download webDav file by redirect to site DirectLink;
2022-04-10 04:11:34 +08:00
18 changed files with 808 additions and 4 deletions

19
pom.xml
View File

@@ -12,7 +12,7 @@
<groupId>im.zhaojun</groupId>
<artifactId>zfile</artifactId>
<version>3.2.2</version>
<version>3.2.3</version>
<name>zfile</name>
<packaging>war</packaging>
<description>一个在线的文件浏览系统</description>
@@ -94,6 +94,23 @@
<version>3.6</version>
</dependency>
<!-- WebDav -->
<dependency>
<groupId>io.milton</groupId>
<artifactId>milton-server-ce</artifactId>
<version>3.1.1.413</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>json</artifactId>
<groupId>org.json</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 其他工具类 -->
<dependency>
<groupId>org.projectlombok</groupId>

View File

@@ -0,0 +1,36 @@
package im.zhaojun.zfile.config;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
/**
* 应用上下文配置
*
* @author me
* @date 2022/4/9
*/
@Configuration
public class ApplicationContextConfigure implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextConfigure.applicationContext = applicationContext;
}
/**
* bean名称获取对象
*/
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
/**
* bean类型获取对象
*/
public static <T> T getBean(Class<T> clazz) throws BeansException {
return applicationContext.getBean(clazz);
}
}

View File

@@ -0,0 +1,60 @@
package im.zhaojun.zfile.config.webdav;
import im.zhaojun.zfile.config.webdav.adapter.WebDavUrlAdapterImpl;
import im.zhaojun.zfile.config.webdav.auth.SystemConfigSecurityManager;
import im.zhaojun.zfile.config.webdav.resolver.WebDavRedirectViewResolver;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
import im.zhaojun.zfile.service.SystemConfigService;
import io.milton.http.ResourceFactory;
import io.milton.http.SecurityManager;
import io.milton.http.annotated.AnnotationResourceFactory;
import io.milton.http.fs.NullSecurityManager;
import io.milton.servlet.DefaultMiltonConfigurator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* Milton(webDav)配置
*
* @author me
* @date 2022/4/9
*/
@Configuration
public class MiltonConfiguration extends DefaultMiltonConfigurator implements InitializingBean {
/**
* 安全管理器
*/
private static SecurityManager securityManager = new NullSecurityManager();
@Resource
private SystemConfigService systemConfigService;
/**
* 构建milton初始化配置
*/
@Override
protected void build() {
builder.setSecurityManager(securityManager);
builder.setContextPath(ZFileConstant.WEB_DAV_PREFIX);
builder.setUrlAdapter(new WebDavUrlAdapterImpl());
final ResourceFactory resourceFactory = builder.getResourceFactory();
if (resourceFactory instanceof AnnotationResourceFactory) {
((AnnotationResourceFactory) resourceFactory).setViewResolver(new WebDavRedirectViewResolver());
}
super.build();
}
/**
* 属性初始化完成后,更新安全管理器,使用系统配置鉴权
*/
@Override
public void afterPropertiesSet() throws Exception {
final SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
if (systemConfig != null) {
securityManager = new SystemConfigSecurityManager(systemConfig);
}
}
}

View File

@@ -0,0 +1,33 @@
package im.zhaojun.zfile.config.webdav;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import io.milton.http.annotated.AnnotationResourceFactory;
import io.milton.servlet.MiltonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* WebDav配置
*
* @author me
* @date 2022/4/9
*/
@Configuration
public class WebDavConfiguration {
@Bean
public FilterRegistrationBean miltonFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MiltonFilter());
registration.setName("miltonFilter");
registration.addUrlPatterns(ZFileConstant.WEB_DAV_PREFIX + "/*");
registration.addInitParameter("resource.factory.class", AnnotationResourceFactory.class.getName());
registration.addInitParameter("milton.configurator", MiltonConfiguration.class.getName());
registration.addInitParameter("controllerPackagesToScan", "im.zhaojun.zfile.controller.home");
registration.setOrder(1);
return registration;
}
}

View File

@@ -0,0 +1,41 @@
package im.zhaojun.zfile.config.webdav.adapter;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import im.zhaojun.zfile.util.RegexMatchUtils;
import io.milton.http.HttpManager;
import io.milton.http.Request;
import io.milton.http.UrlAdapter;
import java.util.regex.Matcher;
/**
* WebDav路径适配器实现
*
* @author me
* @date 2022/4/10
*/
public class WebDavUrlAdapterImpl implements UrlAdapter {
/**
* 获取url
* eg: domain.com/{webdavPrefix}/{driveId}/{folders}
*
* @param request 请求
* @return {@link String}
*/
@Override
public String getUrl(Request request) {
// 匹配url前缀和驱动器ID
Matcher matcher = RegexMatchUtils.match("^" + ZFileConstant.WEB_DAV_PREFIX + "/(\\d+)(.*)",
HttpManager.decodeUrl(request.getAbsolutePath()));
final String driveId = RegexMatchUtils.getIndexResult(matcher, 1);
if (driveId == null) {
return "";
}
// 获取摘除前缀和驱动器ID后的文件路径
final String realPath = RegexMatchUtils.getIndexResult(matcher, 2);
return realPath != null ? realPath : "";
}
}

View File

@@ -0,0 +1,130 @@
package im.zhaojun.zfile.config.webdav.auth;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.SecureUtil;
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
import io.milton.http.Auth;
import io.milton.http.Request;
import io.milton.http.Request.Method;
import io.milton.http.http11.auth.DigestResponse;
import io.milton.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
/**
* 基于当前系统配置的WebDav鉴权管理器
*
* @author me
* @date 2022/4/10
* @see io.milton.http.fs.SimpleSecurityManager
*/
public class SystemConfigSecurityManager implements io.milton.http.SecurityManager {
private static final Logger log = LoggerFactory.getLogger(SystemConfigSecurityManager.class);
private String realm = "SystemConfig";
private Map<String, String> nameAndPasswords;
/**
* 根据系统配置创建安全管理器
*
* @param systemConfig 系统配置DTO
*/
public SystemConfigSecurityManager(SystemConfigDTO systemConfig) {
if (systemConfig != null) {
this.nameAndPasswords = MapUtil.of(systemConfig.getUsername(), systemConfig.getPassword());
}
}
public Object getUserByName(String name) {
String actualPassword = nameAndPasswords.get(name);
if (actualPassword != null) {
return name;
}
return null;
}
/**
* 用户名+密码身份验证
*
* @param user 用户
* @param password 密码
* @return {@link Object}
*/
@Override
public Object authenticate(String user, String password) {
if (user.contains("@")) {
user = user.substring(0, user.indexOf("@"));
}
String actualPassword = nameAndPasswords.get(user);
if (actualPassword == null) {
log.debug("user not found: " + user);
return null;
} else {
//比对密码MD5摘要
return (actualPassword.equals(SecureUtil.md5(password))) ? user : null;
}
}
/**
* 请求摘要身份验证(不进行换算)
*
* @param digestRequest 消化的请求
* @return {@link Object}
*/
@Override
public Object authenticate(DigestResponse digestRequest) {
String serverResponse = nameAndPasswords.get(digestRequest.getUser());
String clientResponse = digestRequest.getResponseDigest();
//比对密码MD5摘要
if (serverResponse.equals(SecureUtil.md5(clientResponse))) {
return "ok";
} else {
return null;
}
}
@Override
public boolean authorise(Request request, Method method, Auth auth, Resource resource) {
if (auth == null) {
log.trace("authorise: declining because there is no auth object");
return false;
} else {
if (auth.getTag() == null) {
log.trace("authorise: declining because there is no auth.getTag() object");
return false;
} else {
log.trace("authorise: permitting because there is an authenticated user associated with this request");
return true;
}
}
}
@Override
public String getRealm(String host) {
return realm;
}
/**
* @param realm the realm to set
*/
public void setRealm(String realm) {
this.realm = realm;
}
public void setNameAndPasswords(Map<String, String> nameAndPasswords) {
this.nameAndPasswords = nameAndPasswords;
}
@Override
public boolean isDigestAllowed() {
// 关闭请求摘要换算client端请求时若换算为摘要则无法和系统设置中获取的密码MD5比对
return false;
}
}

View File

@@ -0,0 +1,62 @@
package im.zhaojun.zfile.config.webdav.resolver;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import im.zhaojun.zfile.model.entity.webdav.WebDavFile;
import io.milton.common.View;
import io.milton.http.template.TemplateProcessor;
import io.milton.http.template.ViewResolver;
import io.milton.servlet.OutputStreamWrappingHttpServletResponse;
import io.milton.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
/**
* WebDav重定向视图处理器
* Get注解handler返回字符串时将使用本ViewResolver处理
*
* @author me
* @date 2022/4/9
*/
public class WebDavRedirectViewResolver implements ViewResolver {
@Override
public TemplateProcessor resolveView(View view) {
return new RedirectTemplateProcessor();
}
/**
* 重定向模板处理程序
*
* @author me
* @date 2022/04/10
*/
public static class RedirectTemplateProcessor implements TemplateProcessor {
@Override
public void execute(Map<String, Object> model, OutputStream out) {
try {
// 获取要下载的资源文件
final Object resource = model.get("resource");
if (!(resource instanceof WebDavFile)) {
throw new RuntimeException("couldn't get direct url.");
}
final WebDavFile file = (WebDavFile) resource;
// 构造文件直链的路径
final String redirectPath = String.format("/%s/%s%s", ZFileConstant.DIRECT_LINK_PREFIX, file.getDriveId(), file.getFullPath());
// 重定向到直链
HttpServletResponse resp = new OutputStreamWrappingHttpServletResponse(ServletResponse.getResponse(), out);
resp.setStatus(301);
resp.setHeader("Location", URLUtil.encode(redirectPath));
resp.setHeader("Connection", "close");
resp.flushBuffer();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@@ -0,0 +1,159 @@
package im.zhaojun.zfile.controller.home;
import com.alibaba.fastjson.JSON;
import im.zhaojun.zfile.config.ApplicationContextConfigure;
import im.zhaojun.zfile.context.DriveContext;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import im.zhaojun.zfile.model.dto.FileItemDTO;
import im.zhaojun.zfile.model.entity.webdav.WebDavEntity;
import im.zhaojun.zfile.model.entity.webdav.WebDavFile;
import im.zhaojun.zfile.model.entity.webdav.WebDavFolder;
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
import im.zhaojun.zfile.util.RegexMatchUtils;
import io.milton.annotations.*;
import io.milton.http.HttpManager;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* WebDav控制器
*
* @author me
* @date 2022/4/9
*/
@Slf4j
@ResourceController
@ConditionalOnProperty(value = "webdav.enable", havingValue = "true")
public class WebDavController {
private static final Logger LOGGER = LoggerFactory.getLogger(WebDavController.class);
/**
* 获取根目录文件夹
*
* @return {@link WebDavFolder} WebDav文件夹
*/
@Root
public WebDavFolder getRootFolder() {
return new WebDavFolder(ZFileConstant.PATH_SEPARATOR, getDriveId());
}
/**
* 获取根目录子文件/文件夹(控制器)
*
* @param rootFolder 根文件夹
* @return {@link WebDavController} 根控制器
*/
@ChildrenOf
public WebDavController getChildren(WebDavController rootFolder) {
return this;
}
/**
* 获取子文件/文件夹
*
* @param parent 父文件夹
* @return {@link List}<{@link WebDavEntity}> WebDav实体
*/
@ChildrenOf
public List<WebDavEntity> getChildren(WebDavFolder parent) {
if (parent == null) {
return Collections.emptyList();
}
try {
// 获取驱动器文件服务
AbstractBaseFileService fileService = ApplicationContextConfigure.getBean(DriveContext.class).get(parent.getDriveId());
if (fileService == null) {
return Collections.emptyList();
}
// 获取文件列表
List<FileItemDTO> fileItemList = fileService.fileList(parent.getFullPath());
// 转换FileItemDTO为WebDavEntity
return WebDavEntity.convertFromFileItemDTO(fileItemList, parent);
} catch (Exception e) {
LOGGER.warn("get webDav children failed,parent:{},msg:{}", JSON.toJSONString(parent), e.getMessage(), e);
return Collections.emptyList();
}
}
/**
* 获取子文件内容
*
* @param webDavFile WebDav文件
* @return {@link String} ViewResolver模板名称
*/
@Get
public String getChild(WebDavFile webDavFile) {
return JSON.toJSONString(webDavFile);
}
/**
* 获取WebDav实体文件名
*/
@Name
public String getWebDavFile(WebDavEntity webDavEntity) {
return webDavEntity.getName();
}
/**
* 获取WebDav实体展示名称
*/
@DisplayName
public String getDisplayName(WebDavEntity webDavEntity) {
return webDavEntity.getName();
}
/**
* 获取WebDav实体唯一id
*/
@UniqueId
public String getUniqueId(WebDavEntity entity) {
return entity.getId().toString();
}
/**
* 获取WebDav实体修改日期
*/
@ModifiedDate
public Date getModifiedDate(WebDavEntity webDavEntity) {
return webDavEntity.getModifiedDate();
}
/**
* 获取WebDav实体创建日期
*/
@CreatedDate
public Date getCreatedDate(WebDavEntity webDavEntity) {
return webDavEntity.getCreatedDate();
}
/**
* 获取WebDav实体大小
*/
@ContentLength
public Long getContentLength(WebDavEntity entity) {
if (entity instanceof WebDavFile) {
return ((WebDavFile) entity).getSize();
}
// 性能考虑,文件夹暂不进行大小统计
return null;
}
/**
* 获取驱动器id
*
* @return {@link Integer}
*/
private Integer getDriveId() {
String requestUrl = HttpManager.decodeUrl(HttpManager.request().getAbsolutePath());
final String driveId = RegexMatchUtils.matchByIndex("^" + ZFileConstant.WEB_DAV_PREFIX + "/(\\d+)(.*)", requestUrl, 1);
return driveId != null ? Integer.valueOf(driveId) : null;
}
}

View File

@@ -21,6 +21,11 @@ public class ZFileConstant {
*/
public static String DIRECT_LINK_PREFIX = "directlink";
/**
* WebDav前缀
*/
public static String WEB_DAV_PREFIX = "/webdav";
/**
* 系统产生的临时文件路径
*/

View File

@@ -0,0 +1,112 @@
package im.zhaojun.zfile.model.entity.webdav;
import im.zhaojun.zfile.model.constant.ZFileConstant;
import im.zhaojun.zfile.model.dto.FileItemDTO;
import im.zhaojun.zfile.model.enums.FileTypeEnum;
import im.zhaojun.zfile.util.StringUtils;
import lombok.Data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* WebDav实体
*
* @author me
* @date 2022/4/9
*/
@Data
public class WebDavEntity {
/**
* 唯一ID
*/
private UUID id;
/**
* 驱动器ID
*/
private Integer driveId;
/**
* 名称
*/
private String name;
/**
* 创建时间
*/
private Date createdDate;
/**
* 修改时间
*/
private Date modifiedDate;
/**
* 是否是目录
*/
private boolean isDirectory;
/**
* 父文件夹
*/
private WebDavFolder parent;
public WebDavEntity() {
}
public WebDavEntity(String name, WebDavFolder parent) {
this.id = UUID.randomUUID();
this.name = name;
this.parent = parent;
this.createdDate = new Date();
this.modifiedDate = new Date();
this.isDirectory = true;
}
public WebDavEntity(UUID id, String name, Date createdDate, Date modifiedDate,
WebDavFolder parent) {
this.id = id;
this.name = name;
this.parent = parent;
this.createdDate = createdDate;
this.modifiedDate = modifiedDate;
this.isDirectory = true;
}
/**
* 获取全路径
*/
public String getFullPath() {
if (this.getParent() != null) {
final String parentFullPath = this.getParent().getFullPath();
return StringUtils.removeDuplicateSeparator(parentFullPath + ZFileConstant.PATH_SEPARATOR + this.getName());
} else {
return ZFileConstant.PATH_SEPARATOR;
}
}
public static List<WebDavEntity> convertFromFileItemDTO(List<FileItemDTO> fileItemList, WebDavFolder parent) {
List<WebDavEntity> result = new ArrayList<>();
if (fileItemList == null || fileItemList.size() == 0) {
return result;
}
for (FileItemDTO each : fileItemList) {
WebDavEntity entity = convertFromFileItemDTO(each, parent);
result.add(entity);
}
return result;
}
public static WebDavEntity convertFromFileItemDTO(FileItemDTO fileItemDTO, WebDavFolder parent) {
if (fileItemDTO == null) {
return null;
}
WebDavEntity entity;
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
entity = new WebDavFolder(fileItemDTO.getName(), parent);
} else {
entity = new WebDavFile(fileItemDTO.getName(), fileItemDTO.getSize(), parent);
}
entity.setModifiedDate(fileItemDTO.getTime());
entity.setDriveId(parent.getDriveId());
return entity;
}
}

View File

@@ -0,0 +1,37 @@
package im.zhaojun.zfile.model.entity.webdav;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.UUID;
/**
* WebDav文件实体
*
* @author me
* @date 2022/4/9
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WebDavFile extends WebDavEntity {
/**
* 大小
*/
private Long size;
/**
* 内容类型
*/
private String contentType;
public WebDavFile(String fileName, Long size, WebDavFolder parent) {
super(fileName, parent);
this.setSize(size);
this.setDirectory(false);
}
public WebDavFile(UUID id, String name, Date createdDate, Date modifiedDate, WebDavFolder parent) {
super(id, name, createdDate, modifiedDate, parent);
this.setDirectory(false);
}
}

View File

@@ -0,0 +1,41 @@
package im.zhaojun.zfile.model.entity.webdav;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.UUID;
/**
* WebDav文件夹实体
*
* @author me
* @date 2022/4/9
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WebDavFolder extends WebDavEntity {
public WebDavFolder(String folderName, WebDavFolder parent) {
super(folderName, parent);
}
public WebDavFolder(String folderName, Integer driveId) {
super(folderName, null);
setDriveId(driveId);
}
public WebDavFolder(UUID id, String name, Date createdDate, Date modifiedDate, WebDavFolder parent) {
super(id, name, createdDate, modifiedDate, parent);
}
public WebDavFile addFile(String fileName, Long size) {
WebDavFile file = new WebDavFile(fileName, size, this);
file.setDirectory(false);
return file;
}
public WebDavFolder addFolder(String folderName) {
return new WebDavFolder(folderName, this);
}
}

View File

@@ -0,0 +1,61 @@
package im.zhaojun.zfile.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正则匹配工具类
*
* @author me
* @date 2022/4/9
*/
public class RegexMatchUtils {
/**
* 正则匹配分组序号值
*
* @param regex 正则表达式
* @param str 待匹配字符串
* @param index 分组序号,从1开始
* @return {@link String} 不存在/匹配失败返回null
*/
public static String matchByIndex(String regex, String str, Integer index) {
Matcher matcher = match(regex, str);
if (matcher == null) {
return null;
}
return getIndexResult(matcher, index);
}
/**
* 匹配字符串
*
* @param regex 正则表达式
* @param str 待匹配字符串
* @return {@link Matcher}
*/
public static Matcher match(String regex, String str) {
if (str == null || "".equals(str)) {
return null;
}
Matcher matcher = Pattern.compile(regex).matcher(str);
if (!matcher.lookingAt()) {
return null;
}
return matcher;
}
/**
* 获取指定分组序号的匹配结果
*
* @param matcher {@link Matcher}
* @param index 分组序号,从1开始
* @return {@link String} 不存在/匹配失败返回null
*/
public static String getIndexResult(Matcher matcher, Integer index) {
if (matcher == null || index == null || index < 0 || index > matcher.groupCount()) {
return null;
}
return matcher.group(index);
}
}

View File

@@ -97,6 +97,11 @@
"type": "java.lang.String",
"defaultValue": "directlink",
"description": "直链前缀名称, 默认为 directlink"
},
{
"name": "zfile.webdav",
"type": "java.lang.Boolean",
"description": "是否开启 webdav 文件管理."
}
]
}

View File

@@ -1,5 +1,6 @@
zfile:
debug: false
webdav: false
directLinkPrefix: directlink
log:
path: ${user.home}/.zfile/logs
@@ -80,4 +81,4 @@ spring:
continue-on-error: true
mode: always
data-locations: classpath*:db/data.sql
encoding: utf-8
encoding: utf-8

View File

@@ -13,4 +13,5 @@ INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (17, 'showAnnoun
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (18, 'layout', '页面布局', 'full');
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (19, 'showLinkBtn', '是否显示生成直链按钮', 'true');
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (20, 'showShortLink', '是否显示短链', 'true');
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (21, 'showPathLink', '是否显示路径直链', 'true');
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (21, 'showPathLink', '是否显示路径直链', 'true');
alter table short_link change "key" key varchar(255) null;

View File

@@ -76,6 +76,9 @@
true 表示当前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- milton webdav -->
<logger name="io.milton" additivity="false" level="info"/>
<!-- jetCache logger -->
<logger name="com.alicp" additivity="false" level="debug"/>

File diff suppressed because one or more lines are too long