package com.shawn.web.controller.base; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import com.fasterxml.jackson.annotation.JsonIgnore; import com.shawn.constant.PageConstant; import com.shawn.model.bean.PageBean; import com.shawn.model.dto.PaginatedResult; import com.shawn.model.dto.ResultMessage; import com.shawn.service.base.BaseServiceInterface; import com.shawn.util.FgObjectUtil; import com.shawn.util.PageUtil; import com.shawn.web.exception.MyException; import com.shawn.web.exception.ResourceNotFoundException; import lombok.extern.apachecommons.CommonsLog; import lombok.extern.slf4j.Slf4j; /* * 一:@RequestParam 与 @RequestBody * 1、@RequestParam 用来处理 content-type 为 application/x-www-form-urlencoded 编码的内容 * 2、@RequestBody 用来处理除content-type 为 application/x-www-form-urlencoded 编码的内容 * 如 application/json,application/xml * * 二:在不给定注解的情况下,参数默认是怎么绑定的? * 1、若为简单类型:调用@RequestParam * 2、若为复杂类型,如对象,调用@ModelAttribute */ @Slf4j public abstract class BaseController { protected BaseServiceInterface baseService; public BaseController(BaseServiceInterface service){ this.baseService = service; } /** * 自定义获取各model的id * @param entity * @return * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws SecurityException * @throws NoSuchMethodException */ protected ID getEntityId(ENTITY entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Class entityClass = entity.getClass(); Method m = entityClass.getDeclaredMethod("getPrimaryKey"); m.setAccessible(true);//因为写成private 所以这里必须设置 return (ID)m.invoke(entity); } /** * 自定义设置各model的id * @param entity * @return * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws SecurityException * @throws NoSuchMethodException */ protected void setEntityId(ENTITY entity,ID id) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Class entityClass = entity.getClass(); Method m = entityClass.getDeclaredMethod("hasPrimaryKey"); m.setAccessible(true);//因为写成private 所以这里必须设置 boolean flag = (boolean)m.invoke(entity); if(flag) { Object property = getEntityId(entity);// 调用getter方法获取属性值 Method m2 = entityClass.getDeclaredMethod("setPrimaryKey",FgObjectUtil.getPropertyType(property)); m2.setAccessible(true);//因为写成private 所以这里必须设置 m2.invoke(entity,id); } /*if(id instanceof String) { Method m = entityClass.getDeclaredMethod("setPrimaryKey",String.class); m.setAccessible(true);//因为写成private 所以这里必须设置 m.invoke(entity,id); }else if(id instanceof Long){ Method m = entityClass.getDeclaredMethod("setPrimaryKey",Long.class); m.setAccessible(true);//因为写成private 所以这里必须设置 m.invoke(entity,id); }else if(id instanceof Integer) { Method m = entityClass.getDeclaredMethod("setPrimaryKey",Integer.class); m.setAccessible(true);//因为写成private 所以这里必须设置 m.invoke(entity,id); }*/ } /** * 自定义new 一个实体对应的ENTITYExample * @return */ protected abstract ENTITYExample createNewExample(); /** * 自定义获取model 表的名称 */ protected String getResourceName() { return baseService.getResourceName(); } /** * 根据id获取一条实体表记录 * @param id * @return */ @GetMapping("/{id}") public ResponseEntity getEntityById(@PathVariable ID id) { ENTITY entity = baseService.selectEntityById(id); if(entity==null){ throw new ResourceNotFoundException() .setResourceName(getResourceName()) .setId(id.toString()); } return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(entity) .setMessage("SUCCESS")); } /** * 新增实体表数据 * @param entity * @return * @throws SecurityException * @throws NoSuchMethodException * @throws InstantiationException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @PostMapping("/postEntity") public ResponseEntity postEntity(@RequestBody ENTITY entity) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { Class entityClass = entity.getClass(); setEntityId(entity, (ID)baseService.generateUniqueID()); Integer i = baseService.insert(entity); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(i) .setMessage("SUCCESS")); } /** * 根据id 更新实体表 * @param id * @param entity * @return * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @PutMapping("/{id}") public ResponseEntity putEntity(@PathVariable ID id, @RequestBody ENTITY entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { log.debug("id:"+id); assertEntityExist(id); setEntityId(entity,id); baseService.updateById(entity); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(entity) .setMessage("SUCCESS")); } /** * 根据id删除实体表数据 * @param id * @return */ @DeleteMapping("/{id}") public ResponseEntity deleteEntity(@PathVariable ID id) { assertEntityExist(id); baseService.deleteById(id); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setMessage("SUCCESS")); } @GetMapping("/selectAllByPage") public ResponseEntity selectAllByPage(@RequestParam(value = "offset", required = false)String offsetString, @RequestParam(value = "limit", required = false) String limitString, @RequestParam(value = "order", required = false) String order ) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { // Parse request parameters int offset = PageUtil.parseOffset(offsetString, PageConstant.OFFSET); int limit = PageUtil.parsePerPage(limitString, PageConstant.LIMIT); ENTITYExample example = createNewExample(); Class exampleClass = example.getClass(); Method m = exampleClass.getDeclaredMethod("setLimit", Integer.class); m.setAccessible(true);//因为写成private 所以这里必须设置 m.invoke(exampleClass.newInstance(), limit); Method m2 = exampleClass.getDeclaredMethod("setOffset", Integer.class); m2.setAccessible(true);//因为写成private 所以这里必须设置 m2.invoke(exampleClass.newInstance(), offset); return ResponseEntity .ok(new PaginatedResult() .setCode(true) .setData(baseService.selectByOption(example)) .setTotal(baseService.selectCount(null).intValue())); } /** * 获取实体表所有数据 * @return */ @GetMapping("/selectAll") public ResponseEntity selectAll() { List entityList = baseService.selectByOption(null); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(entityList) .setMessage("SUCCESS")); } /** * 获取实体表总记录数 * @return */ @GetMapping("/selectCount") public ResponseEntity getCount() { Long result = baseService.selectCount(null); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(result) .setMessage("SUCCESS")); } /** * 根据表字段条件查询单表数据 * 只作用于单表,并且所有条件都为EqualTo * 字段加后缀_like,则做模糊查询 * 字段加后缀_start,则做>=查询 * 字段加后缀_end,则做<=查询 * */ @GetMapping("/selectEntityByEqualToOption") public ResponseEntity selectEntityByEqualToOption(ENTITYParam param) { ENTITYExample example = (ENTITYExample) entity2example(param,createNewExample()); List entityList = baseService.selectByOption(example); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(entityList) .setMessage("SUCCESS")); } /** * 根据表字段条件查询单表数据 * 只作用于单表,并且所有条件都为EqualTo * 字段加后缀_like,则做模糊查询 * 字段加后缀_start,则做>=查询 * 字段加后缀_end,则做<=查询 * */ @GetMapping("/selectEntityByEqualToOptionByPage") public ResponseEntity selectEntityByEqualToOptionByPage(ENTITYParam param) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { ENTITYExample example = (ENTITYExample) entity2example(param,createNewExample()); List entityList = baseService.selectByOption(example); return ResponseEntity .ok(new PaginatedResult() .setCode(true) .setData(entityList) .setTotal(baseService.selectCount(example).intValue())); } /** * 批量更新 */ @PutMapping("/updateBatchByIdList") public ResponseEntity updateBatchByIdList(@RequestBody ENTITYParam param) { int i= baseService.updateBatchByIdList(param); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(i) .setMessage("批量更新"+i+"条数据")); } /** * 批量删除 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws SecurityException * @throws NoSuchMethodException */ @DeleteMapping("/deleteBatchByIdList") public ResponseEntity deleteBatchByIdList(@RequestBody ENTITYParam param) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Method method = (Method) param.getClass().getMethod("getPrimaryKeyList"); List primaryKeyList = (List)method.invoke(param);//获取主键list int i= baseService.deleteBatchByIdList(primaryKeyList); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(i) .setMessage("批量删除"+i+"条数据")); } /** * 批量新增 * @throws ParseException * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @PostMapping("/batchInsert") public ResponseEntity batchInsert(@RequestBody ENTITYParam param) throws ParseException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method method = (Method) param.getClass().getMethod("getEntityList"); List entityList = (List)method.invoke(param);//获取实体list for (ENTITY entity : entityList) { setEntityId(entity, (ID)baseService.generateUniqueID()); } int i= baseService.insertBatch(entityList); return ResponseEntity .status(HttpStatus.OK) .body(new ResultMessage() .setCode(true) .setData(i) .setMessage("批量新增"+i+"条数据")); } /********************************** HELPER METHOD ***********************************/ protected ENTITY assertEntityExist(ID id) { return baseService .selectById(id) .orElseThrow(() -> new ResourceNotFoundException() .setResourceName(getResourceName()) .setId(id.toString())); } /** * 将实体的字段自动转为example的EqualTo * @param entity * @param example * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected Object entity2example(Object entity,Object example){ try { Class exampleClass = example.getClass(); Method createCriteriaMethod = (Method) exampleClass.getMethod("createCriteria"); Object criteria = createCriteriaMethod.invoke(example);//生成criteria Class criteriaClass = criteria.getClass(); //实体 Class entityClass = entity.getClass(); Field[] fields = entityClass.getDeclaredFields(); ArrayList fieldList= new ArrayList(); for (Field field : fields) { fieldList.add(field); } //获取实体类所有父类的属性 fieldList = FgObjectUtil.getAllFields(entityClass,fieldList); for (Field field : fieldList) { String nameKey = field.getName(); if("serialVersionUID".equals(nameKey)){ continue; } if("distinct".equals(nameKey)) { Method entityMethod = (Method) entityClass.getMethod("is" + FgObjectUtil.getMethodName(nameKey)); Object property = entityMethod.invoke(entity);// 调用getter方法获取属性值 if(null ==property || "".equals(property)){ continue; } Method m = exampleClass.getMethod("set"+ FgObjectUtil.getMethodName(nameKey), boolean.class); m.invoke(example, property); continue; } Method entityMethod = (Method) entityClass.getMethod("get" + FgObjectUtil.getMethodName(nameKey)); Object property = entityMethod.invoke(entity);// 调用getter方法获取属性值 if(null ==property || "".equals(property)){ continue; } if("orderByClause".equals(nameKey)||"limit".equals(nameKey)||"offset".equals(nameKey)) { Method m = exampleClass.getMethod("set"+ FgObjectUtil.getMethodName(nameKey), FgObjectUtil.getPropertyType(property)); m.invoke(example, property); }else if(nameKey.endsWith("_start")||nameKey.endsWith("_end")) { String nameKey2 =nameKey.replace("_start", "").replace("_end", ""); if(nameKey.endsWith("_start")) { Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"GreaterThanOrEqualTo",FgObjectUtil.getPropertyType(property)); criteriaMethod.invoke(criteria,property); }else { Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"LessThanOrEqualTo",FgObjectUtil.getPropertyType(property)); criteriaMethod.invoke(criteria,property); } }else if(nameKey.endsWith("_like")){ String nameKey2 =nameKey.replace("_like", ""); //like 参数必须为string Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"Like",String.class); criteriaMethod.invoke(criteria,"%"+property.toString()+"%"); }else { Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey)+"EqualTo",FgObjectUtil.getPropertyType(property)); criteriaMethod.invoke(criteria,property); } } return example; } catch (Exception e) { log.error(e.getMessage()); return null; } } }