From ffc991c7e76f8f8f5f66c68565a6be5bbe803102 Mon Sep 17 00:00:00 2001 From: haown <454902499@qq.com> Date: Fri, 29 Aug 2025 15:34:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exam-admin/pom.xml | 69 +++++++++++++------ .../java/com/yf/exam/ExamApplication.java | 7 +- .../java/com/yf/exam/config/CorsConfig.java | 10 ++- .../config/FastJson2JsonRedisSerializer.java | 42 +++++++++++ .../java/com/yf/exam/config/RedisConfig.java | 65 +++++++++++++++++ .../yf/exam/core/utils/excel/ExportExcel.java | 27 ++++---- .../yf/exam/core/utils/excel/ImportExcel.java | 23 +++---- .../core/utils/excel/fieldtype/ListType.java | 3 +- .../impl/ExamRegistrationServiceImpl.java | 4 ++ .../paper/service/impl/PaperServiceImpl.java | 38 +++++----- .../modules/qu/controller/QuController.java | 14 ++-- .../impl/PaymentInfoTaskServiceImpl.java | 2 +- .../src/main/resources/application-dev.yml | 6 +- exam-admin/src/main/resources/application.yml | 47 +++++++------ 14 files changed, 245 insertions(+), 112 deletions(-) create mode 100644 exam-admin/src/main/java/com/yf/exam/config/FastJson2JsonRedisSerializer.java create mode 100644 exam-admin/src/main/java/com/yf/exam/config/RedisConfig.java diff --git a/exam-admin/pom.xml b/exam-admin/pom.xml index 9c8d09c..93530c7 100644 --- a/exam-admin/pom.xml +++ b/exam-admin/pom.xml @@ -33,7 +33,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.4.RELEASE + 2.5.14 @@ -41,6 +41,12 @@ org.springframework.boot spring-boot-starter-web + @@ -108,24 +114,28 @@ 2.1.1 - - io.springfox - springfox-swagger2 - ${swagger.version} - - - org.slf4j - slf4j-api - - - - - - com.github.xiaoymin - swagger-bootstrap-ui - 1.9.3 - + + io.springfox + springfox-swagger2 + ${swagger.version} + + + org.slf4j + slf4j-api + + + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.3 + + + org.apache.commons + commons-compress + 1.27.1 + org.apache.poi @@ -159,6 +169,18 @@ 1.8.0 + + javax.servlet + javax.servlet-api + 4.0.1 + + + + javax.validation + validation-api + 2.0.1.Final + + com.alibaba @@ -183,6 +205,13 @@ org.springframework.boot spring-boot-starter-data-redis + 2.5.15 + + + + org.apache.commons + commons-pool2 + 2.11.1 @@ -194,7 +223,6 @@ org.springframework.integration spring-integration-redis - 5.5.12 @@ -223,7 +251,8 @@ org.springframework.boot spring-boot-maven-plugin - + 2.1.1.RELEASE + repackage diff --git a/exam-admin/src/main/java/com/yf/exam/ExamApplication.java b/exam-admin/src/main/java/com/yf/exam/ExamApplication.java index 34f485d..fc72a2c 100644 --- a/exam-admin/src/main/java/com/yf/exam/ExamApplication.java +++ b/exam-admin/src/main/java/com/yf/exam/ExamApplication.java @@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** - * 云帆在线考试系统 + * 新医路考试系统 * @author bool * @email 18365918@qq.com * @date 2020-03-04 19:41 @@ -35,10 +35,7 @@ public class ExamApplication implements WebMvcConfigurer { log.info("\n----------------------------------------------------------\n\t" + - "云帆考试系统启动成功,访问路径如下:\n\t" + - "本地路径: \t\thttp://localhost:" + port + path + "/\n\t" + - "网络地址: \thttp://" + ip + ":" + port + path + "/\n\t" + - "API文档: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" + + "新医路考试系统启动成功\n\t" + "----------------------------------------------------------"); } diff --git a/exam-admin/src/main/java/com/yf/exam/config/CorsConfig.java b/exam-admin/src/main/java/com/yf/exam/config/CorsConfig.java index e88cb08..0be0eb5 100644 --- a/exam-admin/src/main/java/com/yf/exam/config/CorsConfig.java +++ b/exam-admin/src/main/java/com/yf/exam/config/CorsConfig.java @@ -23,9 +23,13 @@ public class CorsConfig { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); - config.addAllowedOrigin(CorsConfiguration.ALL); - config.addAllowedHeader(CorsConfiguration.ALL); - config.addAllowedMethod(CorsConfiguration.ALL); + // 设置访问源地址 + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); diff --git a/exam-admin/src/main/java/com/yf/exam/config/FastJson2JsonRedisSerializer.java b/exam-admin/src/main/java/com/yf/exam/config/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..6d729e4 --- /dev/null +++ b/exam-admin/src/main/java/com/yf/exam/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,42 @@ +package com.yf.exam.config; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +/** + * Redis使用FastJson序列化 + * + * @author xinyilu + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + + private final Class clazz; + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} diff --git a/exam-admin/src/main/java/com/yf/exam/config/RedisConfig.java b/exam-admin/src/main/java/com/yf/exam/config/RedisConfig.java new file mode 100644 index 0000000..e4375c8 --- /dev/null +++ b/exam-admin/src/main/java/com/yf/exam/config/RedisConfig.java @@ -0,0 +1,65 @@ +package com.yf.exam.config; + +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis配置 + * + * @author xinyilu + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + @Bean + @SuppressWarnings(value = {"unchecked", "rawtypes"}) + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + + // Hash的key也采用StringRedisSerializer的序列化方式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } + + @Bean + public DefaultRedisScript limitScript() { + DefaultRedisScript redisScript = new DefaultRedisScript<>(); + redisScript.setScriptText(limitScriptText()); + redisScript.setResultType(Long.class); + return redisScript; + } + + /** + * 限流脚本 + */ + private String limitScriptText() { + return "local key = KEYS[1]\n" + + "local count = tonumber(ARGV[1])\n" + + "local time = tonumber(ARGV[2])\n" + + "local current = redis.call('get', key);\n" + + "if current and tonumber(current) > count then\n" + + " return tonumber(current);\n" + + "end\n" + + "current = redis.call('incr', key)\n" + + "if tonumber(current) == 1 then\n" + + " redis.call('expire', key, time)\n" + + "end\n" + + "return tonumber(current);"; + } +} diff --git a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ExportExcel.java b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ExportExcel.java index d98b557..5d8b740 100644 --- a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ExportExcel.java +++ b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ExportExcel.java @@ -3,9 +3,21 @@ */ package com.yf.exam.core.utils.excel; -import com.google.common.collect.Lists; import com.yf.exam.core.utils.Reflections; import com.yf.exam.core.utils.excel.annotation.ExcelField; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -23,19 +35,6 @@ import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * 导出Excel文件(导出“XLSX”格式,支持大数据量导出 @see org.apache.poi.ss.SpreadsheetVersion) * @author jeeplus diff --git a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ImportExcel.java b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ImportExcel.java index fca308a..41350b7 100644 --- a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ImportExcel.java +++ b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/ImportExcel.java @@ -3,9 +3,19 @@ */ package com.yf.exam.core.utils.excel; -import com.google.common.collect.Lists; import com.yf.exam.core.utils.Reflections; import com.yf.exam.core.utils.excel.annotation.ExcelField; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -19,17 +29,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - /** * 导入Excel文件(支持“XLS”和“XLSX”格式) * @author jeeplus diff --git a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/fieldtype/ListType.java b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/fieldtype/ListType.java index 9369888..d7c5411 100644 --- a/exam-admin/src/main/java/com/yf/exam/core/utils/excel/fieldtype/ListType.java +++ b/exam-admin/src/main/java/com/yf/exam/core/utils/excel/fieldtype/ListType.java @@ -3,10 +3,9 @@ */ package com.yf.exam.core.utils.excel.fieldtype; -import com.google.common.collect.Lists; import com.yf.exam.core.utils.StringUtils; - import java.util.List; +import org.apache.commons.compress.utils.Lists; /** * 字段类型转换 diff --git a/exam-admin/src/main/java/com/yf/exam/modules/exam/service/impl/ExamRegistrationServiceImpl.java b/exam-admin/src/main/java/com/yf/exam/modules/exam/service/impl/ExamRegistrationServiceImpl.java index 7c225cf..73a7dd3 100644 --- a/exam-admin/src/main/java/com/yf/exam/modules/exam/service/impl/ExamRegistrationServiceImpl.java +++ b/exam-admin/src/main/java/com/yf/exam/modules/exam/service/impl/ExamRegistrationServiceImpl.java @@ -130,6 +130,10 @@ public class ExamRegistrationServiceImpl extends ServiceImpl implements PaperService { - @Autowired + @Resource private SysUserService sysUserService; - @Autowired + @Resource private ExamService examService; - @Autowired + @Resource private QuService quService; - @Autowired + @Resource private QuAnswerService quAnswerService; - @Autowired - private PaperService paperService; + @Resource + private PaperMapper paperMapper; - @Autowired + @Resource private PaperQuService paperQuService; - @Autowired + @Resource private PaperQuAnswerService paperQuAnswerService; - @Autowired + @Resource private UserBookService userBookService; - @Autowired + @Resource private ExamRepoService examRepoService; - @Autowired + @Resource private UserExamService userExamService; - @Autowired + @Resource private JobService jobService; - @Autowired + @Resource private ExamRegistrationService examRegistrationService; /** @@ -174,7 +174,7 @@ public class PaperServiceImpl extends ServiceImpl implements ExamDetailRespDTO respDTO = new ExamDetailRespDTO(); // 试题基本信息 - Paper paper = paperService.getById(paperId); + Paper paper = paperMapper.selectById(paperId); BeanMapper.copy(paper, respDTO); // 查找题目列表 @@ -207,7 +207,7 @@ public class PaperServiceImpl extends ServiceImpl implements ExamResultRespDTO respDTO = new ExamResultRespDTO(); // 试题基本信息 - Paper paper = paperService.getById(paperId); + Paper paper = paperMapper.selectById(paperId); BeanMapper.copy(paper, respDTO); List quList = paperQuService.listForPaperResult(paperId); @@ -364,7 +364,7 @@ public class PaperServiceImpl extends ServiceImpl implements cl.add(Calendar.MINUTE, exam.getTotalTime()); paper.setLimitTime(cl.getTime()); - paperService.save(paper); + this.save(paper); if (!CollectionUtils.isEmpty(quList)) { this.savePaperQu(paper.getId(), quList); @@ -474,7 +474,7 @@ public class PaperServiceImpl extends ServiceImpl implements public void handExam(String paperId) { //获取试卷信息 - Paper paper = paperService.getById(paperId); + Paper paper = paperMapper.selectById(paperId); //如果不是正常的,抛出异常 if(!PaperState.ING.equals(paper.getState())){ @@ -511,7 +511,7 @@ public class PaperServiceImpl extends ServiceImpl implements paper.setUserTime(userTime); //更新试卷 - paperService.updateById(paper); + this.updateById(paper); // 终止定时任务 diff --git a/exam-admin/src/main/java/com/yf/exam/modules/qu/controller/QuController.java b/exam-admin/src/main/java/com/yf/exam/modules/qu/controller/QuController.java index 07e7d76..93ded88 100644 --- a/exam-admin/src/main/java/com/yf/exam/modules/qu/controller/QuController.java +++ b/exam-admin/src/main/java/com/yf/exam/modules/qu/controller/QuController.java @@ -1,8 +1,6 @@ package com.yf.exam.modules.qu.controller; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.google.common.collect.Lists; import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.dto.BaseIdReqDTO; @@ -10,17 +8,20 @@ import com.yf.exam.core.api.dto.BaseIdRespDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.exception.ServiceException; -import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.excel.ExportExcel; import com.yf.exam.core.utils.excel.ImportExcel; import com.yf.exam.modules.qu.dto.QuDTO; import com.yf.exam.modules.qu.dto.export.QuExportDTO; import com.yf.exam.modules.qu.dto.ext.QuDetailDTO; import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO; -import com.yf.exam.modules.qu.entity.Qu; import com.yf.exam.modules.qu.service.QuService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.shiro.authz.annotation.RequiresRoles; @@ -34,11 +35,6 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - /** *

* 问题题目控制器 diff --git a/exam-admin/src/main/java/com/yf/exam/modules/quartz/service/impl/PaymentInfoTaskServiceImpl.java b/exam-admin/src/main/java/com/yf/exam/modules/quartz/service/impl/PaymentInfoTaskServiceImpl.java index a51a97a..4f469fa 100644 --- a/exam-admin/src/main/java/com/yf/exam/modules/quartz/service/impl/PaymentInfoTaskServiceImpl.java +++ b/exam-admin/src/main/java/com/yf/exam/modules/quartz/service/impl/PaymentInfoTaskServiceImpl.java @@ -3,7 +3,7 @@ package com.yf.exam.modules.quartz.service.impl; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.google.common.collect.Lists; +import org.apache.commons.compress.utils.Lists; import com.yf.exam.config.XylWeChatPaymentConfig; import com.yf.exam.core.enums.GooodsOrderStatusEnum; import com.yf.exam.core.enums.PayTypeEnum; diff --git a/exam-admin/src/main/resources/application-dev.yml b/exam-admin/src/main/resources/application-dev.yml index 088eb63..5652900 100644 --- a/exam-admin/src/main/resources/application-dev.yml +++ b/exam-admin/src/main/resources/application-dev.yml @@ -38,7 +38,7 @@ spring: instanceName: eamScheduler instanceId: AUTO jobStore: - class: org.quartz.impl.jdbcjobstore.JobStoreTX + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate tablePrefix: QRTZ_ isClustered: true @@ -56,8 +56,8 @@ conf: # 物理文件存储位置,以/结束,windows已正斜杠,如:d:/exam-upload/ dir: D:/exam-upload/ # 访问地址,注意不要去除/upload/file/,此节点为虚拟标识符 - # 如:http://localhost:8101/upload/file/exam.jpg,对应物理文件为:/data/upload/exam.jpg - url: http://8.131.93.145:54012/upload/file/ + # 如:http://47.104.245.3:8101/upload/file/,对应物理文件为:/data/upload/exam.jpg + url: https://examapi.xinelu.cn/upload/file/ # 允许上传的文件后缀 allow-extensions: jpg,jpeg,png folder: diff --git a/exam-admin/src/main/resources/application.yml b/exam-admin/src/main/resources/application.yml index 003af38..d422466 100644 --- a/exam-admin/src/main/resources/application.yml +++ b/exam-admin/src/main/resources/application.yml @@ -21,6 +21,27 @@ spring: mapper: # 支持类型转换 allow-coercion-of-scalars: true + redis: + # 地址 + host: 127.0.0.1 + # 端口,默认为6379 + port: 6379 + # 数据库索引 + database: 2 + # 密码 + password: xyl_1024@ + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms server: port: 8101 # 启用服务端压缩 @@ -28,28 +49,6 @@ server: enabled: true min-response-size: 10 mime-types: application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css - # redis 配置 - redis: - # 地址 - host: localhost - # 端口,默认为6379 - port: 6379 - # 数据库索引 - database: 2 - # 密码 - password: - # 连接超时时间 - timeout: 10s - lettuce: - pool: - # 连接池中的最小空闲连接 - min-idle: 0 - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池的最大数据库连接数 - max-active: 8 - # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms # 考试系统微信小程序参数配置信息 applet-chat-config: # 微信小程序 @@ -72,8 +71,8 @@ xyl-we-chat-config: xyl-private-key-path: apiclient_key.pem # 山东省公共卫生学会API V3版本密钥 Xyl699003981qazVFR4xsw23edcASDFG xyl-payment-key: gonggongweishengXUEHUI2025081100 - # 山东省公共卫生学会微信支付回调地址 https://quanyidaojia.xinelu.cn - xyl-wechat-notify-url: http://8.131.93.145:54012 + # 山东省公共卫生学会微信支付回调地址 https://examapi.xinelu.cn + xyl-wechat-notify-url: https://examapi.xinelu.cn # 微信支付接口地址,包含小程序和App支付接口地址 we-chat-payment-url-config: # 小程序JSAPI下单接口地址