本人原创:https://mp.csdn.net/console/editor/html/105723714
传统的单表操作需要写一套curd的controller层,service层,dao层,mapper xml文件,效率底下。
现在改良的快速开发有freemaker模板生成传统的以上层的文件。
最近几年tk mybatis把dao层和mapper文件通过反射和代理简化了之前的繁琐。
借鉴tk mybatis思路 可以把controller层和servce层通过基类,泛型,反射再一步简化其中的繁琐。
抽象controller
package com.zytool.easyrestful.core;
import com.zytool.easyrestful.core.bean.ResultBean;
import com.zytool.easyrestful.core.utils.HttpRequestUtil;
import io.swagger.annotations.ApiOperation;
import lombok.Setter;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
public class GenericController<T extends GenericEntity> {
@Setter
private GenericService<T> genericService;
@ApiOperation("查询列表")
@GetMapping("/list")
public Object list(Pageable pageable, HttpServletRequest request) {
return ResultBean.success(genericService.selectByPage(pageable, HttpRequestUtil.getRequestMap(request)));
}
@ApiOperation("查询详情")
@GetMapping("/get")
public Object get(@RequestParam int id) {
return ResultBean.success(genericService.getById(id));
}
@ApiOperation("保存")
@PostMapping("/save")
public Object save(@RequestBody T entity) {
return ResultBean.success(genericService.save(entity));
}
@ApiOperation("删除")
@PostMapping("/delete")
public Object delete(@RequestBody T entity) {
return ResultBean.success(genericService.delete(entity));
}
}
抽象service
package com.zytool.easyrestful.core;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zytool.easyrestful.core.condition.ConditionExampleBuilder;
import com.zytool.easyrestful.core.utils.ClassUtil;
import lombok.Setter;
import org.springframework.data.domain.Pageable;
import tk.mybatis.mapper.entity.Example;
import java.util.Map;
public class GenericService<T extends GenericEntity> {
@Setter
private GenericMapper<T> genericMapper;
public PageInfo<T> selectByPage(Pageable pageRequest, Map<String, String> params) {
PageHelper.startPage(pageRequest.getPageNumber(), pageRequest.getPageSize());
Class entityClazz = ClassUtil.getGenericClass(this.getClass());
Example example = ConditionExampleBuilder.build(entityClazz, params);
return new PageInfo<>(genericMapper.selectByExample(example));
}
public T getById(int id) {
return genericMapper.selectByPrimaryKey(id);
}
public int save(T entity) {
if (entity.getId() > 0) {
return genericMapper.updateEntity(entity);
}
return genericMapper.insertEntity(entity);
}
public int delete(T entity) {
return genericMapper.deleteByPrimaryKey(entity.getId());
}
}
抽象mapper
package com.zytool.easyrestful.core;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
import java.util.Date;
public interface GenericMapper<T extends GenericEntity> extends Mapper<T>, MySqlMapper<T> {
default int insertEntity(T t) {
t.setCreateTime(new Date());
return insert(t);
}
default int updateEntity(T t) {
t.setUpdateTime(new Date());
return updateByPrimaryKey(t);
}
}
抽象实体
package com.zytool.easyrestful.core;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Id;
import java.util.Date;
@Data
@ApiModel
public class GenericEntity {
@Id
private Integer id;
private Integer deleteFlag;
private Integer version;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}
针对单表查询条件,controller使用map接收, 通过比较参数名和数据库实体字段识别是否查询该字段,再使用自定义condition注解解析需要的条件和方法,这样可以灵活的查询需要查询的列。
代码如下
package com.zytool.easyrestful.core.condition;
import cn.hutool.core.util.StrUtil;
import com.zytool.easyrestful.core.annotation.Condition;
import com.zytool.easyrestful.core.matcher.Match;
import com.zytool.easyrestful.core.utils.EntityUtil;
import tk.mybatis.mapper.entity.Example;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
public class ConditionExampleBuilder {
public static Example build(Class entityClazz, Map<String, String> params) {
List<Field> fieldList = EntityUtil.getFields(entityClazz);
Example example = new Example(entityClazz);
Example.Criteria criteria = example.createCriteria();
for (Field field : fieldList) {
String fieldName = field.getName();
String fieldValue = params.get(fieldName);
Condition condition = field.getAnnotation(Condition.class);
if (condition != null && (!StrUtil.isBlank(fieldValue) || condition.match() == Match.RANGE)) {
if (condition.match() == Match.EQ) {
criteria.andEqualTo(fieldName, fieldValue);
} else if (condition.match() == Match.GT) {
criteria.andGreaterThan(fieldName, fieldValue);
} else if (condition.match() == Match.LT) {
criteria.andLessThan(fieldName, fieldValue);
} else if (condition.match() == Match.GTEQ) {
criteria.andGreaterThanOrEqualTo(fieldName, fieldValue);
} else if (condition.match() == Match.LTEQ) {
criteria.andGreaterThanOrEqualTo(fieldName, fieldValue);
} else if (condition.match() == Match.LIKE) {
criteria.andLike(fieldName, " %" + fieldValue + "%");
} else if (condition.match() == Match.LLIKE) {
criteria.andLike(fieldName, " %" + fieldValue);
} else if (condition.match() == Match.RLIKE) {
criteria.andLike(fieldName, fieldValue + "%");
} else if (condition.match() == Match.RANGE) {
criteria.andBetween(fieldName, params.get(condition.param1()), params.get(condition.param2()));
}
}
}
return example;
}
}
再通过代码生成工具生成继承上述类的子类,代码结构得到大量的简化和优化。
简化后一套curd只需要一下代码
package com.zytool.easyrestful.controller;
import com.zytool.easyrestful.core.GenericController;
import com.zytool.easyrestful.core.bean.ResultBean;
import com.zytool.easyrestful.entity.UserEntity;
import com.zytool.easyrestful.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController extends GenericController<UserEntity> {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
super.setGenericService(userService);
}
}
package com.zytool.easyrestful.service;
import com.zytool.easyrestful.core.GenericService;
import com.zytool.easyrestful.entity.UserEntity;
import com.zytool.easyrestful.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService extends GenericService<UserEntity> {
private UserMapper userMapper;
@Autowired
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
super.setGenericMapper(userMapper);
}
}
package com.zytool.easyrestful.mapper;
import com.zytool.easyrestful.core.GenericMapper;
import com.zytool.easyrestful.entity.UserEntity;
import org.apache.ibatis.annotations.Param;
public interface UserMapper extends GenericMapper<UserEntity> {
}
package com.zytool.easyrestful.entity;
import com.zytool.easyrestful.core.GenericEntity;
import com.zytool.easyrestful.core.annotation.Condition;
import com.zytool.easyrestful.core.matcher.Match;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Table;
@Data
@Table(name = "user")
@ApiModel(value = "用户表", reference = "UserEntity")
public class UserEntity extends GenericEntity {
@ApiModelProperty("姓名")
@Condition(match = Match.LIKE)
private String name;
@ApiModelProperty("年龄")
@Condition(match = Match.RANGE, param1 = "ageFrom", param2 = "ageTo")
private Integer age;
@ApiModelProperty("性别")
@Condition
private String sex;
@ApiModelProperty("介绍")
private String introduce;
}
基本只要定义实体就可以,其他层通过工具生成或者手写都很方便。
可以把上述类封装成jar包,对于大量单表操作的项目,可以实现快速开发。