init
parent
08619ea2c1
commit
313506db24
|
|
@ -1,4 +0,0 @@
|
||||||
FROM frolvlad/alpine-oraclejdk8:slim
|
|
||||||
volume /tmp
|
|
||||||
COPY target/exam-api.jar app.jar
|
|
||||||
ENTRYPOINT ["java","-jar","/app.jar"]
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ public class ExamApplication implements WebMvcConfigurer {
|
||||||
|
|
||||||
log.info("\n----------------------------------------------------------\n\t" +
|
log.info("\n----------------------------------------------------------\n\t" +
|
||||||
"系统启动成功,访问路径如下:\n\t" +
|
"系统启动成功,访问路径如下:\n\t" +
|
||||||
"本地路径: \t\thttp://localhost:" + port + path + "/\n\t" +
|
"本地路径: \t\thttp://127.0.0.1:" + port + path + "/\n\t" +
|
||||||
"网络地址: \thttp://" + ip + ":" + port + path + "/\n\t" +
|
"网络地址: \thttp://" + ip + ":" + port + path + "/\n\t" +
|
||||||
//"API文档: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
|
"API文档: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
|
||||||
"----------------------------------------------------------");
|
"----------------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.config;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传配置
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "conf.upload")
|
|
||||||
public class UploadConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 访问路径
|
|
||||||
*/
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 物理目录
|
|
||||||
*/
|
|
||||||
private String dir;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.controller;
|
|
||||||
|
|
||||||
|
|
||||||
import com.yx.exam.ability.Constant;
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadReqDTO;
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadRespDTO;
|
|
||||||
import com.yx.exam.ability.upload.service.UploadService;
|
|
||||||
import com.yx.exam.core.api.ApiRest;
|
|
||||||
import com.yx.exam.core.api.controller.BaseController;
|
|
||||||
import io.swagger.annotations.Api;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地文件上传下载请求类
|
|
||||||
* @author chenhaodong
|
|
||||||
*/
|
|
||||||
@Log4j2
|
|
||||||
@Api(tags = {"文件上传"})
|
|
||||||
@RestController
|
|
||||||
public class UploadController extends BaseController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UploadService uploadService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传
|
|
||||||
* @param reqDTO
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@PostMapping("/common/api/file/upload")
|
|
||||||
@ApiOperation(value = "文件上传", notes = "此接口较为特殊,参数都通过表单方式提交,而非JSON")
|
|
||||||
public ApiRest<UploadRespDTO> upload(@ModelAttribute UploadReqDTO reqDTO) {
|
|
||||||
// 上传并返回URL
|
|
||||||
UploadRespDTO respDTO = uploadService.upload(reqDTO);
|
|
||||||
return super.success(respDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 独立文件下载
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
*/
|
|
||||||
@GetMapping(Constant.FILE_PREFIX+"**")
|
|
||||||
@ApiOperation(value = "文件下载", notes = "文件下载")
|
|
||||||
public void download(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
uploadService.download(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.dto;
|
|
||||||
|
|
||||||
|
|
||||||
import com.yx.exam.core.api.dto.BaseDTO;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传请求类
|
|
||||||
* @author chenhaodong
|
|
||||||
* @date 2019-12-26 17:54
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ApiModel(value="文件上传参数", description="文件上传参数")
|
|
||||||
public class UploadReqDTO extends BaseDTO {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "上传文件内容", required=true)
|
|
||||||
private MultipartFile file;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.dto;
|
|
||||||
|
|
||||||
import com.yx.exam.core.api.dto.BaseDTO;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传文件结果
|
|
||||||
* @author chenhaodong
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@ApiModel(value="文件上传响应", description="文件上传响应")
|
|
||||||
public class UploadRespDTO extends BaseDTO {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "上传后的完整的URL地址", required=true)
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.service;
|
|
||||||
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadReqDTO;
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadRespDTO;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 阿里云OSS业务类
|
|
||||||
* @author chenhaodong
|
|
||||||
* @date 2019-07-12 16:45
|
|
||||||
*/
|
|
||||||
public interface UploadService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传
|
|
||||||
* @param reqDTO
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
UploadRespDTO upload(UploadReqDTO reqDTO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下载文件
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
*/
|
|
||||||
void download(HttpServletRequest request, HttpServletResponse response);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.service.impl;
|
|
||||||
|
|
||||||
import com.yx.exam.ability.Constant;
|
|
||||||
import com.yx.exam.ability.upload.config.UploadConfig;
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadReqDTO;
|
|
||||||
import com.yx.exam.ability.upload.dto.UploadRespDTO;
|
|
||||||
import com.yx.exam.ability.upload.service.UploadService;
|
|
||||||
import com.yx.exam.ability.upload.utils.FileUtils;
|
|
||||||
import com.yx.exam.core.exception.ServiceException;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传业务类
|
|
||||||
* @author chenhaodong
|
|
||||||
* @date 2019-07-30 21:02
|
|
||||||
*/
|
|
||||||
@Log4j2
|
|
||||||
@Service
|
|
||||||
public class UploadServiceImpl implements UploadService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UploadConfig conf;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UploadRespDTO upload(UploadReqDTO reqDTO) {
|
|
||||||
|
|
||||||
|
|
||||||
// 文件内容
|
|
||||||
MultipartFile file = reqDTO.getFile();
|
|
||||||
|
|
||||||
// 上传文件夹
|
|
||||||
String fileDir = conf.getDir();
|
|
||||||
|
|
||||||
// 真实物理地址
|
|
||||||
String fullPath;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 新文件
|
|
||||||
String filePath = FileUtils.processPath(file);
|
|
||||||
// 文件保存地址
|
|
||||||
fullPath = fileDir + filePath;
|
|
||||||
// 创建文件夹
|
|
||||||
FileUtils.checkDir(fullPath);
|
|
||||||
// 上传文件
|
|
||||||
FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(fullPath));
|
|
||||||
|
|
||||||
return this.generateResult(filePath);
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new ServiceException("文件上传失败:"+e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
|
|
||||||
// 获取真实的文件路径
|
|
||||||
String filePath = this.getRealPath(request.getRequestURI());
|
|
||||||
|
|
||||||
System.out.println("++++完整路径为:"+filePath);
|
|
||||||
|
|
||||||
try {
|
|
||||||
FileUtils.writeRange(request, response, filePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
response.setStatus(404);
|
|
||||||
log.error("预览文件失败" + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造返回
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private UploadRespDTO generateResult(String fileName) {
|
|
||||||
|
|
||||||
//获取加速域名
|
|
||||||
String domain = conf.getUrl();
|
|
||||||
|
|
||||||
// 返回结果
|
|
||||||
return new UploadRespDTO(domain + fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取真实物理文件地址
|
|
||||||
* @param uri
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getRealPath(String uri){
|
|
||||||
|
|
||||||
String regx = Constant.FILE_PREFIX+"(.*)";
|
|
||||||
|
|
||||||
// 查找全部变量
|
|
||||||
Pattern pattern = Pattern.compile(regx);
|
|
||||||
Matcher m = pattern.matcher(uri);
|
|
||||||
if (m.find()) {
|
|
||||||
String str = m.group(1);
|
|
||||||
return conf.getDir() + str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.utils;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
||||||
import com.yx.exam.core.utils.DateUtils;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件工具类
|
|
||||||
* @author chenhaodong
|
|
||||||
*/
|
|
||||||
public class FileUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 后缀分割符号
|
|
||||||
*/
|
|
||||||
private static final String SUFFIX_SPLIT = ".";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支持以断点的方式输出文件,提供文件在线预览和视频在线播放
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param filePath
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static void writeRange(HttpServletRequest request,
|
|
||||||
HttpServletResponse response, String filePath) throws IOException {
|
|
||||||
|
|
||||||
// 读取文件
|
|
||||||
File file = new File(filePath);
|
|
||||||
|
|
||||||
//只读模式
|
|
||||||
RandomAccessFile randomFile = new RandomAccessFile(file, "r");
|
|
||||||
long contentLength = randomFile.length();
|
|
||||||
String range = request.getHeader("Range");
|
|
||||||
int start = 0, end = 0;
|
|
||||||
if (range != null && range.startsWith("bytes=")) {
|
|
||||||
String[] values = range.split("=")[1].split("-");
|
|
||||||
start = Integer.parseInt(values[0]);
|
|
||||||
if (values.length > 1) {
|
|
||||||
end = Integer.parseInt(values[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int requestSize;
|
|
||||||
if (end != 0 && end > start) {
|
|
||||||
requestSize = end - start + 1;
|
|
||||||
} else {
|
|
||||||
requestSize = Integer.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] buffer = new byte[128];
|
|
||||||
response.setContentType(MediaUtils.getContentType(filePath));
|
|
||||||
response.setHeader("Accept-Ranges", "bytes");
|
|
||||||
response.setHeader("ETag", file.getName());
|
|
||||||
response.setHeader("Last-Modified", new Date().toString());
|
|
||||||
//第一次请求只返回content length来让客户端请求多次实际数据
|
|
||||||
if (range == null) {
|
|
||||||
response.setHeader("Content-length", contentLength + "");
|
|
||||||
} else {
|
|
||||||
//以后的多次以断点续传的方式来返回视频数据
|
|
||||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
|
||||||
long requestStart = 0, requestEnd = 0;
|
|
||||||
String[] ranges = range.split("=");
|
|
||||||
if (ranges.length > 1) {
|
|
||||||
String[] rangeData = ranges[1].split("-");
|
|
||||||
requestStart = Integer.parseInt(rangeData[0]);
|
|
||||||
if (rangeData.length > 1) {
|
|
||||||
requestEnd = Integer.parseInt(rangeData[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long length;
|
|
||||||
if (requestEnd > 0) {
|
|
||||||
length = requestEnd - requestStart + 1;
|
|
||||||
response.setHeader("Content-length", "" + length);
|
|
||||||
response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
|
|
||||||
} else {
|
|
||||||
length = contentLength - requestStart;
|
|
||||||
response.setHeader("Content-length", "" + length);
|
|
||||||
response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1) + "/" + contentLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ServletOutputStream out = response.getOutputStream();
|
|
||||||
int needSize = requestSize;
|
|
||||||
randomFile.seek(start);
|
|
||||||
while (needSize > 0) {
|
|
||||||
int len = randomFile.read(buffer);
|
|
||||||
if (needSize < buffer.length) {
|
|
||||||
out.write(buffer, 0, needSize);
|
|
||||||
} else {
|
|
||||||
out.write(buffer, 0, len);
|
|
||||||
if (len < buffer.length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
needSize -= buffer.length;
|
|
||||||
}
|
|
||||||
randomFile.close();
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重命名文件
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String renameFile(String fileName) {
|
|
||||||
|
|
||||||
//没有后缀名不处理
|
|
||||||
if (!fileName.contains(SUFFIX_SPLIT)) {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
//文件后缀
|
|
||||||
String suffix = fileName.substring(fileName.lastIndexOf("."));
|
|
||||||
|
|
||||||
//以系统时间命名
|
|
||||||
return IdWorker.getIdStr() + suffix;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理新的文件路径,为上传文件预设目录,如:2021/01/01/xxx.jpg,要注意的是,前面没有斜杠
|
|
||||||
* @param file 文件
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String processPath(MultipartFile file){
|
|
||||||
|
|
||||||
// 创建OSSClient实例。
|
|
||||||
String fileName = file.getOriginalFilename();
|
|
||||||
|
|
||||||
// 需要重命名
|
|
||||||
fileName = renameFile(fileName);
|
|
||||||
|
|
||||||
//获得上传的文件夹
|
|
||||||
String dir = DateUtils.formatDate(new Date(), "yyyy/MM/dd/");
|
|
||||||
|
|
||||||
return new StringBuffer(dir).append(fileName).toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理新的文件路径,为上传文件预设目录,如:2021/01/01/xxx.jpg,要注意的是,前面没有斜杠
|
|
||||||
* @param fileName 文件
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String processPath(String fileName){
|
|
||||||
|
|
||||||
// 需要重命名
|
|
||||||
fileName = renameFile(fileName);
|
|
||||||
|
|
||||||
//获得上传的文件夹
|
|
||||||
String dir = DateUtils.formatDate(new Date(), "yyyy/MM/dd/");
|
|
||||||
|
|
||||||
return new StringBuffer(dir).append(fileName).toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查文件夹是否存在,不存在则创建
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static void checkDir(String fileName){
|
|
||||||
int index = fileName.lastIndexOf("/");
|
|
||||||
if(index == -1){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(fileName.substring(0,index));
|
|
||||||
if(!file.exists()){
|
|
||||||
file.mkdirs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package com.yx.exam.ability.upload.utils;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 媒体工具,判断媒体类型
|
|
||||||
* @author chenhaodong
|
|
||||||
* @date 2019-11-14 16:21
|
|
||||||
*/
|
|
||||||
public class MediaUtils {
|
|
||||||
|
|
||||||
public static final Map<String, String> MEDIA_MAP = new HashMap(){
|
|
||||||
{
|
|
||||||
|
|
||||||
//本来是pdf的
|
|
||||||
put(".pdf", "application/pdf");
|
|
||||||
|
|
||||||
//视频
|
|
||||||
put(".mp4", "video,video/mp4");
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得文件类型
|
|
||||||
* @param filePath
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getContentType(String filePath){
|
|
||||||
|
|
||||||
if(!StringUtils.isBlank(filePath)
|
|
||||||
&& filePath.indexOf(".")!=-1) {
|
|
||||||
|
|
||||||
// 后缀转换成小写
|
|
||||||
String suffix = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
||||||
|
|
||||||
if (MEDIA_MAP.containsKey(suffix)) {
|
|
||||||
return MEDIA_MAP.get(suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "application/octet-stream";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -44,7 +44,10 @@ public class QueryInterceptor extends PaginationInterceptor implements Intercept
|
||||||
public Object intercept(Invocation invocation) throws Throwable {
|
public Object intercept(Invocation invocation) throws Throwable {
|
||||||
|
|
||||||
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
|
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
|
||||||
|
|
||||||
|
//通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性
|
||||||
MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
|
MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
|
||||||
|
//先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
|
||||||
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
||||||
|
|
||||||
//sql语句类型
|
//sql语句类型
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ public class SwaggerConfig {
|
||||||
public Docket examApi() {
|
public Docket examApi() {
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
.groupName("考试模块接口")
|
.groupName("系统模块接口")
|
||||||
.select()
|
.select()
|
||||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||||
.paths(PathSelectors.ant("/exam/api/**"))
|
.paths(PathSelectors.ant("/exam/api/**"))
|
||||||
|
|
@ -45,9 +45,9 @@ public class SwaggerConfig {
|
||||||
|
|
||||||
|
|
||||||
private ApiInfo apiInfo() {
|
private ApiInfo apiInfo() {
|
||||||
return new ApiInfoBuilder().title("考试系统接口")
|
return new ApiInfoBuilder().title("系统接口")
|
||||||
.description("考试系统接口")
|
.description("系统接口")
|
||||||
.contact(new Contact("Van", "https://exam.yfhl.net", "18365918@qq.com"))
|
.contact(new Contact("Van", "https://exam.yfhl.net", "755141280@qq.com"))
|
||||||
.version("1.0.0")
|
.version("1.0.0")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package com.yx.exam.core.enums;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 组卷方式
|
|
||||||
* @author chenhaodong
|
|
||||||
*/
|
|
||||||
public interface JoinType {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 题库组题
|
|
||||||
*/
|
|
||||||
Integer REPO_JOIN = 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package com.yx.exam.core.enums;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开放方式
|
|
||||||
* @author chenhaodong
|
|
||||||
*/
|
|
||||||
public interface OpenType {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 完全开放
|
|
||||||
*/
|
|
||||||
Integer OPEN = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门开放
|
|
||||||
*/
|
|
||||||
Integer DEPT_OPEN = 2;
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.yx.exam.modules;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用常量
|
* 通用常量
|
||||||
* @author bool
|
* @author chd
|
||||||
*/
|
*/
|
||||||
public class Constant {
|
public class Constant {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
* 通用配置控制器
|
* 通用配置控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
@Api(tags={"通用配置"})
|
@Api(tags={"通用配置"})
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import java.io.Serializable;
|
||||||
* 通用配置请求类
|
* 通用配置请求类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import lombok.Data;
|
||||||
* 通用配置实体类
|
* 通用配置实体类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import com.yx.exam.modules.config.entity.SysConfig;
|
||||||
* 通用配置Mapper
|
* 通用配置Mapper
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
public interface SysConfigMapper extends BaseMapper<SysConfig> {
|
public interface SysConfigMapper extends BaseMapper<SysConfig> {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import com.yx.exam.modules.config.entity.SysConfig;
|
||||||
* 通用配置业务类
|
* 通用配置业务类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
public interface SysConfigService extends IService<SysConfig> {
|
public interface SysConfigService extends IService<SysConfig> {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.stereotype.Service;
|
||||||
* 语言设置 服务实现类
|
* 语言设置 服务实现类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-17 09:12
|
* @since 2020-04-17 09:12
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import java.util.List;
|
||||||
* 部门信息控制器
|
* 部门信息控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
@Api(tags={"部门信息"})
|
@Api(tags={"部门信息"})
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import java.io.Serializable;
|
||||||
* 部门信息数据传输类
|
* 部门信息数据传输类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import java.io.Serializable;
|
||||||
* 部门排序请求类
|
* 部门排序请求类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-03-14 10:37
|
* @since 2020-03-14 10:37
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.List;
|
||||||
* 部门树结构响应类
|
* 部门树结构响应类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import lombok.Data;
|
||||||
* 部门信息实体类
|
* 部门信息实体类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.apache.ibatis.annotations.Param;
|
||||||
* 部门信息Mapper
|
* 部门信息Mapper
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
public interface SysDepartMapper extends BaseMapper<SysDepart> {
|
public interface SysDepartMapper extends BaseMapper<SysDepart> {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import java.util.List;
|
||||||
* 部门信息业务类
|
* 部门信息业务类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
public interface SysDepartService extends IService<SysDepart> {
|
public interface SysDepartService extends IService<SysDepart> {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import java.util.Map;
|
||||||
* 部门信息业务实现类
|
* 部门信息业务实现类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-09-02 17:25
|
* @since 2020-09-02 17:25
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import javax.annotation.Resource;
|
||||||
* 码值数据表 前端控制器
|
* 码值数据表 前端控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author mawuhui
|
* @author chenhaodong
|
||||||
* @since 2022-11-24
|
* @since 2022-11-24
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import org.apache.ibatis.annotations.Param;
|
||||||
* 机主信息Mapper
|
* 机主信息Mapper
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-08-22 13:46
|
* @since 2020-08-22 13:46
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import org.apache.shiro.SecurityUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户静态工具类
|
* 用户静态工具类
|
||||||
* @author bool
|
* @author chd
|
||||||
*/
|
*/
|
||||||
public class UserUtils {
|
public class UserUtils {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import java.util.List;
|
||||||
* 管理用户控制器
|
* 管理用户控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
@Api(tags = {"管理用户"})
|
@Api(tags = {"管理用户"})
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.List;
|
||||||
* 管理用户控制器
|
* 管理用户控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
@Api(tags = {"管理用户"})
|
@Api(tags = {"管理用户"})
|
||||||
|
|
@ -50,11 +50,11 @@ public class SysUserController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录
|
* 用户登出
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
@ApiOperation(value = "用户登录")
|
@ApiOperation(value = "用户登出")
|
||||||
@RequestMapping(value = "/logout", method = {RequestMethod.POST})
|
@RequestMapping(value = "/logout", method = {RequestMethod.POST})
|
||||||
public ApiRest logout(HttpServletRequest request) {
|
public ApiRest logout(HttpServletRequest request) {
|
||||||
String token = request.getHeader("token");
|
String token = request.getHeader("token");
|
||||||
|
|
@ -152,7 +152,7 @@ public class SysUserController extends BaseController {
|
||||||
* 保存或修改系统用户
|
* 保存或修改系统用户
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ApiOperation(value = "学员注册")
|
@ApiOperation(value = "用户注册")
|
||||||
@RequestMapping(value = "/reg", method = {RequestMethod.POST})
|
@RequestMapping(value = "/reg", method = {RequestMethod.POST})
|
||||||
public ApiRest<SysUserLoginDTO> reg(@RequestBody SysUserDTO reqDTO) {
|
public ApiRest<SysUserLoginDTO> reg(@RequestBody SysUserDTO reqDTO) {
|
||||||
SysUserLoginDTO respDTO = baseService.reg(reqDTO);
|
SysUserLoginDTO respDTO = baseService.reg(reqDTO);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import java.util.Date;
|
||||||
* 管理用户实体类
|
* 管理用户实体类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import com.yx.exam.modules.user.entity.SysRole;
|
||||||
* 角色业务类
|
* 角色业务类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
public interface SysRoleService extends IService<SysRole> {
|
public interface SysRoleService extends IService<SysRole> {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||||
* 用户角色业务类
|
* 用户角色业务类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
public interface SysUserRoleService extends IService<SysUserRole> {
|
public interface SysUserRoleService extends IService<SysUserRole> {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import java.util.List;
|
||||||
* 管理用户业务类
|
* 管理用户业务类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
public interface SysUserService extends IService<SysUser> {
|
public interface SysUserService extends IService<SysUser> {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import java.util.List;
|
||||||
* 语言设置 服务实现类
|
* 语言设置 服务实现类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import java.util.List;
|
||||||
* 语言设置 服务实现类
|
* 语言设置 服务实现类
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author 聪明笨狗
|
* @author chd
|
||||||
* @since 2020-04-13 16:57
|
* @since 2020-04-13 16:57
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# 开发环境配置文件
|
# 开发环境配置文件
|
||||||
spring:
|
spring:
|
||||||
# 数据库配置
|
# 数据库配置
|
||||||
datasource:
|
datasource:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: yf-exam-lite
|
name: chdbs
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: dev
|
||||||
main:
|
main:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "yf-exam-lite",
|
"name": "chdbs",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "陈昊东毕设",
|
"description": "陈昊东毕设",
|
||||||
"author": "haodongchen@aliyun.com",
|
"author": "haodongchen@aliyun.com",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { post } from '@/utils/request'
|
||||||
|
|
||||||
|
export function sjkctj() {
|
||||||
|
return post('/tongji/api/sjxxtj', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -17,7 +17,6 @@ import './permission' // permission control
|
||||||
import './utils/error-log' // error log
|
import './utils/error-log' // error log
|
||||||
|
|
||||||
import * as filters from './filters'
|
import * as filters from './filters'
|
||||||
|
|
||||||
// Element UI
|
// Element UI
|
||||||
Vue.use(Element, {
|
Vue.use(Element, {
|
||||||
size: Cookies.get('size') || 'medium' // set element-ui default size
|
size: Cookies.get('size') || 'medium' // set element-ui default size
|
||||||
|
|
|
||||||
|
|
@ -166,15 +166,6 @@ export const asyncRoutes = [
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/*{
|
|
||||||
path: 'bysxxgl',
|
|
||||||
component: () => import('@/views/sys/bysxxgl'),
|
|
||||||
name: 'SysBysxxgl',
|
|
||||||
meta: {
|
|
||||||
title: '毕业生信息管理',
|
|
||||||
icon: 'admin'
|
|
||||||
}
|
|
||||||
},*/
|
|
||||||
{
|
{
|
||||||
path: 'bookgl',
|
path: 'bookgl',
|
||||||
component: () => import('@/views/sys/bookgl'),
|
component: () => import('@/views/sys/bookgl'),
|
||||||
|
|
@ -228,8 +219,7 @@ export const asyncRoutes = [
|
||||||
title: '留言管理',
|
title: '留言管理',
|
||||||
icon: 'admin'
|
icon: 'admin'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
<div>权限控制:基于Shiro和JWT开发的权限控制功能。</div>
|
<div>权限控制:基于Shiro和JWT开发的权限控制功能。</div>
|
||||||
<div>基础功能:系统配置、用户管理、部门管理、角色管理等。</div>
|
<div>基础功能:系统配置、用户管理、部门管理、角色管理等。</div>
|
||||||
<div>图书管理:图书的信息管理,借还流程的完善</div>
|
<div>图书管理:图书的信息管理,借还流程的完善</div>
|
||||||
<div>人员权限:暂时设置管理员与教师和学生三个角色</div>
|
<div>人员权限:暂时设置管理员和学生两个角色</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
<el-table-column align="center" label="操作">
|
<el-table-column align="center" label="操作">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<a style="color: #1890ff" @click="handleUpdate(scope.row)">
|
<a style="color: #1890ff" @click="handleUpdate(scope.row)">
|
||||||
<el-button link type="primary" size="small"
|
<el-button link type="primary" size="small" v-if="0===scope.row.bState"
|
||||||
>借书
|
>借书
|
||||||
</el-button>
|
</el-button>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue