Merge pull request '匡文超分支提交到develop里' (#11) from kuangwenchao_branch into develop

pull/9/head
pbensvpw6 9 months ago
commit 7f4c120d8a

@ -1,21 +1,22 @@
package com.yf.exam.core.annon; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/annon/Dict.java
package com.yf.exam.core.annon; // 定义包名,表示该类属于 com.yf.exam.core.annon 包
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType; // 导入 ElementType 类,用于指定注解可以应用于的元素类型
import java.lang.annotation.Retention; import java.lang.annotation.Retention; // 导入 Retention 类,用于指定注解的保留策略
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; // 导入 RetentionPolicy 类,定义注解的保留策略
import java.lang.annotation.Target; import java.lang.annotation.Target; // 导入 Target 类,用于指定注解的适用范围
/** /**
* *
* @author bool * @author bool
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD) // 指定该注解可以应用于字段(类的属性)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME) // 指定该注解在运行时仍然可用
public @interface Dict { public @interface Dict { // 定义一个名为 Dict 的注解
String dicCode(); String dicCode(); // 定义一个抽象方法 dicCode返回数据字典的代码
String dicText() default ""; String dicText() default ""; // 定义一个抽象方法 dicText返回数据字典的文本默认为空字符串
String dictTable() default ""; String dictTable() default ""; // 定义一个抽象方法 dictTable返回数据字典的表名默认为空字符串
} }

@ -1,67 +1,63 @@
package com.yf.exam.core.api; package com.yf.exam.core.api; // 定义包名
import lombok.AllArgsConstructor; // 导入Lombok的全参构造器注解
import lombok.NoArgsConstructor; // 导入Lombok的无参构造器注解
import lombok.AllArgsConstructor; import java.io.Serializable; // 导入Serializable接口
import lombok.NoArgsConstructor;
import java.io.Serializable;
/** /**
* * // 类注释,说明该类的用途
* 使 * 使 // 说明枚举命名规则
* @author bool * @author bool // 作者信息
* @date 2019-06-14 21:15 * @date 2019-06-14 21:15 // 日期信息
*/ */
@NoArgsConstructor @NoArgsConstructor // 生成无参构造器
@AllArgsConstructor @AllArgsConstructor // 生成全参构造器
public enum ApiError implements Serializable { public enum ApiError implements Serializable { // 定义ApiError枚举实现Serializable接口
/** /**
* *
*/ */
ERROR_10010001("参数不全或类型错误!"), ERROR_10010001("参数不全或类型错误!"), // 错误码10010001及其对应的消息
ERROR_10010002("您还未登录,请先登录!"), ERROR_10010002("您还未登录,请先登录!"), // 错误码10010002及其对应的消息
ERROR_10010003("数据不存在!"), ERROR_10010003("数据不存在!"), // 错误码10010003及其对应的消息
ERROR_10010012("图形验证码错误!"), ERROR_10010012("图形验证码错误!"), // 错误码10010012及其对应的消息
ERROR_10010013("短信验证码错误!"), ERROR_10010013("短信验证码错误!"), // 错误码10010013及其对应的消息
ERROR_10010014("不允许重复评论!"), ERROR_10010014("不允许重复评论!"), // 错误码10010014及其对应的消息
/** /**
* *
*/ */
ERROR_20010001("试题被删除,无法继续考试!"), ERROR_20010001("试题被删除,无法继续考试!"), // 错误码20010001及其对应的消息
ERROR_20010002("您有正在进行的考试!"), ERROR_20010002("您有正在进行的考试!"), // 错误码20010002及其对应的消息
ERROR_90010001("账号不存在,请确认!"),
ERROR_90010002("账号或密码错误!"),
ERROR_90010003("至少要包含一个角色!"),
ERROR_90010004("管理员账号无法修改!"),
ERROR_90010005("账号被禁用,请联系管理员!"),
ERROR_90010006("活动用户不足,无法开启竞拍!"),
ERROR_90010007("旧密码不正确,请确认!"),
ERROR_90010001("账号不存在,请确认!"), // 错误码90010001及其对应的消息
ERROR_90010002("账号或密码错误!"), // 错误码90010002及其对应的消息
ERROR_90010003("至少要包含一个角色!"), // 错误码90010003及其对应的消息
ERROR_90010004("管理员账号无法修改!"), // 错误码90010004及其对应的消息
ERROR_90010005("账号被禁用,请联系管理员!"), // 错误码90010005及其对应的消息
ERROR_90010006("活动用户不足,无法开启竞拍!"), // 错误码90010006及其对应的消息
ERROR_90010007("旧密码不正确,请确认!"), // 错误码90010007及其对应的消息
ERROR_60000001("数据不存在!"); ERROR_60000001("数据不存在!"); // 错误码60000001及其对应的消息
public String msg; public String msg; // 定义错误消息字段
/** /**
* Markdown * Markdown // 方法注释,说明该方法的用途
* @param args * @param args // 参数说明
*/ */
public static void main(String[] args) { public static void main(String[] args) { // 主方法
for (ApiError e : ApiError.values()) { for (ApiError e : ApiError.values()) { // 遍历所有ApiError枚举值
System.out.println("'"+e.name().replace("ERROR_", "")+"':'"+e.msg+"',"); System.out.println("'"+e.name().replace("ERROR_", "")+"':'"+e.msg+"',"); // 输出错误码和消息
} }
} }
/** /**
* * // 方法注释,说明该方法的用途
* @return * @return // 返回值说明
*/ */
public Integer getCode(){ public Integer getCode(){ // 获取错误码的方法
return Integer.parseInt(this.name().replace("ERROR_", "")); return Integer.parseInt(this.name().replace("ERROR_", "")); // 返回去掉"ERROR_"前缀的整数值
} }
} }

@ -1,64 +1,64 @@
package com.yf.exam.core.api;
package com.yf.exam.core.api; // 定义包名
import com.yf.exam.core.api.ApiError; import com.yf.exam.core.api.ApiError; // 导入ApiError类
import com.yf.exam.core.exception.ServiceException; import com.yf.exam.core.exception.ServiceException; // 导入ServiceException类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入ApiModel注解
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入ApiModelProperty注解
import lombok.Data; import lombok.Data; // 导入Data注解
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor; // 导入NoArgsConstructor注解
/** /**
* *
* @author bool * @author bool
* @date 2018/11/20 09:48 * @date 2018/11/20 09:48
*/ */
@Data @Data // 自动生成getter、setter、toString等方法
@NoArgsConstructor @NoArgsConstructor // 自动生成无参构造函数
@ApiModel(value="接口响应", description="接口响应") @ApiModel(value="接口响应", description="接口响应") // Swagger注解描述API模型
public class ApiRest<T>{ public class ApiRest<T>{ // 定义泛型类ApiRest
/** /**
* *
*/ */
@ApiModelProperty(value = "响应消息") @ApiModelProperty(value = "响应消息") // Swagger注解描述响应消息属性
private String msg; private String msg; // 响应消息
/** /**
* *
*/ */
@ApiModelProperty(value = "响应代码,0为成功,1为失败", required = true) @ApiModelProperty(value = "响应代码,0为成功,1为失败", required = true) // Swagger注解描述响应代码属性
private Integer code; private Integer code; // 响应代码
/** /**
* body * body
*/ */
@ApiModelProperty(value = "响应内容") @ApiModelProperty(value = "响应内容") // Swagger注解描述响应内容属性
protected T data; protected T data; // 响应内容
/** /**
* *
* @return * @return
*/ */
public boolean isSuccess(){ public boolean isSuccess(){ // 判断请求是否成功
return code.equals(0); return code.equals(0); // 如果响应代码为0返回true
} }
/** /**
* *
* @param error * @param error
*/ */
public ApiRest(ServiceException error){ public ApiRest(ServiceException error){ // 构造函数接收ServiceException对象
this.code = error.getCode(); this.code = error.getCode(); // 设置响应代码
this.msg = error.getMsg(); this.msg = error.getMsg(); // 设置响应消息
} }
/** /**
* *
* @param error * @param error
*/ */
public ApiRest(ApiError error){ public ApiRest(ApiError error){ // 构造函数接收ApiError对象
this.code = error.getCode(); this.code = error.getCode(); // 设置响应代码
this.msg = error.msg; this.msg = error.msg; // 设置响应消息
} }
} }

@ -1,154 +1,150 @@
package com.yf.exam.core.api.controller; package com.yf.exam.core.api.controller;
// 导入所需的类
import com.yf.exam.core.api.ApiError; import com.yf.exam.core.api.ApiError; // 导入ApiError类用于处理API错误
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入ApiRest类用于构建API响应
import com.yf.exam.core.exception.ServiceException; import com.yf.exam.core.exception.ServiceException; // 导入ServiceException类用于处理服务异常
/** /**
* *
* API
* @author Dav * @author Dav
*/ */
public class BaseController { public class BaseController {
/** /**
* *
* CODE_SUCCESS
*/ */
private static final Integer CODE_SUCCESS = 0; private static final Integer CODE_SUCCESS = 0; // 定义成功状态码
private static final String MSG_SUCCESS = "操作成功!"; private static final String MSG_SUCCESS = "操作成功!"; // 定义成功消息
/** /**
* *
* CODE_FAILURE
*/ */
private static final Integer CODE_FAILURE = 1; private static final Integer CODE_FAILURE = 1; // 定义失败状态码
private static final String MSG_FAILURE = "请求失败!"; private static final String MSG_FAILURE = "请求失败!"; // 定义失败消息
/** /**
* *
* @param code * @param code
* @param message * @param message
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> message(Integer code, String message, T data){ protected <T> ApiRest<T> message(Integer code, String message, T data){
ApiRest<T> response = new ApiRest<>(); ApiRest<T> response = new ApiRest<>(); // 创建ApiRest对象
response.setCode(code); response.setCode(code); // 设置状态码
response.setMsg(message); response.setMsg(message); // 设置消息内容
if(data!=null) { if(data!=null) { // 如果数据不为空
response.setData(data); response.setData(data); // 设置响应数据
} }
return response; return response; // 返回构造好的响应
} }
/** /**
* *
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> success(){ protected <T> ApiRest<T> success(){
return message(0, "请求成功!", null); return message(0, "请求成功!", null); // 调用message方法构造成功响应
} }
/** /**
* *
* @param message * @param message
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> success(String message, T data){ protected <T> ApiRest<T> success(String message, T data){
return message(CODE_SUCCESS, message, data); return message(CODE_SUCCESS, message, data); // 调用message方法构造成功响应
} }
/** /**
* *
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> success(T data){ protected <T> ApiRest<T> success(T data){
return message(CODE_SUCCESS, MSG_SUCCESS, data); return message(CODE_SUCCESS, MSG_SUCCESS, data); // 调用message方法构造成功响应
} }
/** /**
* *
* @param code * @param code
* @param message * @param message
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(Integer code, String message, T data){ protected <T> ApiRest<T> failure(Integer code, String message, T data){
return message(code, message, data); return message(code, message, data); // 调用message方法构造失败响应
} }
/** /**
* *
* @param message * @param message
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(String message, T data){ protected <T> ApiRest<T> failure(String message, T data){
return message(CODE_FAILURE, message, data); return message(CODE_FAILURE, message, data); // 调用message方法构造失败响应
} }
/** /**
* *
* @param message * @param message
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(String message){ protected <T> ApiRest<T> failure(String message){
return message(CODE_FAILURE, message, null); return message(CODE_FAILURE, message, null); // 调用message方法构造失败响应
} }
/** /**
* *
* @param data * @param data
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(T data){ protected <T> ApiRest<T> failure(T data){
return message(CODE_FAILURE, MSG_FAILURE, data); return message(CODE_FAILURE, MSG_FAILURE, data); // 调用message方法构造失败响应
} }
/** /**
* *
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(){ protected <T> ApiRest<T> failure(){
return message(CODE_FAILURE, MSG_FAILURE, null); return message(CODE_FAILURE, MSG_FAILURE, null); // 调用message方法构造失败响应
} }
/** /**
* *
* @param <T> * @param error ApiError
* @return * @param data
* @param <T>
* @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(ApiError error, T data){ protected <T> ApiRest<T> failure(ApiError error, T data){
return message(error.getCode(), error.msg, data); return message(error.getCode(), error.msg, data); // 调用message方法构造失败响应
} }
/** /**
* *
* @param ex * @param ex ServiceException
* @param <T> * @param <T>
* @return * @return ApiRest<T> API
*/ */
protected <T> ApiRest<T> failure(ServiceException ex){ protected <T> ApiRest<T> failure(ServiceException ex){
ApiRest<T> apiRest = message(ex.getCode(), ex.getMsg(), null); ApiRest<T> apiRest = message(ex.getCode(), ex.getMsg(), null); // 调用message方法构造失败响应
return apiRest; return apiRest; // 返回构造好的响应
} }
} }

@ -1,7 +1,10 @@
// 包声明,定义该类所在的包
package com.yf.exam.core.api.dto; package com.yf.exam.core.api.dto;
// 导入lombok库中的@Data注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 导入Serializable接口用于对象序列化
import java.io.Serializable; import java.io.Serializable;
/** /**
@ -9,7 +12,11 @@ import java.io.Serializable;
* @author dav * @author dav
* @date 2019/3/16 15:56 * @date 2019/3/16 15:56
*/ */
// 使用@Data注解自动生成该类的getter、setter等方法
@Data @Data
// 定义一个名为BaseDTO的公共类实现Serializable接口
public class BaseDTO implements Serializable { public class BaseDTO implements Serializable {
// 该类目前没有任何字段或方法
} }

@ -1,28 +1,28 @@
package com.yf.exam.core.api.dto; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/api/dto/BaseIdReqDTO.java
package com.yf.exam.core.api.dto; // 定义包名,表示该类属于哪个包
import com.yf.exam.core.api.dto.BaseDTO; import com.yf.exam.core.api.dto.BaseDTO; // 导入BaseDTO类BaseIdReqDTO类将继承自它
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore; // 导入JsonIgnore注解用于在序列化时忽略某个字段
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入ApiModel注解用于Swagger文档生成
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入ApiModelProperty注解用于Swagger文档生成
import lombok.Data; import lombok.Data; // 导入Lombok的Data注解用于自动生成getter、setter等方法
/** /**
* <p> * <p>
* ID * ID
* </p> * </p>
* *
* @author * @author // 类的作者信息
* @since 2019-04-20 12:15 * @since 2019-04-20 12:15 // 类的创建时间
*/ */
@Data @Data // 使用Lombok的Data注解自动生成toString、equals、hashCode、getter和setter方法
@ApiModel(value="主键通用请求类", description="主键通用请求类") @ApiModel(value="主键通用请求类", description="主键通用请求类") // Swagger文档中显示的模型信息
public class BaseIdReqDTO extends BaseDTO { public class BaseIdReqDTO extends BaseDTO { // 定义BaseIdReqDTO类继承自BaseDTO
@ApiModelProperty(value = "主键ID", required=true) @ApiModelProperty(value = "主键ID", required=true) // Swagger文档中显示的属性信息表示该字段是必需的
private String id; private String id; // 定义主键ID字段
@JsonIgnore
private String userId;
@JsonIgnore // 在序列化时忽略该字段不会被JSON输出
private String userId; // 定义用户ID字段通常用于内部逻辑不需要暴露给外部
} }

@ -1,26 +1,28 @@
package com.yf.exam.core.api.dto; package com.yf.exam.core.api.dto;
import com.yf.exam.core.api.dto.BaseDTO; // 导入所需的类
import io.swagger.annotations.ApiModel; import com.yf.exam.core.api.dto.BaseDTO; // 导入基础DTO类
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于API文档生成
import lombok.AllArgsConstructor; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于API文档生成
import lombok.Data; import lombok.AllArgsConstructor; // 导入Lombok注解用于生成全参构造函数
import lombok.NoArgsConstructor; import lombok.Data; // 导入Lombok注解用于自动生成getter、setter等方法
import lombok.NoArgsConstructor; // 导入Lombok注解用于生成无参构造函数
/** /**
* <p> * <p>
* *
* ID
* </p> * </p>
* *
* @author * @author
* @since 2019-04-20 12:15 * @since 2019-04-20 12:15
*/ */
@Data @Data // 自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="主键通用响应类", description="主键通用响应类") @ApiModel(value="主键通用响应类", description="主键通用响应类") // Swagger注解描述该类的用途
@AllArgsConstructor @AllArgsConstructor // 自动生成全参构造函数
@NoArgsConstructor @NoArgsConstructor // 自动生成无参构造函数
public class BaseIdRespDTO extends BaseDTO { public class BaseIdRespDTO extends BaseDTO { // 继承自BaseDTO类
@ApiModelProperty(value = "主键ID", required=true) @ApiModelProperty(value = "主键ID", required=true) // Swagger注解描述id属性
private String id; private String id; // 主键ID属性必填
} }

@ -1,26 +1,26 @@
package com.yf.exam.core.api.dto; package com.yf.exam.core.api.dto;
import com.yf.exam.core.api.dto.BaseDTO; import com.yf.exam.core.api.dto.BaseDTO; // 导入基础DTO类
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore; // 导入JsonIgnore注解用于序列化时忽略字段
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入ApiModel注解用于Swagger文档生成
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入ApiModelProperty注解用于Swagger文档生成
import lombok.Data; import lombok.Data; // 导入Lombok的Data注解用于自动生成getter、setter等方法
import java.util.List; import java.util.List; // 导入List类用于定义ID列表
/** /**
* ID * ID
* IDID便API
* @author bool * @author bool
* @date 2019-08-01 19:07 * @date 2019-08-01 19:07
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString等方法
@ApiModel(value="删除参数", description="删除参数") @ApiModel(value="删除参数", description="删除参数") // Swagger注解描述该类的用途
public class BaseIdsReqDTO extends BaseDTO { public class BaseIdsReqDTO extends BaseDTO { // 继承自BaseDTO类
@JsonIgnore // 在序列化时忽略该字段
private String userId; // 用户ID通常用于标识请求的用户
@JsonIgnore @ApiModelProperty(value = "要删除的ID列表", required = true) // Swagger注解描述该字段
private String userId; private List<String> ids; // 要删除的ID列表必填项
@ApiModelProperty(value = "要删除的ID列表", required = true)
private List<String> ids;
} }

@ -1,32 +1,32 @@
package com.yf.exam.core.api.dto; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/api/dto/BaseStateReqDTO.java
package com.yf.exam.core.api.dto; // 定义包名表示该类属于com.yf.exam.core.api.dto包
import com.yf.exam.core.api.dto.BaseDTO; import com.yf.exam.core.api.dto.BaseDTO; // 导入BaseDTO类BaseStateReqDTO类将继承自它
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入ApiModel注解用于Swagger文档生成
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入ApiModelProperty注解用于Swagger文档生成
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor; // 导入Lombok库的AllArgsConstructor注解自动生成全参构造函数
import lombok.Data; import lombok.Data; // 导入Lombok库的Data注解自动生成getter、setter、toString等方法
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor; // 导入Lombok库的NoArgsConstructor注解自动生成无参构造函数
import java.util.List; import java.util.List; // 导入List类用于定义ID列表
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author * @author // 类的作者
* @since 2019-04-20 12:15 * @since 2019-04-20 12:15 // 类的创建时间
*/ */
@Data @Data // 自动生成getter、setter、toString等方法
@ApiModel(value="通用状态请求类", description="通用状态请求类") @ApiModel(value="通用状态请求类", description="通用状态请求类") // Swagger文档中类的描述
@AllArgsConstructor @AllArgsConstructor // 自动生成全参构造函数
@NoArgsConstructor @NoArgsConstructor // 自动生成无参构造函数
public class BaseStateReqDTO extends BaseDTO { public class BaseStateReqDTO extends BaseDTO { // 定义BaseStateReqDTO类继承自BaseDTO
@ApiModelProperty(value = "要修改对象的ID列表", required=true) // Swagger文档中属性的描述表示该属性为必填项
private List<String> ids; // 定义一个ID列表用于存储要修改对象的ID
@ApiModelProperty(value = "要修改对象的ID列表", required=true) @ApiModelProperty(value = "通用状态0为正常1为禁用", required=true) // Swagger文档中属性的描述表示该属性为必填项
private List<String> ids; private Integer state; // 定义一个状态字段0表示正常1表示禁用
@ApiModelProperty(value = "通用状态0为正常1为禁用", required=true)
private Integer state;
} }

@ -1,47 +1,44 @@
package com.yf.exam.core.api.dto; package com.yf.exam.core.api.dto; // 定义包名
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入MyBatis分页类
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore; // 导入Jackson注解用于忽略字段
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于API文档
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于API文档属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于自动生成getter和setter
/** /**
* *
* @param <T> * @param <T>
* @author bool * @author bool
*/ */
@ApiModel(value="分页参数", description="分页参数") @ApiModel(value="分页参数", description="分页参数") // Swagger模型注解
@Data @Data // Lombok注解自动生成getter、setter、toString等方法
public class PagingReqDTO<T> { public class PagingReqDTO<T> { // 定义分页请求DTO类使用泛型T
@ApiModelProperty(value = "当前页码", required = true, example = "1") // Swagger属性注解
private Integer current; // 当前页码
@ApiModelProperty(value = "当前页码", required = true, example = "1") @ApiModelProperty(value = "每页数量", required = true, example = "10") // Swagger属性注解
private Integer current; private Integer size; // 每页数量
@ApiModelProperty(value = "每页数量", required = true, example = "10") @ApiModelProperty(value = "查询参数") // Swagger属性注解
private Integer size; private T params; // 查询参数类型为泛型T
@ApiModelProperty(value = "查询参数") @ApiModelProperty(value = "排序字符") // Swagger属性注解
private T params; private String orderBy; // 排序字段
@ApiModelProperty(value = "排序字符") @JsonIgnore // Jackson注解忽略该字段
private String orderBy; @ApiModelProperty(value = "当前用户的ID") // Swagger属性注解
private String userId; // 当前用户的ID
@JsonIgnore
@ApiModelProperty(value = "当前用户的ID")
private String userId;
/** /**
* MyBatis * MyBatis
* @return * @return MyBatisPage
*/ */
public Page toPage(){ public Page toPage(){ // 定义转换方法
Page page = new Page(); Page page = new Page(); // 创建Page对象
page.setCurrent(this.current); page.setCurrent(this.current); // 设置当前页码
page.setSize(this.size); page.setSize(this.size); // 设置每页数量
return page; return page; // 返回Page对象
} }
} }

@ -1,29 +1,29 @@
package com.yf.exam.core.api.dto; package com.yf.exam.core.api.dto; // 定义包名
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入分页类
/** /**
* *
* @author bool * @author bool
* @date 2019-07-20 15:17 * @date 2019-07-20 15:17
* @param <T> * @param <T>
*/ */
public class PagingRespDTO<T> extends Page<T> { public class PagingRespDTO<T> extends Page<T> { // 定义分页响应类继承自Page类
/** /**
* *
* @return * @return
*/ */
@Override @Override
public long getPages() { public long getPages() { // 重写getPages方法
if (this.getSize() == 0L) { if (this.getSize() == 0L) { // 如果每页大小为0
return 0L; return 0L; // 返回0
} else { } else { // 否则
long pages = this.getTotal() / this.getSize(); long pages = this.getTotal() / this.getSize(); // 计算总页数
if (this.getTotal() % this.getSize() != 0L) { if (this.getTotal() % this.getSize() != 0L) { // 如果总数不能被每页大小整除
++pages; ++pages; // 页数加1
} }
return pages; return pages; // 返回总页数
} }
} }

@ -1,48 +1,48 @@
package com.yf.exam.core.api.utils; package com.yf.exam.core.api.utils; // 定义包名
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.SerializerFeature; // 导入FastJson序列化特性
import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.config.FastJsonConfig; // 导入FastJson配置类
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; // 导入FastJson消息转换器
import org.springframework.http.MediaType; import org.springframework.http.MediaType; // 导入媒体类型类
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; // 导入HTTP消息转换器接口
import java.nio.charset.Charset; import java.nio.charset.Charset; // 导入字符集类
import java.util.ArrayList; import java.util.ArrayList; // 导入ArrayList类
import java.util.List; import java.util.List; // 导入List接口
/** /**
* JSON * JSON
* @author dav * @author dav
* @date 2018/9/11 19:30 * @date 2018/9/11 19:30
*/ */
public class JsonConverter { public class JsonConverter { // 定义JsonConverter类
/** /**
* FastJson * FastJson
* *
* @return * @return HttpMessageConverter
*/ */
public static HttpMessageConverter fastConverter() { public static HttpMessageConverter fastConverter() { // 定义静态方法fastConverter
// 定义一个convert转换消息的对象 // 定义一个convert转换消息的对象
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); // 创建FastJson消息转换器实例
// 添加FastJson的配置信息 // 添加FastJson的配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); // 创建FastJson配置实例
// 默认转换器 // 默认转换器
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, // 设置序列化特性:格式化输出
SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullNumberAsZero, // 将null数字写为0
SerializerFeature.MapSortField, SerializerFeature.MapSortField, // 对Map进行排序
SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullStringAsEmpty, // 将null字符串写为空
SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.DisableCircularReferenceDetect, // 禁用循环引用检测
SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteDateUseDateFormat, // 使用日期格式化
SerializerFeature.WriteNullListAsEmpty); SerializerFeature.WriteNullListAsEmpty); // 将null列表写为空列表
fastJsonConfig.setCharset(Charset.forName("UTF-8")); fastJsonConfig.setCharset(Charset.forName("UTF-8")); // 设置字符集为UTF-8
// 处理中文乱码问题 // 处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<>(); List<MediaType> fastMediaTypes = new ArrayList<>(); // 创建媒体类型列表
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); // 添加支持的媒体类型UTF-8 JSON
fastConverter.setSupportedMediaTypes(fastMediaTypes); fastConverter.setSupportedMediaTypes(fastMediaTypes); // 设置支持的媒体类型
// 在convert中添加配置信息 // 在convert中添加配置信息
fastConverter.setFastJsonConfig(fastJsonConfig); fastConverter.setFastJsonConfig(fastJsonConfig); // 设置FastJson配置
return fastConverter; return fastConverter; // 返回FastJson消息转换器
} } // 结束fastConverter方法
} } // 结束JsonConverter类

@ -1,19 +1,21 @@
package com.yf.exam.core.enums; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/enums/CommonState.java
package com.yf.exam.core.enums; // 定义包名
/** /**
* *
* *
* @author bool * @author bool // 作者信息
* @date 2019-09-17 17:57 * @date 2019-09-17 17:57 // 日期信息
*/ */
public interface CommonState { public interface CommonState { // 定义一个公共接口
/** /**
* *
*/ */
Integer NORMAL = 0; Integer NORMAL = 0; // 定义正常状态的常量值为0
/** /**
* *
*/ */
Integer ABNORMAL = 1; Integer ABNORMAL = 1; // 定义非正常状态的常量值为1
} }

@ -1,18 +1,19 @@
package com.yf.exam.core.enums; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/enums/OpenType.java
package com.yf.exam.core.enums; // 定义包名
/** /**
* *
* @author bool * @author bool
*/ */
public interface OpenType { public interface OpenType { // 定义接口 OpenType
/** /**
* *
*/ */
Integer OPEN = 1; Integer OPEN = 1; // 定义常量 OPEN值为 1
/** /**
* *
*/ */
Integer DEPT_OPEN = 2; Integer DEPT_OPEN = 2; // 定义常量 DEPT_OPEN值为 2
} }

@ -1,51 +1,52 @@
package com.yf.exam.core.exception; // 文件路径: yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/exception/ServiceException.java
package com.yf.exam.core.exception; // 定义包名
import com.yf.exam.core.api.ApiError; import com.yf.exam.core.api.ApiError; // 导入ApiError类
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入ApiRest类
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor; // 导入AllArgsConstructor注解
import lombok.Data; import lombok.Data; // 导入Data注解
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor; // 导入NoArgsConstructor注解
@Data @Data // 自动生成getter、setter、toString等方法
@AllArgsConstructor @AllArgsConstructor // 生成包含所有字段的构造函数
@NoArgsConstructor @NoArgsConstructor // 生成无参构造函数
public class ServiceException extends RuntimeException{ public class ServiceException extends RuntimeException{ // 定义ServiceException类继承RuntimeException
/** /**
* *
*/ */
private Integer code; private Integer code; // 定义错误码字段
/** /**
* *
*/ */
private String msg; private String msg; // 定义错误消息字段
/** /**
* *
* @param apiRest * @param apiRest
*/ */
public ServiceException(ApiRest apiRest){ public ServiceException(ApiRest apiRest){ // 构造函数接受ApiRest对象
this.code = apiRest.getCode(); this.code = apiRest.getCode(); // 初始化错误码
this.msg = apiRest.getMsg(); this.msg = apiRest.getMsg(); // 初始化错误消息
} }
/** /**
* *
* @param apiError * @param apiError
*/ */
public ServiceException(ApiError apiError){ public ServiceException(ApiError apiError){ // 构造函数接受ApiError对象
this.code = apiError.getCode(); this.code = apiError.getCode(); // 初始化错误码
this.msg = apiError.msg; this.msg = apiError.msg; // 初始化错误消息
} }
/** /**
* *
* @param msg * @param msg
*/ */
public ServiceException(String msg){ public ServiceException(String msg){ // 构造函数,接受错误消息
this.code = 1; this.code = 1; // 默认错误码为1
this.msg = msg; this.msg = msg; // 初始化错误消息
} }
} }

@ -1,46 +1,46 @@
package com.yf.exam.core.exception; package com.yf.exam.core.exception; // 定义包名
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入ApiRest类
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus; // 导入HttpStatus类
import org.springframework.ui.Model; import org.springframework.ui.Model; // 导入Model类
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder; // 导入WebDataBinder类
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*; // 导入所有注解
/** /**
* *
* @author bool * @author bool
* @date 2019-06-21 19:27 * @date 2019-06-21 19:27
*/ */
@RestControllerAdvice @RestControllerAdvice // 声明这是一个全局异常处理类
public class ServiceExceptionHandler { public class ServiceExceptionHandler { // 定义ServiceExceptionHandler类
/** /**
* @RequestMapping * @RequestMapping
* @param binder * @param binder
*/ */
@InitBinder @InitBinder // 初始化数据绑定器
public void initWebBinder(WebDataBinder binder){ public void initWebBinder(WebDataBinder binder){ // 定义初始化方法
// 这里可以添加自定义的初始化逻辑
} }
/** /**
* Model使@RequestMapping * Model使@RequestMapping
* @param model * @param model
*/ */
@ModelAttribute @ModelAttribute // 将方法的返回值绑定到模型中
public void addAttribute(Model model) { public void addAttribute(Model model) { // 定义添加属性的方法
// 这里可以添加需要绑定到模型的属性
} }
/** /**
* ServiceException * ServiceException
* @param e * @param e
* @return * @return ApiRest API
*/ */
@ExceptionHandler({com.yf.exam.core.exception.ServiceException.class}) @ExceptionHandler({com.yf.exam.core.exception.ServiceException.class}) // 指定捕获的异常类型
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK) // 设置响应状态为200 OK
public ApiRest serviceExceptionHandler(ServiceException e) { public ApiRest serviceExceptionHandler(ServiceException e) { // 定义异常处理方法
return new ApiRest(e); return new ApiRest(e); // 返回ApiRest对象包含异常信息
} }
} }

@ -1,13 +1,12 @@
package com.yf.exam.core.utils; package com.yf.exam.core.utils; // 定义包名
import org.dozer.DozerBeanMapper; import org.dozer.DozerBeanMapper; // 导入DozerBeanMapper类
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.ArrayList; // 导入ArrayList类
import java.util.Collection; // 导入Collection接口
import java.util.List; // 导入List接口
import java.util.function.Function; // 导入Function接口
import java.util.stream.Collectors; // 导入Collectors类
/** /**
* Dozer, Bean<->BeanMapper.: * Dozer, Bean<->BeanMapper.:
@ -18,42 +17,42 @@ import java.util.stream.Collectors;
* 4. BAB. * 4. BAB.
* *
*/ */
public class BeanMapper { public class BeanMapper { // 定义BeanMapper类
/** /**
* Dozer, DozerMapper. * Dozer, DozerMapper.
*/ */
private static DozerBeanMapper dozerBeanMapper = new DozerBeanMapper(); private static DozerBeanMapper dozerBeanMapper = new DozerBeanMapper(); // 创建DozerBeanMapper的单例
/** /**
* Dozer. * Dozer.
*/ */
public static <T> T map(Object source, Class<T> destinationClass) { public static <T> T map(Object source, Class<T> destinationClass) { // 定义map方法转换对象类型
return dozerBeanMapper.map(source, destinationClass); return dozerBeanMapper.map(source, destinationClass); // 使用Dozer进行对象转换
} }
/** /**
* DozerCollection. * DozerCollection.
*/ */
public static <T> List<T> mapList(Iterable<?> sourceList, Class<T> destinationClass) { public static <T> List<T> mapList(Iterable<?> sourceList, Class<T> destinationClass) { // 定义mapList方法转换集合中的对象
List<T> destinationList = new ArrayList(); List<T> destinationList = new ArrayList(); // 创建目标列表
for (Object sourceObject : sourceList) { for (Object sourceObject : sourceList) { // 遍历源列表中的每个对象
T destinationObject = dozerBeanMapper.map(sourceObject, destinationClass); T destinationObject = dozerBeanMapper.map(sourceObject, destinationClass); // 转换对象
destinationList.add(destinationObject); destinationList.add(destinationObject); // 将转换后的对象添加到目标列表
} }
return destinationList; return destinationList; // 返回目标列表
} }
/** /**
* DozerAB. * DozerAB.
*/ */
public static void copy(Object source, Object destinationObject) { public static void copy(Object source, Object destinationObject) { // 定义copy方法拷贝对象A的值到对象B
if(source!=null) { if(source!=null) { // 检查源对象是否为null
dozerBeanMapper.map(source, destinationObject); dozerBeanMapper.map(source, destinationObject); // 使用Dozer进行值拷贝
} }
} }
public static <T, S> List<T> mapList(Collection<S> source, Function<? super S, ? extends T> mapper) { public static <T, S> List<T> mapList(Collection<S> source, Function<? super S, ? extends T> mapper) { // 定义重载的mapList方法使用自定义映射函数
return source.stream().map(mapper).collect(Collectors.toList()); return source.stream().map(mapper).collect(Collectors.toList()); // 使用流和映射函数转换集合并返回列表
} }
} }

@ -1,31 +1,32 @@
package com.yf.exam.core.utils; language:yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/utils/CronUtils.java
package com.yf.exam.core.utils; // 包声明,定义了类的包路径
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; // 导入用于格式化日期的类
import java.util.Date; import java.util.Date; // 导入日期类
/** /**
* quartz * quartz
* @author bool * @author bool // 作者信息
* @date 2020/11/29 3:00 * @date 2020/11/29 3:00 // 日期信息
*/ */
public class CronUtils { public class CronUtils { // 定义CronUtils类
/** /**
* *
*/ */
private static final String DATE_FORMAT = "ss mm HH dd MM ? yyyy"; private static final String DATE_FORMAT = "ss mm HH dd MM ? yyyy"; // 定义日期格式的常量
/** /**
* *
* @param date * @param date // 输入的日期
* @return * @return // 返回格式化后的cron表达式
*/ */
public static String dateToCron(final Date date){ public static String dateToCron(final Date date){ // 定义静态方法将日期转换为cron表达式
SimpleDateFormat fmt = new SimpleDateFormat(DATE_FORMAT); SimpleDateFormat fmt = new SimpleDateFormat(DATE_FORMAT); // 创建SimpleDateFormat对象
String formatTimeStr = ""; String formatTimeStr = ""; // 初始化格式化后的时间字符串
if (date != null) { if (date != null) { // 检查日期是否为null
formatTimeStr = fmt.format(date); formatTimeStr = fmt.format(date); // 格式化日期
} }
return formatTimeStr; return formatTimeStr; // 返回格式化后的字符串
} }
} }

@ -1,9 +1,9 @@
package com.yf.exam.core.utils; package com.yf.exam.core.utils; // 包声明,定义该类所在的包
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; // 导入用于日期格式化的类
import java.util.Calendar; import java.util.Calendar; // 导入日历类
import java.util.Date; import java.util.Date; // 导入日期类
import java.util.GregorianCalendar; import java.util.GregorianCalendar; // 导入公历日历类
/** /**
* *
@ -13,27 +13,27 @@ import java.util.GregorianCalendar;
* @author Bool * @author Bool
* @version * @version
*/ */
public class DateUtils { public class DateUtils { // 定义DateUtils类
/** /**
* *
* calcExpDays: <br/> * calcExpDays: <br/>
* @author Bool * @author Bool
* @param userCreateTime * @param userCreateTime
* @return * @return
* @since JDK 1.6 * @since JDK 1.6
*/ */
public static int calcExpDays(Date userCreateTime){ public static int calcExpDays(Date userCreateTime){ // 计算日期差异的方法
Calendar start = Calendar.getInstance(); Calendar start = Calendar.getInstance(); // 获取当前日历实例
start.setTime(userCreateTime); start.setTime(userCreateTime); // 设置开始时间为用户创建时间
Calendar now = Calendar.getInstance(); Calendar now = Calendar.getInstance(); // 获取当前日历实例
now.setTime(new Date()); now.setTime(new Date()); // 设置当前时间
long l = now.getTimeInMillis() - start.getTimeInMillis(); long l = now.getTimeInMillis() - start.getTimeInMillis(); // 计算时间差(毫秒)
int days = new Long(l / (1000 * 60 * 60 * 24)).intValue(); int days = new Long(l / (1000 * 60 * 60 * 24)).intValue(); // 将毫秒转换为天数
return days; return days; // 返回天数
} }
@ -42,36 +42,34 @@ public class DateUtils {
* dateNow:. <br/> * dateNow:. <br/>
* @author Bool * @author Bool
* @param format * @param format
* @return * @return
*/ */
public static String dateNow(String format) { public static String dateNow(String format) { // 获取当前时间字符串的方法
SimpleDateFormat fmt = new SimpleDateFormat(format); SimpleDateFormat fmt = new SimpleDateFormat(format); // 创建日期格式化对象
Calendar c = new GregorianCalendar(); Calendar c = new GregorianCalendar(); // 获取公历日历实例
return fmt.format(c.getTime()); return fmt.format(c.getTime()); // 返回格式化后的当前时间字符串
} }
/** /**
* formatDate: <br/> * formatDate: <br/>
* @author Bool * @author Bool
* @param time * @param time
* @param format * @param format
* @return * @return
*/ */
public static String formatDate(Date time, String format) { public static String formatDate(Date time, String format) { // 格式化日期的方法
SimpleDateFormat fmt = new SimpleDateFormat(format); SimpleDateFormat fmt = new SimpleDateFormat(format); // 创建日期格式化对象
return fmt.format(time.getTime()); return fmt.format(time.getTime()); // 返回格式化后的日期字符串
} }
/** /**
* parseDate:使yyyy-MM-dd HH:mm:ss * parseDate:使yyyy-MM-dd HH:mm:ss
* @author Bool * @author Bool
* @param date * @param date
* @return * @return
*/ */
public static Date parseDate(String date) { public static Date parseDate(String date) { // 将字符串解析为日期的方法
return parseDate(date, "yyyy-MM-dd HH:mm:ss"); return parseDate(date, "yyyy-MM-dd HH:mm:ss"); // 使用默认格式解析
} }
@ -79,25 +77,23 @@ public class DateUtils {
* *
* parseDate:使 * parseDate:使
* @author Bool * @author Bool
* @param date * @param date
* @param pattern * @param pattern
* @return * @return
*/ */
public static Date parseDate(String date, String pattern) { public static Date parseDate(String date, String pattern) { // 使用指定格式解析字符串为日期
if (pattern==null) { if (pattern==null) { // 如果未指定格式
pattern = "yyyy-MM-dd HH:mm:ss"; pattern = "yyyy-MM-dd HH:mm:ss"; // 使用默认格式
} }
SimpleDateFormat fmt = new SimpleDateFormat(pattern); SimpleDateFormat fmt = new SimpleDateFormat(pattern); // 创建日期格式化对象
try { try {
return fmt.parse(date); // 尝试解析日期字符串
return fmt.parse(date); } catch (Exception ex) { // 捕获异常
} catch (Exception ex) { ex.printStackTrace(); // 打印异常堆栈
ex.printStackTrace();
} }
return null; return null; // 返回null表示解析失败
} }
} }

@ -1,7 +1,6 @@
package com.yf.exam.core.utils; package com.yf.exam.core.utils; // 定义包名
import javax.servlet.http.HttpServletRequest; // 导入HttpServletRequest类
import javax.servlet.http.HttpServletRequest;
/** /**
* IPIP * IPIP
@ -11,55 +10,52 @@ import javax.servlet.http.HttpServletRequest;
* @author Bool * @author Bool
* @version * @version
*/ */
public class IpUtils { public class IpUtils { // 定义IpUtils类
/** /**
* *
* getClientIp:IP * getClientIp:IP
* @author Bool * @author Bool
* @param request * @param request HttpServletRequest
* @return * @return IP
*/ */
public static String extractClientIp(HttpServletRequest request) { public static String extractClientIp(HttpServletRequest request) { // 定义静态方法extractClientIp接收HttpServletRequest参数
String ip = null; String ip = null; // 初始化ip变量为null
//X-Forwarded-ForSquid 服务代理 //X-Forwarded-ForSquid 服务代理
String ipAddresses = request.getHeader("X-Forwarded-For"); String ipAddresses = request.getHeader("X-Forwarded-For"); // 获取请求头中的X-Forwarded-For字段
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { // 检查ipAddresses是否为空或未知
//Proxy-Client-IPapache 服务代理 //Proxy-Client-IPapache 服务代理
ipAddresses = request.getHeader("Proxy-Client-IP"); ipAddresses = request.getHeader("Proxy-Client-IP"); // 获取Proxy-Client-IP字段
} }
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { // 检查ipAddresses是否为空或未知
//WL-Proxy-Client-IPweblogic 服务代理 //WL-Proxy-Client-IPweblogic 服务代理
ipAddresses = request.getHeader("WL-Proxy-Client-IP"); ipAddresses = request.getHeader("WL-Proxy-Client-IP"); // 获取WL-Proxy-Client-IP字段
} }
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { // 检查ipAddresses是否为空或未知
//HTTP_CLIENT_IP有些代理服务器 //HTTP_CLIENT_IP有些代理服务器
ipAddresses = request.getHeader("HTTP_CLIENT_IP"); ipAddresses = request.getHeader("HTTP_CLIENT_IP"); // 获取HTTP_CLIENT_IP字段
} }
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { // 检查ipAddresses是否为空或未知
//X-Real-IPnginx服务代理 //X-Real-IPnginx服务代理
ipAddresses = request.getHeader("X-Real-IP"); ipAddresses = request.getHeader("X-Real-IP"); // 获取X-Real-IP字段
} }
//有些网络通过多层代理那么获取到的ip就会有多个一般都是通过逗号,分割开来并且第一个ip为客户端的真实IP //有些网络通过多层代理那么获取到的ip就会有多个一般都是通过逗号,分割开来并且第一个ip为客户端的真实IP
if (ipAddresses != null && ipAddresses.length() != 0) { if (ipAddresses != null && ipAddresses.length() != 0) { // 检查ipAddresses是否不为空
ip = ipAddresses.split(",")[0]; ip = ipAddresses.split(",")[0]; // 通过逗号分割并获取第一个IP地址
} }
//还是不能获取到最后再通过request.getRemoteAddr();获取 //还是不能获取到最后再通过request.getRemoteAddr();获取
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { // 检查ip是否为空或未知
ip = request.getRemoteAddr(); ip = request.getRemoteAddr(); // 最后通过getRemoteAddr获取IP地址
} }
return ip; return ip; // 返回获取到的IP地址
} }
} }

@ -1,22 +1,22 @@
/** /**
* Copyright (c) 2005-2012 springside.org.cn * Copyright (c) 2005-2012 springside.org.cn
*/ */
package com.yf.exam.core.utils; package com.yf.exam.core.utils; // 定义包名
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2; // 引入Log4j2日志库
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils; // 引入Apache Commons Lang的StringUtils类
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate; // 引入Apache Commons Lang的Validate类
import org.springframework.util.Assert; import org.springframework.util.Assert; // 引入Spring的Assert类
import java.lang.reflect.Field; import java.lang.reflect.Field; // 引入反射中的Field类
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException; // 引入反射中的InvocationTargetException类
import java.lang.reflect.Method; import java.lang.reflect.Method; // 引入反射中的Method类
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier; // 引入反射中的Modifier类
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType; // 引入反射中的ParameterizedType类
import java.lang.reflect.Type; import java.lang.reflect.Type; // 引入反射中的Type类
import java.util.ArrayList; import java.util.ArrayList; // 引入ArrayList类
import java.util.Arrays; import java.util.Arrays; // 引入Arrays类
import java.util.List; import java.util.List; // 引入List接口
/** /**
* . * .
@ -24,32 +24,32 @@ import java.util.List;
* @author calvin * @author calvin
* @version 2016-01-15 * @version 2016-01-15
*/ */
@Log4j2 @Log4j2 // 使用Log4j2注解
public class Reflections { public class Reflections { // 定义Reflections类
private static final String SETTER_PREFIX = "set"; private static final String SETTER_PREFIX = "set"; // 定义setter方法前缀
private static final String GETTER_PREFIX = "get"; private static final String GETTER_PREFIX = "get"; // 定义getter方法前缀
private static final String CGLIB_CLASS_SEPARATOR = "$$"; private static final String CGLIB_CLASS_SEPARATOR = "$$"; // 定义CGLIB类分隔符
/** /**
* *
* *
* @param object * @param object
* @return * @return
*/ */
public static Field[] getAllFields(Object object) { public static Field[] getAllFields(Object object) { // 定义获取所有字段的方法
Class<?> clazz = object.getClass(); Class<?> clazz = object.getClass(); // 获取对象的类
List<Field> fieldList = new ArrayList<>(); List<Field> fieldList = new ArrayList<>(); // 创建字段列表
while (clazz != null) { while (clazz != null) { // 循环直到没有父类
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); // 添加当前类的字段
clazz = clazz.getSuperclass(); clazz = clazz.getSuperclass(); // 获取父类
} }
Field[] fields = new Field[fieldList.size()]; Field[] fields = new Field[fieldList.size()]; // 创建字段数组
fieldList.toArray(fields); fieldList.toArray(fields); // 将列表转换为数组
return fields; return fields; // 返回字段数组
} }
@ -57,29 +57,29 @@ public class Reflections {
* Getter. * Getter.
* .. * ..
*/ */
public static Object invokeGetter(Object obj, String propertyName) { public static Object invokeGetter(Object obj, String propertyName) { // 定义调用getter方法
Object object = obj; Object object = obj; // 初始化对象
for (String name : StringUtils.split(propertyName, ".")){ for (String name : StringUtils.split(propertyName, ".")){ // 分割属性名
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); // 生成getter方法名
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); // 调用getter方法
} }
return object; return object; // 返回结果
} }
/** /**
* Setter, * Setter,
* .. * ..
*/ */
public static void invokeSetter(Object obj, String propertyName, Object value) { public static void invokeSetter(Object obj, String propertyName, Object value) { // 定义调用setter方法
Object object = obj; Object object = obj; // 初始化对象
String[] names = StringUtils.split(propertyName, "."); String[] names = StringUtils.split(propertyName, "."); // 分割属性名
for (int i=0; i<names.length; i++){ for (int i=0; i<names.length; i++){ // 遍历属性名
if(i<names.length-1){ if(i<names.length-1){ // 如果不是最后一个属性
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); // 生成getter方法名
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); // 调用getter方法
}else{ }else{ // 如果是最后一个属性
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); // 生成setter方法名
invokeMethodByName(object, setterMethodName, new Object[] { value }); invokeMethodByName(object, setterMethodName, new Object[] { value }); // 调用setter方法
} }
} }
} }
@ -87,36 +87,36 @@ public class Reflections {
/** /**
* , private/protected, getter. * , private/protected, getter.
*/ */
public static Object getFieldValue(final Object obj, final String fieldName) { public static Object getFieldValue(final Object obj, final String fieldName) { // 定义获取字段值的方法
Field field = getAccessibleField(obj, fieldName); Field field = getAccessibleField(obj, fieldName); // 获取可访问的字段
if (field == null) { if (field == null) { // 如果字段不存在
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); // 抛出异常
} }
Object result = null; Object result = null; // 初始化结果
try { try {
result = field.get(obj); result = field.get(obj); // 获取字段值
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) { // 捕获非法访问异常
log.error("不可能抛出的异常{}", e.getMessage()); log.error("不可能抛出的异常{}", e.getMessage()); // 记录错误
} }
return result; return result; // 返回结果
} }
/** /**
* , private/protected, setter. * , private/protected, setter.
*/ */
public static void setFieldValue(final Object obj, final String fieldName, final Object value) { public static void setFieldValue(final Object obj, final String fieldName, final Object value) { // 定义设置字段值的方法
Field field = getAccessibleField(obj, fieldName); Field field = getAccessibleField(obj, fieldName); // 获取可访问的字段
if (field == null) { if (field == null) { // 如果字段不存在
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); // 抛出异常
} }
try { try {
field.set(obj, value); field.set(obj, value); // 设置字段值
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) { // 捕获非法访问异常
log.error("不可能抛出的异常:{}", e.getMessage()); log.error("不可能抛出的异常:{}", e.getMessage()); // 记录错误
} }
} }
@ -126,16 +126,16 @@ public class Reflections {
* + * +
*/ */
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) { final Object[] args) { // 定义调用方法的方法
Method method = getAccessibleMethod(obj, methodName, parameterTypes); Method method = getAccessibleMethod(obj, methodName, parameterTypes); // 获取可访问的方法
if (method == null) { if (method == null) { // 如果方法不存在
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); // 抛出异常
} }
try { try {
return method.invoke(obj, args); return method.invoke(obj, args); // 调用方法并返回结果
} catch (Exception e) { } catch (Exception e) { // 捕获异常
throw convertReflectionExceptionToUnchecked(e); throw convertReflectionExceptionToUnchecked(e); // 转换异常
} }
} }
@ -144,16 +144,16 @@ public class Reflections {
* 使getAccessibleMethodByName()Method. * 使getAccessibleMethodByName()Method.
* *
*/ */
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) { public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) { // 定义通过方法名调用方法
Method method = getAccessibleMethodByName(obj, methodName); Method method = getAccessibleMethodByName(obj, methodName); // 获取可访问的方法
if (method == null) { if (method == null) { // 如果方法不存在
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); // 抛出异常
} }
try { try {
return method.invoke(obj, args); return method.invoke(obj, args); // 调用方法并返回结果
} catch (Exception e) { } catch (Exception e) { // 捕获异常
throw convertReflectionExceptionToUnchecked(e); throw convertReflectionExceptionToUnchecked(e); // 转换异常
} }
} }
@ -162,20 +162,20 @@ public class Reflections {
* *
* Object, null. * Object, null.
*/ */
public static Field getAccessibleField(final Object obj, final String fieldName) { public static Field getAccessibleField(final Object obj, final String fieldName) { // 定义获取可访问字段的方法
Validate.notNull(obj, "object can't be null"); Validate.notNull(obj, "object can't be null"); // 验证对象不为空
Validate.notBlank(fieldName, "fieldName can't be blank"); Validate.notBlank(fieldName, "fieldName can't be blank"); // 验证字段名不为空
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { // 循环向上转型
try { try {
Field field = superClass.getDeclaredField(fieldName); Field field = superClass.getDeclaredField(fieldName); // 获取声明的字段
makeAccessible(field); makeAccessible(field); // 设置字段为可访问
return field; return field; // 返回字段
} catch (NoSuchFieldException e) {//NOSONAR } catch (NoSuchFieldException e) { // 捕获没有该字段的异常
// Field不在当前类定义,继续向上转型 // Field不在当前类定义,继续向上转型
continue;// new add continue; // 继续循环
} }
} }
return null; return null; // 返回null
} }
/** /**
@ -186,21 +186,21 @@ public class Reflections {
* . 使Method,Method.invoke(Object obj, Object... args) * . 使Method,Method.invoke(Object obj, Object... args)
*/ */
public static Method getAccessibleMethod(final Object obj, final String methodName, public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) { final Class<?>... parameterTypes) { // 定义获取可访问方法的方法
Validate.notNull(obj, "object can't be null"); Validate.notNull(obj, "object can't be null"); // 验证对象不为空
Validate.notBlank(methodName, "methodName can't be blank"); Validate.notBlank(methodName, "methodName can't be blank"); // 验证方法名不为空
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { // 循环向上转型
try { try {
Method method = searchType.getDeclaredMethod(methodName, parameterTypes); Method method = searchType.getDeclaredMethod(methodName, parameterTypes); // 获取声明的方法
makeAccessible(method); makeAccessible(method); // 设置方法为可访问
return method; return method; // 返回方法
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) { // 捕获没有该方法的异常
// Method不在当前类定义,继续向上转型 // Method不在当前类定义,继续向上转型
continue;// new add continue; // 继续循环
} }
} }
return null; return null; // 返回null
} }
/** /**
@ -210,39 +210,39 @@ public class Reflections {
* *
* . 使Method,Method.invoke(Object obj, Object... args) * . 使Method,Method.invoke(Object obj, Object... args)
*/ */
public static Method getAccessibleMethodByName(final Object obj, final String methodName) { public static Method getAccessibleMethodByName(final Object obj, final String methodName) { // 定义通过方法名获取可访问方法的方法
Validate.notNull(obj, "object can't be null"); Validate.notNull(obj, "object can't be null"); // 验证对象不为空
Validate.notBlank(methodName, "methodName can't be blank"); Validate.notBlank(methodName, "methodName can't be blank"); // 验证方法名不为空
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { // 循环向上转型
Method[] methods = searchType.getDeclaredMethods(); Method[] methods = searchType.getDeclaredMethods(); // 获取声明的方法数组
for (Method method : methods) { for (Method method : methods) { // 遍历方法
if (method.getName().equals(methodName)) { if (method.getName().equals(methodName)) { // 如果方法名匹配
makeAccessible(method); makeAccessible(method); // 设置方法为可访问
return method; return method; // 返回方法
} }
} }
} }
return null; return null; // 返回null
} }
/** /**
* private/protectedpublicJDKSecurityManager * private/protectedpublicJDKSecurityManager
*/ */
public static void makeAccessible(Method method) { public static void makeAccessible(Method method) { // 定义设置方法为可访问的方法
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) // 如果方法或类不是public
&& !method.isAccessible()) { && !method.isAccessible()) { // 且方法不可访问
method.setAccessible(true); method.setAccessible(true); // 设置为可访问
} }
} }
/** /**
* private/protectedpublicJDKSecurityManager * private/protectedpublicJDKSecurityManager
*/ */
public static void makeAccessible(Field field) { public static void makeAccessible(Field field) { // 定义设置字段为可访问的方法
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier // 如果字段或类不是public或字段是final
.isFinal(field.getModifiers())) && !field.isAccessible()) { .isFinal(field.getModifiers())) && !field.isAccessible()) { // 且字段不可访问
field.setAccessible(true); field.setAccessible(true); // 设置为可访问
} }
} }
@ -256,8 +256,8 @@ public class Reflections {
* @return the first generic declaration, or Object.class if cannot be determined * @return the first generic declaration, or Object.class if cannot be determined
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Class<T> getClassGenricType(final Class clazz) { public static <T> Class<T> getClassGenricType(final Class clazz) { // 定义获取类的泛型类型的方法
return getClassGenricType(clazz, 0); return getClassGenricType(clazz, 0); // 调用重载方法
} }
/** /**
@ -270,55 +270,54 @@ public class Reflections {
* @param index the Index of the generic ddeclaration,start from 0. * @param index the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be determined * @return the index generic declaration, or Object.class if cannot be determined
*/ */
public static Class getClassGenricType(final Class clazz, final int index) { public static Class getClassGenricType(final Class clazz, final int index) { // 定义获取类的泛型类型的方法
Type genType = clazz.getGenericSuperclass(); // 获取类的泛型超类
Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { // 如果不是参数化类型
log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType"); // 记录警告
if (!(genType instanceof ParameterizedType)) { return Object.class; // 返回Object.class
log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
} }
Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); // 获取实际类型参数
if (index >= params.length || index < 0) { if (index >= params.length || index < 0) { // 如果索引超出范围
log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length); + params.length); // 记录警告
return Object.class; return Object.class; // 返回Object.class
} }
if (!(params[index] instanceof Class)) { if (!(params[index] instanceof Class)) { // 如果参数不是Class类型
log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); // 记录警告
return Object.class; return Object.class; // 返回Object.class
} }
return (Class) params[index]; return (Class) params[index]; // 返回指定索引的Class类型
} }
public static Class<?> getUserClass(Object instance) { public static Class<?> getUserClass(Object instance) { // 定义获取用户类的方法
Assert.notNull(instance, "Instance must not be null"); Assert.notNull(instance, "Instance must not be null"); // 验证实例不为空
Class clazz = instance.getClass(); Class clazz = instance.getClass(); // 获取实例的类
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { // 如果类名包含CGLIB分隔符
Class<?> superClass = clazz.getSuperclass(); Class<?> superClass = clazz.getSuperclass(); // 获取父类
if (superClass != null && !Object.class.equals(superClass)) { if (superClass != null && !Object.class.equals(superClass)) { // 如果父类存在且不是Object
return superClass; return superClass; // 返回父类
} }
} }
return clazz; return clazz; // 返回当前类
} }
/** /**
* checked exceptionunchecked exception. * checked exceptionunchecked exception.
*/ */
public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) { public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) { // 定义转换异常的方法
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException // 如果是非法访问或参数异常
|| e instanceof NoSuchMethodException) { || e instanceof NoSuchMethodException) { // 或者没有该方法异常
return new IllegalArgumentException(e); return new IllegalArgumentException(e); // 返回非法参数异常
} else if (e instanceof InvocationTargetException) { } else if (e instanceof InvocationTargetException) { // 如果是调用目标异常
return new RuntimeException(((InvocationTargetException) e).getTargetException()); return new RuntimeException(((InvocationTargetException) e).getTargetException()); // 返回目标异常
} else if (e instanceof RuntimeException) { } else if (e instanceof RuntimeException) { // 如果是运行时异常
return (RuntimeException) e; return (RuntimeException) e; // 返回运行时异常
} }
return new RuntimeException("Unexpected Checked Exception.", e); return new RuntimeException("Unexpected Checked Exception.", e); // 返回未知异常
} }
} }

@ -1,32 +1,33 @@
package com.yf.exam.core.utils; language:yfexam-exam-main/yfexam-exam-main/exam-api/src/main/java/com/yf/exam/core/utils/SpringUtils.java
package com.yf.exam.core.utils; // 定义包名
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException; // 导入BeansException类
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext; // 导入ApplicationContext接口
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware; // 导入ApplicationContextAware接口
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component; // 导入Component注解
/** /**
* Spring * Spring
* *
* @author bool * @author bool // 作者信息
* @date 2019-12-09 15:55 * @date 2019-12-09 15:55 // 日期信息
*/ */
@Component @Component // 将该类标记为Spring组件
public class SpringUtils implements ApplicationContextAware { public class SpringUtils implements ApplicationContextAware { // 定义SpringUtils类并实现ApplicationContextAware接口
private static ApplicationContext applicationContext; private static ApplicationContext applicationContext; // 静态变量用于存储ApplicationContext
@Override @Override // 重写setApplicationContext方法
public void setApplicationContext(ApplicationContext context) throws BeansException { public void setApplicationContext(ApplicationContext context) throws BeansException { // 设置ApplicationContext
applicationContext = context; applicationContext = context; // 将传入的context赋值给静态变量
} }
public static <T> T getBean(Class<T> tClass) { public static <T> T getBean(Class<T> tClass) { // 泛型方法根据类获取Bean
return applicationContext.getBean(tClass); return applicationContext.getBean(tClass); // 从ApplicationContext中获取指定类型的Bean
} }
public static <T> T getBean(String name, Class<T> type) { public static <T> T getBean(String name, Class<T> type) { // 泛型方法根据名称和类型获取Bean
return applicationContext.getBean(name, type); return applicationContext.getBean(name, type); // 从ApplicationContext中获取指定名称和类型的Bean
} }
} }

@ -1,39 +1,38 @@
package com.yf.exam.core.utils; package com.yf.exam.core.utils; // 定义包名
import java.util.Map; import java.util.Map; // 导入Map类
/** /**
* *
* @author bool * @author bool
* @date 2019-05-15 11:40 * @date 2019-05-15 11:40
*/ */
public class StringUtils { public class StringUtils { // 定义StringUtils类
/** /**
* *
* @param str * @param str
* @return * @return nulltruefalse
*/ */
public static boolean isBlank(String str){ public static boolean isBlank(String str){ // 定义静态方法isBlank
return str==null || "".equals(str); return str==null || "".equals(str); // 检查字符串是否为null或空
} }
/** /**
* MAPxml<xml><key>value</key>...</xml> * MAPxml<xml><key>value</key>...</xml>
* @param params * @param params Map
* @return * @return xml
*/ */
public static String mapToXml(Map<String, String> params){ public static String mapToXml(Map<String, String> params){ // 定义静态方法mapToXml
StringBuffer sb = new StringBuffer("<xml>"); StringBuffer sb = new StringBuffer("<xml>"); // 创建StringBuffer并初始化为<xml>
for(String key:params.keySet()){ for(String key:params.keySet()){ // 遍历Map中的每个key
sb.append("<") sb.append("<") // 添加开始标签
.append(key).append(">") .append(key).append(">") // 添加key
.append(params.get(key)) .append(params.get(key)) // 添加对应的value
.append("</").append(key).append(">"); .append("</").append(key).append(">"); // 添加结束标签
} }
sb.append("</xml>"); sb.append("</xml>"); // 添加结束的</xml>标签
return sb.toString(); return sb.toString(); // 返回构建的xml字符串
} }
} }

@ -1,82 +1,83 @@
/** /**
* Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/ */
package com.yf.exam.core.utils.excel; package com.yf.exam.core.utils.excel; // 包声明
import com.google.common.collect.Lists; import com.google.common.collect.Lists; // 导入Lists类
import com.yf.exam.core.utils.Reflections; import com.yf.exam.core.utils.Reflections; // 导入Reflections工具类
import com.yf.exam.core.utils.excel.annotation.ExcelField; import com.yf.exam.core.utils.excel.annotation.ExcelField; // 导入ExcelField注解
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils; // 导入StringUtils工具类
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell; // 导入Cell类
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle; // 导入CellStyle类
import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.Comment; // 导入Comment类
import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.DataFormat; // 导入DataFormat类
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font; // 导入Font类
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors; // 导入IndexedColors类
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row; // 导入Row类
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet; // 导入Sheet类
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook; // 导入Workbook类
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress; // 导入CellRangeAddress类
import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook; // 导入SXSSFWorkbook类
import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; // 导入XSSFClientAnchor类
import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.apache.poi.xssf.usermodel.XSSFRichTextString; // 导入XSSFRichTextString类
import org.slf4j.Logger; import org.slf4j.Logger; // 导入Logger接口
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory; // 导入LoggerFactory类
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse; // 导入HttpServletResponse类
import java.io.IOException; import java.io.IOException; // 导入IOException类
import java.io.OutputStream; import java.io.OutputStream; // 导入OutputStream类
import java.lang.reflect.Field; import java.lang.reflect.Field; // 导入Field类
import java.lang.reflect.Method; import java.lang.reflect.Method; // 导入Method类
import java.net.URLEncoder; import java.net.URLEncoder; // 导入URLEncoder类
import java.util.Collections; import java.util.Collections; // 导入Collections类
import java.util.Comparator; import java.util.Comparator; // 导入Comparator接口
import java.util.Date; import java.util.Date; // 导入Date类
import java.util.HashMap; import java.util.HashMap; // 导入HashMap类
import java.util.List; import java.util.List; // 导入List接口
import java.util.Map; import java.util.Map; // 导入Map接口
/** /**
* ExcelXLSX @see org.apache.poi.ss.SpreadsheetVersion * ExcelXLSX @see org.apache.poi.ss.SpreadsheetVersion
* @author jeeplus * @author jeeplus
* @version 2016-04-21 * @version 2016-04-21
*/ */
public class ExportExcel { public class ExportExcel { // ExportExcel类定义
private static Logger log = LoggerFactory.getLogger(ExportExcel.class); private static Logger log = LoggerFactory.getLogger(ExportExcel.class); // 日志记录器
/** /**
* *
*/ */
private SXSSFWorkbook wb; private SXSSFWorkbook wb; // 工作薄对象
/** /**
* *
*/ */
private Sheet sheet; private Sheet sheet; // 工作表对象
/** /**
* *
*/ */
private Map<String, CellStyle> styles; private Map<String, CellStyle> styles; // 样式列表
/** /**
* *
*/ */
private int rownum; private int rownum; // 当前行号
/** /**
* Object[]{ ExcelField, Field/Method } * Object[]{ ExcelField, Field/Method }
*/ */
List<Object[]> annotationList = Lists.newArrayList(); List<Object[]> annotationList = Lists.newArrayList(); // 注解列表
/** /**
* *
* @param title * @param title
* @param cls annotation.ExportField * @param cls annotation.ExportField
*/ */
public ExportExcel(String title, Class<?> cls){ public ExportExcel(String title, Class<?> cls){ // 构造函数
this(title, cls, 1); this(title, cls, 1); // 调用另一个构造函数
} }
/** /**
@ -86,123 +87,123 @@ public class ExportExcel {
* @param type 1:2 * @param type 1:2
* @param groups * @param groups
*/ */
public ExportExcel(String title, Class<?> cls, int type, int... groups){ public ExportExcel(String title, Class<?> cls, int type, int... groups){ // 构造函数
// Get annotation field // Get annotation field
Field[] fs = cls.getDeclaredFields(); Field[] fs = cls.getDeclaredFields(); // 获取类的所有字段
for (Field f : fs){ for (Field f : fs){ // 遍历字段
ExcelField ef = f.getAnnotation(ExcelField.class); ExcelField ef = f.getAnnotation(ExcelField.class); // 获取ExcelField注解
if (ef != null && (ef.type()==0 || ef.type()==type)){ if (ef != null && (ef.type()==0 || ef.type()==type)){ // 检查注解类型
if (groups!=null && groups.length>0){ if (groups!=null && groups.length>0){ // 检查分组
boolean inGroup = false; boolean inGroup = false; // 初始化分组标志
for (int g : groups){ for (int g : groups){ // 遍历分组
if (inGroup){ if (inGroup){ // 如果已经在分组中
break; break; // 退出循环
} }
for (int efg : ef.groups()){ for (int efg : ef.groups()){ // 遍历注解中的分组
if (g == efg){ if (g == efg){ // 如果匹配
inGroup = true; inGroup = true; // 设置标志
annotationList.add(new Object[]{ef, f}); annotationList.add(new Object[]{ef, f}); // 添加到注解列表
break; break; // 退出循环
} }
} }
} }
}else{ }else{ // 如果没有分组
annotationList.add(new Object[]{ef, f}); annotationList.add(new Object[]{ef, f}); // 添加到注解列表
} }
} }
} }
// Get annotation method // Get annotation method
Method[] ms = cls.getDeclaredMethods(); Method[] ms = cls.getDeclaredMethods(); // 获取类的所有方法
for (Method m : ms){ for (Method m : ms){ // 遍历方法
ExcelField ef = m.getAnnotation(ExcelField.class); ExcelField ef = m.getAnnotation(ExcelField.class); // 获取ExcelField注解
if (ef != null && (ef.type()==0 || ef.type()==type)){ if (ef != null && (ef.type()==0 || ef.type()==type)){ // 检查注解类型
if (groups!=null && groups.length>0){ if (groups!=null && groups.length>0){ // 检查分组
boolean inGroup = false; boolean inGroup = false; // 初始化分组标志
for (int g : groups){ for (int g : groups){ // 遍历分组
if (inGroup){ if (inGroup){ // 如果已经在分组中
break; break; // 退出循环
} }
for (int efg : ef.groups()){ for (int efg : ef.groups()){ // 遍历注解中的分组
if (g == efg){ if (g == efg){ // 如果匹配
inGroup = true; inGroup = true; // 设置标志
annotationList.add(new Object[]{ef, m}); annotationList.add(new Object[]{ef, m}); // 添加到注解列表
break; break; // 退出循环
} }
} }
} }
}else{ }else{ // 如果没有分组
annotationList.add(new Object[]{ef, m}); annotationList.add(new Object[]{ef, m}); // 添加到注解列表
} }
} }
} }
// Field sorting // Field sorting
Collections.sort(annotationList, new Comparator<Object[]>() { Collections.sort(annotationList, new Comparator<Object[]>() { // 对注解列表进行排序
@Override @Override
public int compare(Object[] o1, Object[] o2) { public int compare(Object[] o1, Object[] o2) { // 比较方法
return new Integer(((ExcelField)o1[0]).sort()).compareTo( return new Integer(((ExcelField)o1[0]).sort()).compareTo( // 比较排序值
new Integer(((ExcelField)o2[0]).sort())); new Integer(((ExcelField)o2[0]).sort()));
} }
}); });
// Initialize // Initialize
List<String> headerList = Lists.newArrayList(); List<String> headerList = Lists.newArrayList(); // 初始化表头列表
for (Object[] os : annotationList){ for (Object[] os : annotationList){ // 遍历注解列表
String t = ((ExcelField)os[0]).title(); String t = ((ExcelField)os[0]).title(); // 获取标题
// 如果是导出,则去掉注释 // 如果是导出,则去掉注释
if (type==1){ if (type==1){ // 如果是导出数据
String[] ss = StringUtils.split(t, "**", 2); String[] ss = StringUtils.split(t, "**", 2); // 分割标题
if (ss.length==2){ if (ss.length==2){ // 如果有注释
t = ss[0]; t = ss[0]; // 去掉注释
} }
} }
headerList.add(t); headerList.add(t); // 添加标题到表头列表
} }
initialize(title, headerList); initialize(title, headerList); // 初始化工作薄
} }
/** /**
* *
* @param title * @param title
* @param headerList * @param headerList
*/ */
private void initialize(String title, List<String> headerList) { private void initialize(String title, List<String> headerList) { // 初始化方法
this.wb = new SXSSFWorkbook(500); this.wb = new SXSSFWorkbook(500); // 创建工作薄
this.sheet = wb.createSheet("Export"); this.sheet = wb.createSheet("Export"); // 创建工作表
this.styles = createStyles(wb); this.styles = createStyles(wb); // 创建样式
// Create title // Create title
if (StringUtils.isNotBlank(title)){ if (StringUtils.isNotBlank(title)){ // 如果标题不为空
Row titleRow = sheet.createRow(rownum++); Row titleRow = sheet.createRow(rownum++); // 创建标题行
titleRow.setHeightInPoints(30); titleRow.setHeightInPoints(30); // 设置行高
Cell titleCell = titleRow.createCell(0); Cell titleCell = titleRow.createCell(0); // 创建单元格
titleCell.setCellStyle(styles.get("title")); titleCell.setCellStyle(styles.get("title")); // 设置单元格样式
titleCell.setCellValue(title); titleCell.setCellValue(title); // 设置单元格值
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), // 合并单元格
titleRow.getRowNum(), titleRow.getRowNum(), headerList.size()-1)); titleRow.getRowNum(), titleRow.getRowNum(), headerList.size()-1));
} }
// Create header // Create header
if (headerList == null){ if (headerList == null){ // 如果表头列表为空
throw new RuntimeException("headerList not null!"); throw new RuntimeException("headerList not null!"); // 抛出异常
} }
Row headerRow = sheet.createRow(rownum++); Row headerRow = sheet.createRow(rownum++); // 创建表头行
headerRow.setHeightInPoints(16); headerRow.setHeightInPoints(16); // 设置行高
for (int i = 0; i < headerList.size(); i++) { for (int i = 0; i < headerList.size(); i++) { // 遍历表头列表
Cell cell = headerRow.createCell(i); Cell cell = headerRow.createCell(i); // 创建单元格
cell.setCellStyle(styles.get("header")); cell.setCellStyle(styles.get("header")); // 设置单元格样式
String[] ss = StringUtils.split(headerList.get(i), "**", 2); String[] ss = StringUtils.split(headerList.get(i), "**", 2); // 分割表头
if (ss.length==2){ if (ss.length==2){ // 如果有注释
cell.setCellValue(ss[0]); cell.setCellValue(ss[0]); // 设置单元格值
Comment comment = this.sheet.createDrawingPatriarch().createCellComment( Comment comment = this.sheet.createDrawingPatriarch().createCellComment( // 创建注释
new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6)); new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6));
comment.setString(new XSSFRichTextString(ss[1])); comment.setString(new XSSFRichTextString(ss[1])); // 设置注释内容
cell.setCellComment(comment); cell.setCellComment(comment); // 设置单元格注释
}else{ }else{ // 如果没有注释
cell.setCellValue(headerList.get(i)); cell.setCellValue(headerList.get(i)); // 设置单元格值
} }
sheet.autoSizeColumn(i); sheet.autoSizeColumn(i); // 自动调整列宽
} }
for (int i = 0; i < headerList.size(); i++) { for (int i = 0; i < headerList.size(); i++) { // 遍历表头列表
int colWidth = sheet.getColumnWidth(i)*2; int colWidth = sheet.getColumnWidth(i)*2; // 计算列宽
sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth); sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth); // 设置列宽
} }
log.debug("Initialize success."); log.debug("Initialize success."); // 记录初始化成功日志
} }
/** /**
@ -210,73 +211,73 @@ public class ExportExcel {
* @param wb * @param wb
* @return * @return
*/ */
private Map<String, CellStyle> createStyles(Workbook wb) { private Map<String, CellStyle> createStyles(Workbook wb) { // 创建样式方法
Map<String, CellStyle> styles = new HashMap<>(16); Map<String, CellStyle> styles = new HashMap<>(16); // 初始化样式列表
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle(); // 创建样式
style.setAlignment(CellStyle.ALIGN_CENTER); style.setAlignment(CellStyle.ALIGN_CENTER); // 设置水平对齐方式
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); // 设置垂直对齐方式
Font titleFont = wb.createFont(); Font titleFont = wb.createFont(); // 创建字体
titleFont.setFontName("Arial"); titleFont.setFontName("Arial"); // 设置字体名称
titleFont.setFontHeightInPoints((short) 16); titleFont.setFontHeightInPoints((short) 16); // 设置字体大小
titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD); titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD); // 设置字体加粗
style.setFont(titleFont); style.setFont(titleFont); // 设置样式字体
styles.put("title", style); styles.put("title", style); // 添加样式到列表
style = wb.createCellStyle(); style = wb.createCellStyle(); // 创建样式
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); // 设置垂直对齐方式
style.setBorderRight(CellStyle.BORDER_THIN); style.setBorderRight(CellStyle.BORDER_THIN); // 设置右边框
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); // 设置右边框颜色
style.setBorderLeft(CellStyle.BORDER_THIN); style.setBorderLeft(CellStyle.BORDER_THIN); // 设置左边框
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); // 设置左边框颜色
style.setBorderTop(CellStyle.BORDER_THIN); style.setBorderTop(CellStyle.BORDER_THIN); // 设置上边框
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); // 设置上边框颜色
style.setBorderBottom(CellStyle.BORDER_THIN); style.setBorderBottom(CellStyle.BORDER_THIN); // 设置下边框
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); // 设置下边框颜色
Font dataFont = wb.createFont(); Font dataFont = wb.createFont(); // 创建字体
dataFont.setFontName("Arial"); dataFont.setFontName("Arial"); // 设置字体名称
dataFont.setFontHeightInPoints((short) 10); dataFont.setFontHeightInPoints((short) 10); // 设置字体大小
style.setFont(dataFont); style.setFont(dataFont); // 设置样式字体
styles.put("data", style); styles.put("data", style); // 添加样式到列表
style = wb.createCellStyle(); style = wb.createCellStyle(); // 创建样式
style.cloneStyleFrom(styles.get("data")); style.cloneStyleFrom(styles.get("data")); // 克隆数据样式
style.setAlignment(CellStyle.ALIGN_LEFT); style.setAlignment(CellStyle.ALIGN_LEFT); // 设置左对齐
styles.put("data1", style); styles.put("data1", style); // 添加样式到列表
style = wb.createCellStyle(); style = wb.createCellStyle(); // 创建样式
style.cloneStyleFrom(styles.get("data")); style.cloneStyleFrom(styles.get("data")); // 克隆数据样式
style.setAlignment(CellStyle.ALIGN_CENTER); style.setAlignment(CellStyle.ALIGN_CENTER); // 设置居中对齐
styles.put("data2", style); styles.put("data2", style); // 添加样式到列表
style = wb.createCellStyle(); style = wb.createCellStyle(); // 创建样式
style.cloneStyleFrom(styles.get("data")); style.cloneStyleFrom(styles.get("data")); // 克隆数据样式
style.setAlignment(CellStyle.ALIGN_RIGHT); style.setAlignment(CellStyle.ALIGN_RIGHT); // 设置右对齐
styles.put("data3", style); styles.put("data3", style); // 添加样式到列表
style = wb.createCellStyle(); style = wb.createCellStyle(); // 创建样式
style.cloneStyleFrom(styles.get("data")); style.cloneStyleFrom(styles.get("data")); // 克隆数据样式
// style.setWrapText(true); // style.setWrapText(true); // 设置文本换行
style.setAlignment(CellStyle.ALIGN_CENTER); style.setAlignment(CellStyle.ALIGN_CENTER); // 设置居中对齐
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); // 设置前景色
style.setFillPattern(CellStyle.SOLID_FOREGROUND); style.setFillPattern(CellStyle.SOLID_FOREGROUND); // 设置填充模式
Font headerFont = wb.createFont(); Font headerFont = wb.createFont(); // 创建字体
headerFont.setFontName("Arial"); headerFont.setFontName("Arial"); // 设置字体名称
headerFont.setFontHeightInPoints((short) 10); headerFont.setFontHeightInPoints((short) 10); // 设置字体大小
headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD); headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD); // 设置字体加粗
headerFont.setColor(IndexedColors.WHITE.getIndex()); headerFont.setColor(IndexedColors.WHITE.getIndex()); // 设置字体颜色
style.setFont(headerFont); style.setFont(headerFont); // 设置样式字体
styles.put("header", style); styles.put("header", style); // 添加样式到列表
return styles; return styles; // 返回样式列表
} }
/** /**
* *
* @return * @return
*/ */
public Row addRow(){ public Row addRow(){ // 添加行方法
return sheet.createRow(rownum++); return sheet.createRow(rownum++); // 创建新行并返回
} }
@ -287,8 +288,8 @@ public class ExportExcel {
* @param val * @param val
* @return * @return
*/ */
public Cell addCell(Row row, int column, Object val){ public Cell addCell(Row row, int column, Object val){ // 添加单元格方法
return this.addCell(row, column, val, 0, Class.class); return this.addCell(row, column, val, 0, Class.class); // 调用重载方法
} }
/** /**
@ -299,104 +300,104 @@ public class ExportExcel {
* @param align 123 * @param align 123
* @return * @return
*/ */
public Cell addCell(Row row, int column, Object val, int align, Class<?> fieldType){ public Cell addCell(Row row, int column, Object val, int align, Class<?> fieldType){ // 添加单元格重载方法
Cell cell = row.createCell(column); Cell cell = row.createCell(column); // 创建单元格
CellStyle style = styles.get("data"+(align>=1&&align<=3?align:"")); CellStyle style = styles.get("data"+(align>=1&&align<=3?align:"")); // 获取样式
try { try { // 尝试设置单元格值
if (val == null){ if (val == null){ // 如果值为null
cell.setCellValue(""); cell.setCellValue(""); // 设置为空字符串
} else if (val instanceof String) { } else if (val instanceof String) { // 如果值是字符串
cell.setCellValue((String) val); cell.setCellValue((String) val); // 设置单元格值
} else if (val instanceof Integer) { } else if (val instanceof Integer) { // 如果值是整数
cell.setCellValue((Integer) val); cell.setCellValue((Integer) val); // 设置单元格值
} else if (val instanceof Long) { } else if (val instanceof Long) { // 如果值是长整型
cell.setCellValue((Long) val); cell.setCellValue((Long) val); // 设置单元格值
} else if (val instanceof Double) { } else if (val instanceof Double) { // 如果值是双精度浮点型
cell.setCellValue((Double) val); cell.setCellValue((Double) val); // 设置单元格值
} else if (val instanceof Float) { } else if (val instanceof Float) { // 如果值是单精度浮点型
cell.setCellValue((Float) val); cell.setCellValue((Float) val); // 设置单元格值
} else if (val instanceof Date) { } else if (val instanceof Date) { // 如果值是日期
DataFormat format = wb.createDataFormat(); DataFormat format = wb.createDataFormat(); // 创建数据格式
style.setDataFormat(format.getFormat("yyyy-MM-dd")); style.setDataFormat(format.getFormat("yyyy-MM-dd")); // 设置日期格式
cell.setCellValue((Date) val); cell.setCellValue((Date) val); // 设置单元格值
} else { } else { // 如果值是其他类型
if (fieldType != Class.class){ if (fieldType != Class.class){ // 如果字段类型不是Class
cell.setCellValue((String)fieldType.getMethod("setValue", Object.class).invoke(null, val)); cell.setCellValue((String)fieldType.getMethod("setValue", Object.class).invoke(null, val)); // 设置单元格值
}else{ }else{ // 如果字段类型是Class
cell.setCellValue((String)Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), cell.setCellValue((String)Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
"fieldtype."+val.getClass().getSimpleName()+"Type")).getMethod("setValue", Object.class).invoke(null, val)); "fieldtype."+val.getClass().getSimpleName()+"Type")).getMethod("setValue", Object.class).invoke(null, val)); // 设置单元格值
} }
} }
} catch (Exception ex) { } catch (Exception ex) { // 捕获异常
log.info("Set cell value ["+row.getRowNum()+","+column+"] error: " + ex.toString()); log.info("Set cell value ["+row.getRowNum()+","+column+"] error: " + ex.toString()); // 记录错误日志
cell.setCellValue(val.toString()); cell.setCellValue(val.toString()); // 设置单元格值为字符串
} }
cell.setCellStyle(style); cell.setCellStyle(style); // 设置单元格样式
return cell; return cell; // 返回单元格对象
} }
/** /**
* annotation.ExportField * annotation.ExportField
* @return list * @return list
*/ */
public <E> ExportExcel setDataList(List<E> list){ public <E> ExportExcel setDataList(List<E> list){ // 设置数据列表方法
for (E e : list){ for (E e : list){ // 遍历数据列表
int colunm = 0; int colunm = 0; // 初始化列号
Row row = this.addRow(); Row row = this.addRow(); // 添加新行
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder(); // 初始化字符串构建器
for (Object[] os : annotationList){ for (Object[] os : annotationList){ // 遍历注解列表
ExcelField ef = (ExcelField)os[0]; ExcelField ef = (ExcelField)os[0]; // 获取ExcelField注解
Object val = null; Object val = null; // 初始化值
try{ try{ // 尝试获取值
if (StringUtils.isNotBlank(ef.value())){ if (StringUtils.isNotBlank(ef.value())){ // 如果注解值不为空
val = Reflections.invokeGetter(e, ef.value()); val = Reflections.invokeGetter(e, ef.value()); // 通过反射获取值
}else{ }else{ // 如果注解值为空
if (os[1] instanceof Field){ if (os[1] instanceof Field){ // 如果是字段
val = Reflections.invokeGetter(e, ((Field)os[1]).getName()); val = Reflections.invokeGetter(e, ((Field)os[1]).getName()); // 通过反射获取值
}else if (os[1] instanceof Method){ }else if (os[1] instanceof Method){ // 如果是方法
val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {}); val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {}); // 通过反射获取值
} }
} }
}catch(Exception ex) { }catch(Exception ex) { // 捕获异常
log.info(ex.toString()); log.info(ex.toString()); // 记录错误日志
val = ""; val = ""; // 设置值为空字符串
} }
this.addCell(row, colunm++, val, ef.align(), ef.fieldType()); this.addCell(row, colunm++, val, ef.align(), ef.fieldType()); // 添加单元格
sb.append(val + ", "); sb.append(val + ", "); // 添加值到字符串构建器
} }
log.debug("Write success: ["+row.getRowNum()+"] "+sb.toString()); log.debug("Write success: ["+row.getRowNum()+"] "+sb.toString()); // 记录写入成功日志
} }
return this; return this; // 返回当前对象
} }
/** /**
* *
* @param os * @param os
*/ */
public ExportExcel write(OutputStream os) throws IOException{ public ExportExcel write(OutputStream os) throws IOException{ // 输出数据流方法
wb.write(os); wb.write(os); // 写入工作薄到输出流
return this; return this; // 返回当前对象
} }
/** /**
* *
* @param fileName * @param fileName
*/ */
public ExportExcel write(HttpServletResponse response, String fileName) throws IOException{ public ExportExcel write(HttpServletResponse response, String fileName) throws IOException{ // 输出到客户端方法
response.reset(); response.reset(); // 重置响应
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Origin", "*"); // 设置跨域头
response.setContentType("application/octet-stream; charset=utf-8"); response.setContentType("application/octet-stream; charset=utf-8"); // 设置内容类型
response.addHeader("Content-Disposition", "attachment; filename="+ URLEncoder.encode(fileName, "utf-8")); response.addHeader("Content-Disposition", "attachment; filename="+ URLEncoder.encode(fileName, "utf-8")); // 设置下载文件名
write(response.getOutputStream()); write(response.getOutputStream()); // 写入输出流
return this; return this; // 返回当前对象
} }
/** /**
* *
*/ */
public ExportExcel dispose(){ public ExportExcel dispose(){ // 清理临时文件方法
wb.dispose(); wb.dispose(); // 释放工作薄资源
return this; return this; // 返回当前对象
} }
} }

@ -1,59 +1,58 @@
/** /**
* Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/ */
package com.yf.exam.core.utils.excel; package com.yf.exam.core.utils.excel; // 定义包名
import com.google.common.collect.Lists; import com.google.common.collect.Lists; // 导入Google的Lists工具类
import com.yf.exam.core.utils.Reflections; import com.yf.exam.core.utils.Reflections; // 导入自定义的Reflections工具类
import com.yf.exam.core.utils.excel.annotation.ExcelField; import com.yf.exam.core.utils.excel.annotation.ExcelField; // 导入ExcelField注解
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils; // 导入Apache Commons的StringUtils工具类
import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFDateUtil; // 导入HSSFDateUtil类用于处理日期
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook; // 导入HSSFWorkbook类用于处理XLS文件
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; // 导入异常类
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell; // 导入Cell类表示单元格
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row; // 导入Row类表示行
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet; // 导入Sheet类表示工作表
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook; // 导入Workbook类表示工作簿
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; // 导入XSSFWorkbook类用于处理XLSX文件
import org.slf4j.Logger; import org.slf4j.Logger; // 导入Logger接口
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory; // 导入LoggerFactory类
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile; // 导入MultipartFile类用于处理文件上传
import java.io.IOException; import java.io.IOException; // 导入IOException异常
import java.io.InputStream; import java.io.InputStream; // 导入InputStream类
import java.lang.reflect.Field; import java.lang.reflect.Field; // 导入Field类用于反射
import java.lang.reflect.Method; import java.lang.reflect.Method; // 导入Method类用于反射
import java.text.NumberFormat; import java.text.NumberFormat; // 导入NumberFormat类用于格式化数字
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; // 导入SimpleDateFormat类用于格式化日期
import java.util.Collections; import java.util.Collections; // 导入Collections类用于集合操作
import java.util.Comparator; import java.util.Comparator; // 导入Comparator接口用于比较
import java.util.Date; import java.util.Date; // 导入Date类表示日期
import java.util.List; import java.util.List; // 导入List接口表示列表
/** /**
* ExcelXLSXLSX * ExcelXLSXLSX
* @author jeeplus * @author jeeplus
* @version 2016-03-10 * @version 2016-03-10
*/ */
public class ImportExcel { public class ImportExcel { // 定义ImportExcel类
private static Logger log = LoggerFactory.getLogger(ImportExcel.class); private static Logger log = LoggerFactory.getLogger(ImportExcel.class); // 创建日志记录器
/** /**
* *
*/ */
private Workbook wb; private Workbook wb; // 定义工作簿对象
/** /**
* *
*/ */
private Sheet sheet; private Sheet sheet; // 定义工作表对象
/** /**
* *
*/ */
private int headerNum; private int headerNum; // 定义标题行号
/** /**
@ -65,8 +64,8 @@ public class ImportExcel {
* @throws IOException * @throws IOException
*/ */
public ImportExcel(MultipartFile multipartFile, int headerNum, int sheetIndex) public ImportExcel(MultipartFile multipartFile, int headerNum, int sheetIndex)
throws InvalidFormatException, IOException { throws InvalidFormatException, IOException { // 构造函数,接收文件、标题行号和工作表索引
this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex); this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex); // 调用另一个构造函数
} }
/** /**
@ -78,22 +77,22 @@ public class ImportExcel {
* @throws IOException * @throws IOException
*/ */
public ImportExcel(String fileName, InputStream is, int headerNum, int sheetIndex) public ImportExcel(String fileName, InputStream is, int headerNum, int sheetIndex)
throws IOException { throws IOException { // 构造函数,接收文件名、输入流、标题行号和工作表索引
if (StringUtils.isBlank(fileName)){ if (StringUtils.isBlank(fileName)){ // 检查文件名是否为空
throw new RuntimeException("导入文档为空!"); throw new RuntimeException("导入文档为空!"); // 抛出异常
}else if(fileName.toLowerCase().endsWith("xls")){ }else if(fileName.toLowerCase().endsWith("xls")){ // 检查文件格式
this.wb = new HSSFWorkbook(is); this.wb = new HSSFWorkbook(is); // 创建HSSFWorkbook对象
}else if(fileName.toLowerCase().endsWith("xlsx")){ }else if(fileName.toLowerCase().endsWith("xlsx")){
this.wb = new XSSFWorkbook(is); this.wb = new XSSFWorkbook(is); // 创建XSSFWorkbook对象
}else{ }else{
throw new RuntimeException("文档格式不正确!"); throw new RuntimeException("文档格式不正确!"); // 抛出异常
} }
if (this.wb.getNumberOfSheets()<sheetIndex){ if (this.wb.getNumberOfSheets()<sheetIndex){ // 检查工作表索引是否有效
throw new RuntimeException("文档中没有工作表!"); throw new RuntimeException("文档中没有工作表!"); // 抛出异常
} }
this.sheet = this.wb.getSheetAt(sheetIndex); this.sheet = this.wb.getSheetAt(sheetIndex); // 获取指定的工作表
this.headerNum = headerNum; this.headerNum = headerNum; // 设置标题行号
log.debug("Initialize success."); log.debug("Initialize success."); // 记录初始化成功的日志
} }
/** /**
@ -101,24 +100,24 @@ public class ImportExcel {
* @param rownum * @param rownum
* @return * @return
*/ */
public Row getRow(int rownum){ public Row getRow(int rownum){ // 获取指定行
return this.sheet.getRow(rownum); return this.sheet.getRow(rownum); // 返回行对象
} }
/** /**
* *
* @return * @return
*/ */
public int getDataRowNum(){ public int getDataRowNum(){ // 获取数据行号
return headerNum+1; return headerNum+1; // 返回标题行号加一
} }
/** /**
* *
* @return * @return
*/ */
public int getLastDataRowNum(){ public int getLastDataRowNum(){ // 获取最后一个数据行号
return this.sheet.getLastRowNum()+headerNum; return this.sheet.getLastRowNum()+headerNum; // 返回最后一行号加标题行号
} }
@ -128,38 +127,37 @@ public class ImportExcel {
* @param column * @param column
* @return * @return
*/ */
public Object getCellValue(Row row, int column) { public Object getCellValue(Row row, int column) { // 获取指定单元格的值
Object val = ""; Object val = ""; // 初始化单元格值
try { try {
Cell cell = row.getCell(column); Cell cell = row.getCell(column); // 获取单元格
if (cell != null) { if (cell != null) { // 检查单元格是否为空
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { // 检查单元格类型
// 当excel 中的数据为数值或日期是需要特殊处理 // 当excel 中的数据为数值或日期是需要特殊处理
if (HSSFDateUtil.isCellDateFormatted(cell)) { if (HSSFDateUtil.isCellDateFormatted(cell)) { // 检查是否为日期格式
double d = cell.getNumericCellValue(); double d = cell.getNumericCellValue(); // 获取数值
Date date = HSSFDateUtil.getJavaDate(d); Date date = HSSFDateUtil.getJavaDate(d); // 转换为Java日期
SimpleDateFormat dformat = new SimpleDateFormat( SimpleDateFormat dformat = new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式
"yyyy-MM-dd"); val = dformat.format(date); // 格式化日期
val = dformat.format(date);
} else { } else {
NumberFormat nf = NumberFormat.getInstance(); NumberFormat nf = NumberFormat.getInstance(); // 获取数字格式化实例
nf.setGroupingUsed(false);// true时的格式1,234,567,890 nf.setGroupingUsed(false); // 设置不使用分组
val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double所以需要转换一下 val = nf.format(cell.getNumericCellValue()); // 格式化数值
} }
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) { } else if (cell.getCellType() == Cell.CELL_TYPE_STRING) { // 检查是否为字符串类型
val = cell.getStringCellValue(); val = cell.getStringCellValue(); // 获取字符串值
} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) { } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) { // 检查是否为公式类型
val = cell.getCellFormula(); val = cell.getCellFormula(); // 获取公式
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { // 检查是否为布尔类型
val = cell.getBooleanCellValue(); val = cell.getBooleanCellValue(); // 获取布尔值
} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) { } else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) { // 检查是否为错误类型
val = cell.getErrorCellValue(); val = cell.getErrorCellValue(); // 获取错误值
} }
} }
} catch (Exception e) { } catch (Exception e) { // 捕获异常
return val; return val; // 返回值
} }
return val; return val; // 返回单元格值
} }
/** /**
@ -167,137 +165,137 @@ public class ImportExcel {
* @param cls * @param cls
* @param groups * @param groups
*/ */
public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{ public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{ // 获取导入数据列表
List<Object[]> annotationList = Lists.newArrayList(); List<Object[]> annotationList = Lists.newArrayList(); // 创建注解列表
// Get annotation field // Get annotation field
Field[] fs = cls.getDeclaredFields(); Field[] fs = cls.getDeclaredFields(); // 获取类的所有字段
for (Field f : fs){ for (Field f : fs){ // 遍历字段
ExcelField ef = f.getAnnotation(ExcelField.class); ExcelField ef = f.getAnnotation(ExcelField.class); // 获取字段上的ExcelField注解
if (ef != null && (ef.type()==0 || ef.type()==2)){ if (ef != null && (ef.type()==0 || ef.type()==2)){ // 检查注解类型
if (groups!=null && groups.length>0){ if (groups!=null && groups.length>0){ // 检查分组
boolean inGroup = false; boolean inGroup = false; // 初始化分组标志
for (int g : groups){ for (int g : groups){ // 遍历分组
if (inGroup){ if (inGroup){ // 如果已经在分组中
break; break; // 跳出循环
} }
for (int efg : ef.groups()){ for (int efg : ef.groups()){ // 遍历注解中的分组
if (g == efg){ if (g == efg){ // 如果分组匹配
inGroup = true; inGroup = true; // 设置标志
annotationList.add(new Object[]{ef, f}); annotationList.add(new Object[]{ef, f}); // 添加到注解列表
break; break; // 跳出循环
} }
} }
} }
}else{ }else{
annotationList.add(new Object[]{ef, f}); annotationList.add(new Object[]{ef, f}); // 添加到注解列表
} }
} }
} }
// Get annotation method // Get annotation method
Method[] ms = cls.getDeclaredMethods(); Method[] ms = cls.getDeclaredMethods(); // 获取类的所有方法
for (Method m : ms){ for (Method m : ms){ // 遍历方法
ExcelField ef = m.getAnnotation(ExcelField.class); ExcelField ef = m.getAnnotation(ExcelField.class); // 获取方法上的ExcelField注解
if (ef != null && (ef.type()==0 || ef.type()==2)){ if (ef != null && (ef.type()==0 || ef.type()==2)){ // 检查注解类型
if (groups!=null && groups.length>0){ if (groups!=null && groups.length>0){ // 检查分组
boolean inGroup = false; boolean inGroup = false; // 初始化分组标志
for (int g : groups){ for (int g : groups){ // 遍历分组
if (inGroup){ if (inGroup){ // 如果已经在分组中
break; break; // 跳出循环
} }
for (int efg : ef.groups()){ for (int efg : ef.groups()){ // 遍历注解中的分组
if (g == efg){ if (g == efg){ // 如果分组匹配
inGroup = true; inGroup = true; // 设置标志
annotationList.add(new Object[]{ef, m}); annotationList.add(new Object[]{ef, m}); // 添加到注解列表
break; break; // 跳出循环
} }
} }
} }
}else{ }else{
annotationList.add(new Object[]{ef, m}); annotationList.add(new Object[]{ef, m}); // 添加到注解列表
} }
} }
} }
// Field sorting // Field sorting
Collections.sort(annotationList, new Comparator<Object[]>() { Collections.sort(annotationList, new Comparator<Object[]>() { // 对注解列表进行排序
@Override @Override
public int compare(Object[] o1, Object[] o2) { public int compare(Object[] o1, Object[] o2) { // 比较两个对象
return new Integer(((ExcelField)o1[0]).sort()).compareTo( return new Integer(((ExcelField)o1[0]).sort()).compareTo( // 根据排序值进行比较
new Integer(((ExcelField)o2[0]).sort())); new Integer(((ExcelField)o2[0]).sort()));
} }
}); });
// Get excel data // Get excel data
List<E> dataList = Lists.newArrayList(); List<E> dataList = Lists.newArrayList(); // 创建数据列表
for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) { for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) { // 遍历数据行
E e = (E)cls.newInstance(); E e = (E)cls.newInstance(); // 创建对象实例
int column = 0; int column = 0; // 初始化列索引
Row row = this.getRow(i); Row row = this.getRow(i); // 获取行对象
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder(); // 创建字符串构建器
for (Object[] os : annotationList){ for (Object[] os : annotationList){ // 遍历注解列表
Object val = this.getCellValue(row, column++); Object val = this.getCellValue(row, column++); // 获取单元格值
if (val != null){ if (val != null){ // 检查值是否为空
ExcelField ef = (ExcelField)os[0]; ExcelField ef = (ExcelField)os[0]; // 获取ExcelField注解
// Get param type and type cast // Get param type and type cast
Class<?> valType = Class.class; Class<?> valType = Class.class; // 初始化值类型
if (os[1] instanceof Field){ if (os[1] instanceof Field){ // 检查是否为字段
valType = ((Field)os[1]).getType(); valType = ((Field)os[1]).getType(); // 获取字段类型
}else if (os[1] instanceof Method){ }else if (os[1] instanceof Method){ // 检查是否为方法
Method method = ((Method)os[1]); Method method = ((Method)os[1]);
if ("get".equals(method.getName().substring(0, 3))){ if ("get".equals(method.getName().substring(0, 3))){ // 检查方法名
valType = method.getReturnType(); valType = method.getReturnType(); // 获取返回类型
}else if("set".equals(method.getName().substring(0, 3))){ }else if("set".equals(method.getName().substring(0, 3))){ // 检查方法名
valType = ((Method)os[1]).getParameterTypes()[0]; valType = ((Method)os[1]).getParameterTypes()[0]; // 获取参数类型
} }
} }
//log.debug("Import value type: ["+i+","+column+"] " + valType); //log.debug("Import value type: ["+i+","+column+"] " + valType);
try { try {
//如果导入的java对象需要在这里自己进行变换。 //如果导入的java对象需要在这里自己进行变换。
if (valType == String.class){ if (valType == String.class){ // 检查值类型
String s = String.valueOf(val.toString()); String s = String.valueOf(val.toString()); // 转换为字符串
if(StringUtils.endsWith(s, ".0")){ if(StringUtils.endsWith(s, ".0")){ // 检查是否以.0结尾
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0"); // 去掉.0
}else{ }else{
val = String.valueOf(val.toString()); val = String.valueOf(val.toString()); // 转换为字符串
} }
}else if (valType == Integer.class){ }else if (valType == Integer.class){ // 检查值类型
val = Double.valueOf(val.toString()).intValue(); val = Double.valueOf(val.toString()).intValue(); // 转换为整数
}else if (valType == Long.class){ }else if (valType == Long.class){ // 检查值类型
val = Double.valueOf(val.toString()).longValue(); val = Double.valueOf(val.toString()).longValue(); // 转换为长整型
}else if (valType == Double.class){ }else if (valType == Double.class){ // 检查值类型
val = Double.valueOf(val.toString()); val = Double.valueOf(val.toString()); // 转换为双精度浮点型
}else if (valType == Float.class){ }else if (valType == Float.class){ // 检查值类型
val = Float.valueOf(val.toString()); val = Float.valueOf(val.toString()); // 转换为浮点型
}else if (valType == Date.class){ }else if (valType == Date.class){ // 检查值类型
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式
val=sdf.parse(val.toString()); val=sdf.parse(val.toString()); // 解析日期
}else{ }else{
if (ef.fieldType() != Class.class){ if (ef.fieldType() != Class.class){ // 检查字段类型
val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString()); val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString()); // 调用getValue方法
}else{ }else{
val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString()); "fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString()); // 动态调用getValue方法
} }
} }
} catch (Exception ex) { } catch (Exception ex) { // 捕获异常
log.info("Get cell value ["+i+","+column+"] error: " + ex.toString()); log.info("Get cell value ["+i+","+column+"] error: " + ex.toString()); // 记录错误日志
val = null; val = null; // 设置值为null
} }
// set entity value // set entity value
if (os[1] instanceof Field){ if (os[1] instanceof Field){ // 检查是否为字段
Reflections.invokeSetter(e, ((Field)os[1]).getName(), val); Reflections.invokeSetter(e, ((Field)os[1]).getName(), val); // 设置字段值
}else if (os[1] instanceof Method){ }else if (os[1] instanceof Method){ // 检查是否为方法
String mthodName = ((Method)os[1]).getName(); String mthodName = ((Method)os[1]).getName(); // 获取方法名
if ("get".equals(mthodName.substring(0, 3))){ if ("get".equals(mthodName.substring(0, 3))){ // 检查方法名
mthodName = "set"+StringUtils.substringAfter(mthodName, "get"); mthodName = "set"+StringUtils.substringAfter(mthodName, "get"); // 转换为set方法名
} }
Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val}); Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val}); // 调用set方法
} }
} }
sb.append(val+", "); sb.append(val+", "); // 添加值到字符串构建器
} }
dataList.add(e); dataList.add(e); // 添加对象到数据列表
log.debug("Read success: ["+i+"] "+sb.toString()); log.debug("Read success: ["+i+"] "+sb.toString()); // 记录读取成功的日志
} }
return dataList; return dataList; // 返回数据列表
} }
} }

@ -1,59 +1,87 @@
// ... existing code ...
/** /**
* Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
// 版权声明,包含版权信息和链接
*/ */
package com.yf.exam.core.utils.excel.annotation; package com.yf.exam.core.utils.excel.annotation;
// 包声明,定义该类所在的包
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
// 导入ElementType类用于定义注解的适用范围
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
// 导入Retention类用于定义注解的保留策略
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
// 导入RetentionPolicy类定义注解的保留策略类型
import java.lang.annotation.Target; import java.lang.annotation.Target;
// 导入Target类用于定义注解的目标
/** /**
* Excel * Excel
* @author jeeplus * @author jeeplus
* @version 2016-03-10 * @version 2016-03-10
*/ */
// 注解类的描述,包含作者和版本信息
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
// 定义该注解可以应用于方法、字段和类
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
// 定义该注解在运行时可用
public @interface ExcelField { public @interface ExcelField {
// 定义ExcelField注解
/** /**
* get.area.nameoffice.name * get.area.nameoffice.name
*
*/ */
String value() default ""; String value() default "";
// 字段名,默认为空字符串
/** /**
* **** * ****
*
*/ */
String title(); String title();
// 字段标题,必填项
/** /**
* 012 * 012
*
*/ */
int type() default 0; int type() default 0;
// 字段类型默认为0导出导入
/** /**
* 0123 * 0123
*
*/ */
int align() default 0; int align() default 0;
// 对齐方式默认为0自动
/** /**
* *
*
*/ */
int sort() default 0; int sort() default 0;
// 字段排序默认为0升序
/** /**
* type * type
*
*/ */
String dictType() default ""; String dictType() default "";
// 字典类型,默认为空字符串
/** /**
* *
*
*/ */
Class<?> fieldType() default Class.class; Class<?> fieldType() default Class.class;
// 字段类型默认为Class.class
/** /**
* *
*
*/ */
int[] groups() default {}; int[] groups() default {};
// 字段归属组,默认为空数组
} }
// ... existing code ...

@ -1,56 +1,57 @@
/** /**
* Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/ */
package com.yf.exam.core.utils.excel.fieldtype; package com.yf.exam.core.utils.excel.fieldtype; // 定义包名
import com.google.common.collect.Lists; import com.google.common.collect.Lists; // 导入Google的Lists工具类
import com.yf.exam.core.utils.StringUtils; import com.yf.exam.core.utils.StringUtils; // 导入自定义的StringUtils工具类
import java.util.List; import java.util.List; // 导入List接口
/** /**
* *
* @author jeeplus * @author jeeplus
* @version 2016-5-29 * @version 2016-5-29
*/ */
public class ListType { public class ListType { // 定义ListType类
/** /**
* *
*/ */
public static Object getValue(String val) { public static Object getValue(String val) { // 定义静态方法getValue接收一个字符串参数
List<String> list = Lists.newArrayList(); List<String> list = Lists.newArrayList(); // 创建一个新的字符串列表
if(!StringUtils.isBlank(val)) { if(!StringUtils.isBlank(val)) { // 检查输入字符串是否为空
for (String s : val.split(",")) { for (String s : val.split(",")) { // 按逗号分割字符串
list.add(s); list.add(s); // 将分割后的字符串添加到列表中
} }
} }
return list; return list; // 返回列表
} }
/** /**
* *
*/ */
public static String setValue(Object val) { public static String setValue(Object val) { // 定义静态方法setValue接收一个对象参数
if (val != null){ if (val != null){ // 检查输入对象是否为null
List<String> list = (List<String>)val; List<String> list = (List<String>)val; // 将对象强制转换为字符串列表
StringBuffer sb = null; StringBuffer sb = null; // 初始化字符串缓冲区
for (String item: list){ for (String item: list){ // 遍历列表中的每个字符串
if(StringUtils.isBlank(item)){ if(StringUtils.isBlank(item)){ // 检查字符串是否为空
continue; continue; // 如果为空,跳过当前循环
} }
if(sb == null){ if(sb == null){ // 如果字符串缓冲区为空
sb = new StringBuffer(item); sb = new StringBuffer(item); // 初始化缓冲区为当前字符串
}else{ }else{
sb.append(",").append(item); sb.append(",").append(item); // 否则,添加逗号和当前字符串
} }
} }
if(sb!=null) { if(sb!=null) { // 如果字符串缓冲区不为空
return sb.toString().replace("[]", ""); return sb.toString().replace("[]", ""); // 返回缓冲区内容并替换"[]"为空
} }
} }
return ""; return ""; // 如果输入对象为null返回空字符串
} }
} }

@ -1,7 +1,6 @@
package com.yf.exam.core.utils.file; package com.yf.exam.core.utils.file; // 包声明
import java.security.MessageDigest;
import java.security.MessageDigest; // 导入MessageDigest类用于生成MD5哈希
/** /**
* MD5 * MD5
@ -11,26 +10,25 @@ import java.security.MessageDigest;
* @author Bool * @author Bool
* @version * @version
*/ */
public class Md5Util { public class Md5Util { // 定义MD5工具类
/** /**
* MD5 * MD5
* @param str * @param str
* @return * @return MD5
*/ */
public static String md5(String str) { public static String md5(String str) { // 定义静态方法md5接受一个字符串参数
try { try { // 开始异常处理
MessageDigest md = MessageDigest.getInstance("MD5"); MessageDigest md = MessageDigest.getInstance("MD5"); // 获取MD5实例
byte[] array = md.digest(str.getBytes("UTF-8")); byte[] array = md.digest(str.getBytes("UTF-8")); // 计算输入字符串的MD5哈希值
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder(); // 创建StringBuilder用于构建结果字符串
for (byte item : array) { for (byte item : array) { // 遍历哈希字节数组
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); // 将每个字节转换为十六进制并添加到StringBuilder
} }
return sb.toString(); return sb.toString(); // 返回最终的MD5哈希字符串
}catch(Exception e) { }catch(Exception e) { // 捕获异常
return null; return null; // 如果发生异常返回null
} }
} }

@ -1,8 +1,7 @@
package com.yf.exam.core.utils.passwd; package com.yf.exam.core.utils.passwd; // 定义包名
import com.yf.exam.core.utils.file.Md5Util; // 导入Md5Util类
import com.yf.exam.core.utils.file.Md5Util; import org.apache.commons.lang3.RandomStringUtils; // 导入RandomStringUtils类
import org.apache.commons.lang3.RandomStringUtils;
/** /**
* *
@ -12,7 +11,7 @@ import org.apache.commons.lang3.RandomStringUtils;
* @author Bool * @author Bool
* @version * @version
*/ */
public class PassHandler { public class PassHandler { // 定义PassHandler类
/** /**
* checkPass: * checkPass:
@ -22,9 +21,9 @@ public class PassHandler {
* @param pass MD5 * @param pass MD5
* @return * @return
*/ */
public static boolean checkPass(String inputPass , String salt , String pass){ public static boolean checkPass(String inputPass , String salt , String pass){ // 定义静态方法checkPass
String pwdMd5 = Md5Util.md5(inputPass); String pwdMd5 = Md5Util.md5(inputPass); // 将输入密码进行MD5加密
return Md5Util.md5(pwdMd5 + salt).equals(pass); return Md5Util.md5(pwdMd5 + salt).equals(pass); // 校验加密后的密码与数据库密码是否一致
} }
@ -35,23 +34,23 @@ public class PassHandler {
* @param inputPass * @param inputPass
* @return PassInfo * @return PassInfo
*/ */
public static PassInfo buildPassword(String inputPass) { public static PassInfo buildPassword(String inputPass) { // 定义静态方法buildPassword
//产生一个6位数的随机码 //产生一个6位数的随机码
String salt = RandomStringUtils.randomAlphabetic(6); String salt = RandomStringUtils.randomAlphabetic(6); // 生成6位随机字母作为盐
//加密后的密码 //加密后的密码
String encryptPassword = Md5Util.md5(Md5Util.md5(inputPass)+salt); String encryptPassword = Md5Util.md5(Md5Util.md5(inputPass)+salt); // 对输入密码和盐进行双重MD5加密
//返回对象 //返回对象
return new PassInfo(salt,encryptPassword); return new PassInfo(salt,encryptPassword); // 返回包含盐和加密密码的PassInfo对象
} }
public static void main(String[] args) { public static void main(String[] args) { // 主方法
PassInfo info = buildPassword("190601"); PassInfo info = buildPassword("190601"); // 调用buildPassword方法生成密码信息
System.out.println(info.getPassword()); System.out.println(info.getPassword()); // 输出加密后的密码
System.out.println(info.getSalt()); System.out.println(info.getSalt()); // 输出生成的盐
} }
} }

@ -1,38 +1,45 @@
package com.yf.exam.core.utils.passwd; package com.yf.exam.core.utils.passwd; // 定义包名
/** /**
* *
* ClassName: PassInfo <br/> * ClassName: PassInfo <br/>
* date: 2018213 7:13:50 <br/> * date: 2018213 7:13:50 <br/>
* *
* @author Bool * @author Bool // 作者
* @version * @version // 版本信息
*/ */
public class PassInfo { public class PassInfo { // 定义PassInfo类
//密码随机串码 // 密码随机串码
private String salt; private String salt; // 声明salt变量
//MD5后的密码 // MD5后的密码
private String password; private String password; // 声明password变量
// 构造函数初始化salt和password
public PassInfo(String salt, String password) { public PassInfo(String salt, String password) {
super(); super(); // 调用父类构造函数
this.salt = salt; this.salt = salt; // 设置salt
this.password = password; this.password = password; // 设置password
} }
// 获取salt
public String getSalt() { public String getSalt() {
return salt; return salt; // 返回salt
} }
// 设置salt
public void setSalt(String salt) { public void setSalt(String salt) {
this.salt = salt; this.salt = salt; // 更新salt
} }
// 获取password
public String getPassword() { public String getPassword() {
return password; return password; // 返回password
} }
// 设置password
public void setPassword(String password) { public void setPassword(String password) {
this.password = password; this.password = password; // 更新password
} }
} }

Loading…
Cancel
Save