Binary file not shown.
@ -0,0 +1,214 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.yfhl</groupId>
|
||||
<artifactId>exam-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0</version>
|
||||
<name>exam-api</name>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.4.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<fastjson.version>2.0.24</fastjson.version>
|
||||
<oss.version>3.7.0</oss.version>
|
||||
<aliyun.sdk.version>4.1.1</aliyun.sdk.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<dozer.version>5.5.1</dozer.version>
|
||||
<apache.commons.version>3.8</apache.commons.version>
|
||||
<mysql.driver.version>8.0.11</mysql.driver.version>
|
||||
<mybatis-plus.version>3.4.1</mybatis-plus.version>
|
||||
<lombok.version>1.18.4</lombok.version>
|
||||
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
|
||||
<alicloud.version>2.1.1.RELEASE</alicloud.version>
|
||||
<poi.version>3.9</poi.version>
|
||||
<log4j2.version>2.17.2</log4j2.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- WEB支持 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--spring quartz依赖-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sf.dozer</groupId>
|
||||
<artifactId>dozer</artifactId>
|
||||
<version>${dozer.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.driver.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>swagger-bootstrap-ui</artifactId>
|
||||
<version>1.9.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- poi office -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--JWT-->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring-boot-starter</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.2.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>${project.name}</finalName>
|
||||
<defaultGoal>compile</defaultGoal>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,15 @@
|
||||
package com.yf.exam.ability;
|
||||
|
||||
|
||||
/**
|
||||
* 通用常量
|
||||
* @author bool
|
||||
*/
|
||||
public class Constant {
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传路径
|
||||
*/
|
||||
public static final String FILE_PREFIX = "/upload/file/";
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.yf.exam.ability.job.enums;
|
||||
|
||||
/**
|
||||
* 任务分组
|
||||
* @author van
|
||||
*/
|
||||
public interface JobGroup {
|
||||
|
||||
/**
|
||||
* 系统任务
|
||||
*/
|
||||
String SYSTEM = "system";
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.yf.exam.ability.job.enums;
|
||||
|
||||
/**
|
||||
* 任务前缀
|
||||
* @author bool
|
||||
*/
|
||||
public interface JobPrefix {
|
||||
|
||||
/**
|
||||
* 强制交卷的
|
||||
*/
|
||||
String BREAK_EXAM = "break_exam_";
|
||||
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package com.yf.exam.ability.job.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.yf.exam.ability.job.enums.JobGroup;
|
||||
import com.yf.exam.ability.job.service.JobService;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.quartz.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author bool
|
||||
*/
|
||||
@Log4j2
|
||||
@Service
|
||||
public class JobServiceImpl implements JobService {
|
||||
|
||||
/**
|
||||
* Quartz定时任务核心的功能实现类
|
||||
*/
|
||||
private Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* 注入
|
||||
* @param schedulerFactoryBean
|
||||
*/
|
||||
public JobServiceImpl(@Autowired SchedulerFactoryBean schedulerFactoryBean) {
|
||||
scheduler = schedulerFactoryBean.getScheduler();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addCronJob(Class jobClass, String jobName, String cron, String data) {
|
||||
|
||||
|
||||
String jobGroup = JobGroup.SYSTEM;
|
||||
|
||||
// 自动命名
|
||||
if(StringUtils.isEmpty(jobName)){
|
||||
jobName = jobClass.getSimpleName().toUpperCase() + "_"+IdWorker.getIdStr();
|
||||
}
|
||||
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
|
||||
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
if (jobDetail != null) {
|
||||
log.info("++++++++++任务:{} 已存在", jobName);
|
||||
this.deleteJob(jobName, jobGroup);
|
||||
}
|
||||
|
||||
log.info("++++++++++构建任务:{},{},{},{},{} ", jobClass.toString(), jobName, jobGroup, cron, data);
|
||||
|
||||
//构建job信息
|
||||
jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
|
||||
//用JopDataMap来传递数据
|
||||
jobDetail.getJobDataMap().put(TASK_DATA, data);
|
||||
|
||||
//按新的cronExpression表达式构建一个新的trigger
|
||||
Trigger trigger = null;
|
||||
|
||||
// 有表达式的按表达式
|
||||
if(!StringUtils.isEmpty(cron)){
|
||||
log.info("+++++表达式执行:"+ JSON.toJSONString(jobDetail));
|
||||
//表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
|
||||
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).withSchedule(scheduleBuilder).build();
|
||||
}else{
|
||||
// 无表达式则立即执行
|
||||
log.info("+++++立即执行:"+ JSON.toJSONString(jobDetail));
|
||||
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).startNow().build();
|
||||
}
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addCronJob(Class jobClass, String jobName, String data) {
|
||||
// 立即执行任务
|
||||
this.addCronJob(jobClass, jobName, null, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pauseJob(String jobName, String jobGroup) {
|
||||
try {
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
scheduler.pauseTrigger(triggerKey);
|
||||
log.info("++++++++++暂停任务:{}", jobName);
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeJob(String jobName, String jobGroup) {
|
||||
try {
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
scheduler.resumeTrigger(triggerKey);
|
||||
log.info("++++++++++重启任务:{}", jobName);
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteJob(String jobName, String jobGroup) {
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(jobName,jobGroup);
|
||||
scheduler.deleteJob(jobKey);
|
||||
log.info("++++++++++删除任务:{}", jobKey);
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.yf.exam.ability.shiro.jwt;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
/**
|
||||
* @author bool
|
||||
*/
|
||||
@Data
|
||||
public class JwtToken implements AuthenticationToken {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* JWT的字符token
|
||||
*/
|
||||
private String token;
|
||||
|
||||
|
||||
public JwtToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.yf.exam.ability.upload.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传配置
|
||||
* @author van
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "conf.upload")
|
||||
public class UploadConfig {
|
||||
|
||||
/**
|
||||
* 访问路径
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 物理目录
|
||||
*/
|
||||
private String dir;
|
||||
|
||||
/**
|
||||
* 允许的后缀
|
||||
*/
|
||||
private String [] allowExtensions;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.yf.exam.ability.upload.dto;
|
||||
|
||||
|
||||
import com.yf.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
|
||||
* @date 2019-12-26 17:54
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value="文件上传参数", description="文件上传参数")
|
||||
public class UploadReqDTO extends BaseDTO {
|
||||
|
||||
@ApiModelProperty(value = "上传文件内容", required=true)
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.yf.exam.ability.upload.dto;
|
||||
|
||||
import com.yf.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 bool
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(value="文件上传响应", description="文件上传响应")
|
||||
public class UploadRespDTO extends BaseDTO {
|
||||
|
||||
@ApiModelProperty(value = "上传后的完整的URL地址", required=true)
|
||||
private String url;
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.yf.exam.ability.upload.service;
|
||||
|
||||
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
||||
import com.yf.exam.ability.upload.dto.UploadRespDTO;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 阿里云OSS业务类
|
||||
* @author bool
|
||||
* @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);
|
||||
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
package com.yf.exam.ability.upload.service.impl;
|
||||
|
||||
import com.yf.exam.ability.Constant;
|
||||
import com.yf.exam.ability.upload.config.UploadConfig;
|
||||
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
||||
import com.yf.exam.ability.upload.dto.UploadRespDTO;
|
||||
import com.yf.exam.ability.upload.service.UploadService;
|
||||
import com.yf.exam.ability.upload.utils.FileUtils;
|
||||
import com.yf.exam.core.exception.ServiceException;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
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.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传业务类
|
||||
* @author bool
|
||||
* @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();
|
||||
|
||||
// 验证文件后缀
|
||||
boolean allow = FilenameUtils.isExtension(file.getOriginalFilename(), conf.getAllowExtensions());
|
||||
if(!allow){
|
||||
throw new ServiceException("文件类型不允许上传!");
|
||||
}
|
||||
// 上传文件夹
|
||||
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());
|
||||
|
||||
// 处理中文问题
|
||||
try {
|
||||
filePath = URLDecoder.decode(filePath, "utf-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package com.yf.exam.aspect.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlCommandType;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.plugin.Intercepts;
|
||||
import org.apache.ibatis.plugin.Invocation;
|
||||
import org.apache.ibatis.plugin.Plugin;
|
||||
import org.apache.ibatis.plugin.Signature;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 自动给创建时间个更新时间加值
|
||||
* @author bool
|
||||
*/
|
||||
@Intercepts(value = {@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
|
||||
public class UpdateInterceptor extends AbstractSqlParserHandler implements Interceptor {
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private static final String CREATE_TIME = "createTime";
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private static final String UPDATE_TIME = "updateTime";
|
||||
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
|
||||
// SQL操作命令
|
||||
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
|
||||
// 获取新增或修改的对象参数
|
||||
Object parameter = invocation.getArgs()[1];
|
||||
// 获取对象中所有的私有成员变量(对应表字段)
|
||||
Field[] declaredFields = parameter.getClass().getDeclaredFields();
|
||||
if (parameter.getClass().getSuperclass() != null) {
|
||||
Field[] superField = parameter.getClass().getSuperclass().getDeclaredFields();
|
||||
declaredFields = ArrayUtils.addAll(declaredFields, superField);
|
||||
}
|
||||
|
||||
String fieldName = null;
|
||||
for (Field field : declaredFields) {
|
||||
fieldName = field.getName();
|
||||
if (Objects.equals(CREATE_TIME, fieldName)) {
|
||||
if (SqlCommandType.INSERT.equals(sqlCommandType)) {
|
||||
field.setAccessible(true);
|
||||
field.set(parameter, new Timestamp(System.currentTimeMillis()));
|
||||
}
|
||||
}
|
||||
if (Objects.equals(UPDATE_TIME, fieldName)) {
|
||||
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
|
||||
field.setAccessible(true);
|
||||
field.set(parameter, new Timestamp(System.currentTimeMillis()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object plugin(Object target) {
|
||||
if (target instanceof Executor) {
|
||||
return Plugin.wrap(target, this);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.yf.exam.aspect.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yf.exam.core.api.ApiError;
|
||||
import com.yf.exam.core.api.ApiRest;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* 注入工具类
|
||||
* @author bool
|
||||
* @date 2019-07-17 09:32
|
||||
*/
|
||||
@Log4j2
|
||||
@Component
|
||||
public class InjectUtils {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 给对象字段赋值
|
||||
*
|
||||
* @param object 赋值的对象
|
||||
* @param value 值
|
||||
* @param fields 字段
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
public void setValue(Object object, Object value, String... fields) throws Exception {
|
||||
|
||||
//设置同类的属性
|
||||
for (String fieldName : fields) {
|
||||
|
||||
//获取当前
|
||||
Field field = this.getFiled(object.getClass(), fieldName);
|
||||
if(field == null){
|
||||
continue;
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段名对应的字段
|
||||
*
|
||||
* @param clazz 目标类
|
||||
* @param fieldName 字段名
|
||||
*/
|
||||
private Field getFiled(Class clazz, String fieldName) {
|
||||
|
||||
System.out.println("注入的类:"+clazz.toString());
|
||||
|
||||
//是否具有包含关系
|
||||
try {
|
||||
//获取当前类的属性
|
||||
return clazz.getDeclaredField(fieldName);
|
||||
}catch (Exception e){
|
||||
|
||||
log.error(clazz.toString() + ": not exist field, try superclass " + fieldName);
|
||||
|
||||
//如果为空且存在父类,则往上找
|
||||
if(clazz.getSuperclass()!=null){
|
||||
return this.getFiled(clazz.getSuperclass(), fieldName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打印结果返回
|
||||
* @param response
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void restError(HttpServletResponse response) {
|
||||
|
||||
try {
|
||||
|
||||
//固定错误
|
||||
ApiRest apiRest = new ApiRest(ApiError.ERROR_10010002);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write(JSON.toJSONString(apiRest));
|
||||
response.getWriter().close();
|
||||
|
||||
}catch (IOException e){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.yf.exam.config;
|
||||
|
||||
import org.springframework.boot.web.servlet.MultipartConfigFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
|
||||
/**
|
||||
* 文件上传配置
|
||||
* @author bool
|
||||
* @date 2019-07-29 16:23
|
||||
*/
|
||||
@Configuration
|
||||
public class MultipartConfig {
|
||||
|
||||
@Bean
|
||||
public MultipartConfigElement multipartConfigElement() {
|
||||
MultipartConfigFactory factory = new MultipartConfigFactory();
|
||||
// 单个数据大小
|
||||
factory.setMaxFileSize(DataSize.ofMegabytes(5000L));
|
||||
/// 总上传数据大小
|
||||
factory.setMaxRequestSize(DataSize.ofMegabytes(5000L));
|
||||
return factory.createMultipartConfig();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.yf.exam.config;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 任务调度配置
|
||||
* @author bool
|
||||
*/
|
||||
@Log4j2
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
public class ScheduledConfig implements SchedulingConfigurer, AsyncConfigurer {
|
||||
|
||||
/**
|
||||
* 定时任务使用的线程池
|
||||
* @return
|
||||
*/
|
||||
@Bean(destroyMethod = "shutdown", name = "taskScheduler")
|
||||
public ThreadPoolTaskScheduler taskScheduler(){
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(10);
|
||||
scheduler.setThreadNamePrefix("task-");
|
||||
scheduler.setAwaitTerminationSeconds(600);
|
||||
scheduler.setWaitForTasksToCompleteOnShutdown(true);
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步任务执行线程池
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "asyncExecutor")
|
||||
public ThreadPoolTaskExecutor asyncExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(10);
|
||||
executor.setQueueCapacity(1000);
|
||||
executor.setKeepAliveSeconds(600);
|
||||
executor.setMaxPoolSize(20);
|
||||
executor.setThreadNamePrefix("taskExecutor-");
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
|
||||
ThreadPoolTaskScheduler taskScheduler = taskScheduler();
|
||||
scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
return asyncExecutor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return (throwable, method, objects) -> {
|
||||
log.error("异步任务执行出现异常, message {}, emthod {}, params {}", throwable, method, objects);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.yf.exam.config;
|
||||
|
||||
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.ApiKey;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.service.SecurityScheme;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Swagger配置
|
||||
* @author bool
|
||||
* @date 2020/8/19 20:53
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
@EnableSwaggerBootstrapUI
|
||||
@ConfigurationProperties(prefix = "swagger")
|
||||
public class SwaggerConfig {
|
||||
|
||||
|
||||
@Bean
|
||||
public Docket examApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.groupName("考试模块接口")
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
.paths(PathSelectors.ant("/exam/api/**"))
|
||||
.build()
|
||||
.securitySchemes(Collections.singletonList(securityScheme()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder().title("考试系统接口")
|
||||
.description("考试系统接口")
|
||||
.contact(new Contact("Van", "https://exam.yfhl.net", "18365918@qq.com"))
|
||||
.version("1.0.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 授权头部
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
SecurityScheme securityScheme() {
|
||||
return new ApiKey("token", "token", "header");
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue