整体结构:
common公共层
constants包
-- ResultSetEnum 响应结果集枚举类vo包
-- ResultSet全局统一响应结果类util包
-- ExceptionUtil 打印异常堆栈信息类handler包
-- GlobalExceptionHandler 统一异常处理类exception包
-- GuLiException 自定义异常类
接下来直接上代码:
1. ResultSetEnum 响应结果集枚举类
import lombok.Getter;
@Getter
public enum ResultSetEnum {
SUCCESS(true,20000,"成功"),
UNKNOWN_REASON(false,20001,"未知错误"),
BAD_SQL_GRAMMAR(false,21001,"sql语法错误"),
JSON_PARSE_ERROR(false,21002,"json解析异常"),
PARAM_ERROR(false,21003,"参数不正确"),
FILE_UPLOAD_ERROR(false,21004,"文件上传错误"),
EXCEL_DATA_IMPORT_ERROR(false,21005,"EXCEL数据导入错误");
/** 响应是否成功 */
private Boolean success;
/** 返回码 */
private Integer code;
/** 返回消息 */
private String message;
ResultSetEnum(Boolean success, Integer code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
}
2. ResultSet全局统一响应结果类
import com.common.constants.ResultSetEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data // import lombok.Data;GetSet注解
@ApiModel(value = "全局统一返回结果")
public class ResultSet {
@ApiModelProperty(value = "是否成功")
private Boolean success;
@ApiModelProperty(value = "返回码")
private Integer code;
@ApiModelProperty(value = "返回消息")
private String message;
@ApiModelProperty(value = "返回数据")
private Map<String,Object> data = new HashMap<String, Object>();
/** 私有构造方法,使外界无法new */
private ResultSet(){}
/** 响应成功静态方法 */
public static ResultSet ok(){ // 公开静态方法,实例一个创建好的对象提供给外界
ResultSet resultSet = new ResultSet();
resultSet.setSuccess(ResultSetEnum.SUCCESS.getSuccess());
resultSet.setCode(ResultSetEnum.SUCCESS.getCode());
resultSet.setMessage(ResultSetEnum.SUCCESS.getMessage());
return resultSet;
}
/** 响应失败静态方法 */
public static ResultSet error(){
ResultSet resultSet = new ResultSet();
resultSet.setSuccess(ResultSetEnum.UNKNOWN_REASON.getSuccess());
resultSet.setCode(ResultSetEnum.UNKNOWN_REASON.getCode());
resultSet.setMessage(ResultSetEnum.UNKNOWN_REASON.getMessage());
return resultSet;
}
/** 返回数据集合 */
public ResultSet data(Map<String,Object> map){
this.setData(map);
return this;
}
/** 返回数据集合 */
public ResultSet data(String key,Object value){
this.data.put(key,value);
return this;
}
/** 自定义信息 */
public ResultSet message(String message){
this.setMessage(message);
return this;
}
/** 自定义错误码 */
public ResultSet code(Integer code){
this.setCode(code);
return this;
}
/** 自定义是否成功 */
public ResultSet success(Boolean success){
this.setSuccess(success);
return this;
}
/** 枚举值赋值给结果集 */
public static ResultSet setResult(ResultSetEnum resultSetEnum){
ResultSet resultSet = new ResultSet();
resultSet.setSuccess(resultSetEnum.getSuccess());
resultSet.setCode(resultSetEnum.getCode());
resultSet.setMessage(resultSetEnum.getMessage());
return resultSet;
}
}
3. ExceptionUtil 打印异常堆栈信息工具类
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
public class ExceptionUtil {
public static String getMessage(Exception e){
StringWriter sw = null;
PrintWriter pw = null;
try{
sw = new StringWriter();
pw = new PrintWriter(sw);
// 将出错误的信息输出到printWriter
e.printStackTrace(pw);
pw.flush();
sw.flush();
}finally {
if (sw != null){
try {
sw.close();
}catch (IOException e1){
e1.printStackTrace();
}
}
if (pw != null){
pw.close();
}
}
return sw.toString();
}
}
4. GlobalExceptionHandler 统一异常处理类
import com.common.constants.ResultSetEnum;
import com.common.exception.GuLiException;
import com.common.util.ExceptionUtil;
import com.common.vo.ResultSet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/** 未知异常 */
@ExceptionHandler(Exception.class)
@ResponseBody
public ResultSet error(Exception e){
// e.printStackTrace(); // 输出异常堆栈信息
log.error(e.getMessage());
return ResultSet.error();
}
/** sql语法异常 */
@ExceptionHandler(BadSqlGrammarException.class)
@ResponseBody
public ResultSet error(BadSqlGrammarException e){
// e.printStackTrace(); // 输出异常堆栈信息
log.error(e.getMessage());
return ResultSet.setResult(ResultSetEnum.BAD_SQL_GRAMMAR);
}
/** json解析异常 */
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public ResultSet error(HttpMessageNotReadableException e){
// e.printStackTrace(); // 输出异常堆栈信息
log.error(e.getMessage());
return ResultSet.setResult(ResultSetEnum.JSON_PARSE_ERROR);
}
/** 自定义异常 */
@ExceptionHandler(GuLiException.class)
@ResponseBody
public ResultSet error(GuLiException e){
// e.printStackTrace(); // 输出异常堆栈信息
log.error(ExceptionUtil.getMessage(e));
return ResultSet.error().message(e.getMessage()).code(e.getCode());
}
}
5. GuLiException 自定义异常类
import com.common.constants.ResultSetEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "自定义全局异常类")
public class GuLiException extends RuntimeException{
@ApiModelProperty(value = "状态码")
private Integer code;
/**
* 接收状态码和错误消息
* @param code
* @param message
*/
public GuLiException(Integer code,String message){
super(message);
this.code = code;
}
public GuLiException(ResultSetEnum resultSetEnum){
super(resultSetEnum.getMessage());
this.code = resultSetEnum.getCode();
}
@Override
public String toString() {
return "GuLiException{" +
"code=" + code +
",message=" + this.getMessage() +
'}';
}
}
写一个service接口
import com.edu.entity.Subject;
import com.baomidou.mybatisplus.extension.service.IService;
import com.edu.vo.SubjectNestedVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface SubjectService extends IService<Subject> {
List<String> batchImport(MultipartFile file) throws Exception; //lst集合封装错误数据
List<SubjectNestedVo> nestedList();
}
实现类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.util.ExcelImportUtil;
import com.edu.entity.Subject;
import com.edu.mapper.SubjectMapper;
import com.edu.service.SubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.vo.SubjectNestedVo;
import com.edu.vo.SubjectVo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {
@Override
public List<String> batchImport(MultipartFile file) throws Exception{
// 错误消息
List<String> errorMsg = new ArrayList<>();
// 创建工具类对象
ExcelImportUtil excelHSSFUtil = new ExcelImportUtil(file.getInputStream());
// 获取工作表
Sheet sheet = excelHSSFUtil.getSheet();
int rowCount = sheet.getPhysicalNumberOfRows();
if (rowCount <= 1){
errorMsg.add("请填写数据");
return errorMsg;
}
for (int rowNum = 1; rowNum < rowCount; rowNum++) {
Row rowData = sheet.getRow(rowNum);
if (rowData != null){
// 获取一级分类
String levelOneValue = "";
Cell levelOneCell = rowData.getCell(0);
if (levelOneCell != null){
levelOneValue = excelHSSFUtil.getCellValue(levelOneCell).trim();
if (StringUtils.isEmpty(levelOneValue)){
errorMsg.add("第" + (rowNum + 1) + "行一级分类为空");
continue;
}
}
// 判断一级分类是否重复
Subject subject = this.getByTitle(levelOneValue);
String parentId = null;
if (subject == null){ // 如果为null,将一级分类存入数据库
Subject subjectLevelOne = new Subject();
subjectLevelOne.setTitle(levelOneValue);
subjectLevelOne.setSort(rowNum);
baseMapper.insert(subjectLevelOne); // 向数据库插入数据
parentId = subjectLevelOne.getId(); // 父id为二级分类做准备
}else { // 不为null则代表重复。只取父id
parentId = subject.getId();
}
// 获取二级分类
String levelTwoValue = "";
Cell levelTwoCell = rowData.getCell(1);
if (levelTwoCell != null){
levelTwoValue = excelHSSFUtil.getCellValue(levelTwoCell).trim();
if (StringUtils.isEmpty(levelTwoValue)){
errorMsg.add("第" + (rowNum + 1) + "行二级分类为空");
continue;
}
}
// 判断二级分类是否重复
Subject subject2 = this.getByTitle(levelTwoValue, parentId);
Subject subjectLevelTwo = null;
if (subject2 == null){ // 如果为null,将二级分类存入数据库
subjectLevelTwo = new Subject();
subjectLevelTwo.setTitle(levelTwoValue);
subjectLevelTwo.setParentId(parentId);
subjectLevelTwo.setSort(rowNum);
baseMapper.insert(subjectLevelTwo); // 向数据库插入数据
}
}
}
return errorMsg;
}
@Override
public List<SubjectNestedVo> nestedList() {
//最终要的到的数据列表
ArrayList<SubjectNestedVo> subjectNestedVoArrayList = new ArrayList<>();
//获取一级分类数据记录
QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0);
queryWrapper.orderByAsc("sort", "id");
List<Subject> subjects = baseMapper.selectList(queryWrapper);
//获取二级分类数据记录
QueryWrapper<Subject> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.ne("parent_id", 0);
queryWrapper2.orderByAsc("sort", "id");
List<Subject> subSubjects = baseMapper.selectList(queryWrapper2);
//填充一级分类vo数据
int count = subjects.size();
for (int i = 0; i < count; i++) {
Subject subject = subjects.get(i);
//创建一级类别vo对象
SubjectNestedVo subjectNestedVo = new SubjectNestedVo();
BeanUtils.copyProperties(subject, subjectNestedVo);
subjectNestedVoArrayList.add(subjectNestedVo);
//填充二级分类vo数据
ArrayList<SubjectVo> subjectVoArrayList = new ArrayList<>();
int count2 = subSubjects.size();
for (int j = 0; j < count2; j++) {
Subject subSubject = subSubjects.get(j);
if(subject.getId().equals(subSubject.getParentId())){
//创建二级类别vo对象
SubjectVo subjectVo = new SubjectVo();
BeanUtils.copyProperties(subSubject, subjectVo);
subjectVoArrayList.add(subjectVo);
}
}
subjectNestedVo.setChildren(subjectVoArrayList);
}
return subjectNestedVoArrayList;
}
/** 根据分类名称查询这个一级分类是否存在 */
private Subject getByTitle(String title){
QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("title",title); // 查课程名称是否相同
queryWrapper.eq("parent_id","0"); // 一级分类是否为0
return baseMapper.selectOne(queryWrapper);
}
/** 根据分类名称和父类id查询这个二级分类中是否存在 */
private Subject getByTitle(String title,String parentId){
QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("title",title); // 查课程名称是否相同
queryWrapper.eq("parent_id",parentId); // 当前父id和表中父类id是否相同
return baseMapper.selectOne(queryWrapper);
}
}
controller方法
@RestController
@RequestMapping("/admin/edu/subject")
@CrossOrigin //跨域
@Api(description = "课程科目管理")
@Slf4j
public class SubjectAdminController {
@Autowired
private SubjectService subjectService;
/** excel导入科目 */
@ApiOperation(value = "excel导入科目")
@PostMapping("/import")
public ResultSet batchImport(
@ApiParam(name = "file",value = "excel文件",required = true)
@RequestParam("file") MultipartFile file){
try {
List<String> errorMsg = subjectService.batchImport(file);
if (errorMsg.size() == 0){
return ResultSet.ok().message("批量数据导入成功");
}else {
return ResultSet.error().message("部分数据导入失败").data("errorMsgList",errorMsg);
}
} catch (Exception e) {
log.error(e.getMessage());
throw new GuLiException(ResultSetEnum.EXCEL_DATA_IMPORT_ERROR);
}
}
/** 获取分类列表 */
@ApiOperation(value = "嵌套数据列表")
@GetMapping("")
public ResultSet nestedList(){
List<SubjectNestedVo> subjectNestedVoList = subjectService.nestedList();
return ResultSet.ok().data("items", subjectNestedVoList);
}
}