快速开发平台 fast_security_admin:SpringBoot+Mybatis-Plus+反射 通用开发接口
Posted liu++
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速开发平台 fast_security_admin:SpringBoot+Mybatis-Plus+反射 通用开发接口相关的知识,希望对你有一定的参考价值。
快速开发平台 fast_security_admin(一):SpringBoot+Mybatis-Plus+反射 通用开发接口
需求提出
之前使用mybatis每个实体类都要写getAll()、getById()、update()、save()、remove(),有大量重复代码,那么用了mybatis-plus好一些不用写重复的sql了,但是还要写重复的service、controller以及前端页面
。
解决方案(思路)
第一步就是写通用接口,也就是本篇博客介绍的内容,通过传入字符串调用哪个Entity的Service,由于使用了Mybatis-plus每个Service都有list()、getById()、remove(),这就使实现成为可能,在后面会介绍错误或者说不好的思路。
第二步,数据库创建一个表头表,以及菜单表,在下一篇博客介绍。
第三步,前端vue组件开发,所有的数据都动态的。
暂时没有图,以后做成了再回来补图片。
具体实现
目录结构
简单介绍一下,Fast**是本次重点类,其余的是demo,比如说UserAuths,换成User也一样。
demo是什么样的
以UserAuths为例
UserAuths实体类,使用mybatisplus标注@TableId
@Data
public class UserAuths implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "user_id", type = IdType.AUTO)
private Integer userId;
private Integer identityTypeId;
private String identifier;
private String credential;
}
UserAuthsMapper,mybatisplus自动生成的暂时什么都不用动,以后需要自己写复杂sql,再在里面加方法,mapper的xml文件不展示了都是自动生成的。
@Repository
public interface UserAuthsMapper extends BaseMapper<UserAuths> {
}
UserAuthsService,同样是自动生成的,暂时不用动
public interface UserAuthsService extends IService<UserAuths>{
}
UserAuthsServiceImpl,同样是自动生成的,暂时不用动。
@Service
public class UserAuthsServiceImpl extends ServiceImpl<UserAuthsMapper, UserAuths> implements UserAuthsService {}
关键代码:Fast**
ServerResponse是统一返回vo封装。
FastService
public interface FastService {
ServerResponse list(String entity) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
ServerResponse getById(String entity,Integer id) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException;
ServerResponse removeById(String entity,Integer id) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
}
重点FastServiceImpl
@Service
public class FastServiceImpl implements FastService {
@Autowired
private ApplicationContext applicationContext;
//根据传入的字符串获取ServiceImpl的bean然后利用反射调用方法,因为是使用mybatis-plus所以里面咱们自己不写,它也有继承的方法。
@Override
public ServerResponse list(String entity) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
Object list = c.getMethod("list").invoke(bean);
return ServerResponse.succese(list);
}
@Override
public ServerResponse getById(String entity, Integer id) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
Object getById = c.getMethod("getById", new Class[]{Serializable.class}).invoke(bean, id);
return ServerResponse.succese(getById);
}
@Override
public ServerResponse updateById(String entity, Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
c.getMethod("updateById", new Class[]{o.getClass()}).invoke(bean, o);
return ServerResponse.succese();
}
@Override
public ServerResponse save(String entity, Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
c.getMethod("updateById", new Class[]{o.getClass()}).invoke(bean, o);
return ServerResponse.succese();
}
@Override
public ServerResponse removeById(String entity, Integer id) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
c.getMethod("removeById", new Class[]{Serializable.class}).invoke(bean, id);
return ServerResponse.succese();
}
}
因为在springboot里面,要用ApplicationContext获取bean,ApplicationContext这个还封装了一个工具类,如果感兴趣可以看我gitee。
FastController
@RestController
@RequestMapping("/fast")
public class FastController {
@Autowired
private FastService fastService;
@GetMapping("list/{entity}")
public ServerResponse list(@PathVariable("entity")String entity) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return fastService.list(entity);
}
@GetMapping("getById/{entity}/{id}")
public ServerResponse getById(@PathVariable("entity")String entity,@PathVariable("id")Integer id) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return fastService.getById(entity,id);
}
@DeleteMapping("removeById/{entity}/{id}")
public ServerResponse removeById(@PathVariable("entity")String entity,@PathVariable("id") Integer id) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return fastService.removeById(entity, id);
}
}
很简单。
注意的问题
1.在springboot中或者说在spring中获取bean不要直接用Class.forName(name),这样获取不到,具体是为什么,百度,我之后肯定写一篇关于ApplicationContext的博客。
2.一定是在Server层开始封装,不要想着在mapper层封装,写动态sql,这样不行(不好),会面临两个问题,一个是动态表名必须${},会有sql注入的问题,再有就是动态返回值,这个还要封装工作量太大没必要,mybatis有这个动态返回值的插件,但是没必要,利用mybatis-plus就行了。
3.与Hibernate,不是很了解Hibernate,但是肯定是有所不同的,但是有点像,没必要纠结(个人不纠结哈哈)。为什么说像,这个肯定是在开发后台的时候用,在初期,快速搭建,后期如果性能没问题继续用在后台我是这样想的,据百度,Hibernate不行是因为扩展性太差,强耦合,目前的设想是做成多模块项目,应该还好,就是mybatisplus的耦合性,毕竟在下只是学生不做特别大的项目应该没事。
4.第一次设想把save和update也做了,但是用mybatis-plus提供的方法不行!
ServerResponse updateById(String entity,Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
ServerResponse save(String entity,Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
你save传入的参数必须是具体的实体类!!!object不行,想用反射,但是不行!!!你想获取实体类要在实体类加@Component注解这样应该会影响性能,并且获得了类也没用,将object转实体类这一步行不通!!!错误代码如下,以save为例。
@Override
public ServerResponse save(String entity, Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object bean = applicationContext.getBean(entity + "ServiceImpl");
Class<?> c = bean.getClass();
ObjectMapper objectMapper=new ObjectMapper();
//转不了
Object o1 = objectMapper.convertValue(o, applicationContext.getBean(entity).getClass());
//如果不转,这一步不行
c.getMethod("save", applicationContext.getBean(entity).getClass()).invoke(bean,o1);
return ServerResponse.succese();
}
那么有什么解决办法吗?当然有,可以用jdbc封装或者写mybatis也行(不是很方便传入参数类型没想好),但是这里jdbc简单一点,但是有sql注入的问题(虽然可以手写过滤器),传的参数也比较复杂,并且必要性不大。
java使用JDBC动态save、update及SQL预处理的方法
我想写通用接口的一个重要目的是减少前端工作量,但是save界面(弹窗)很难统一,创一个记录各个表字段的表,但是统一save页面这样真的不是很方便,不方便在一些特殊字段date、上传文件,而且数据库字段名和实体类属性名不一样,比较乱,想自定义save页面没有办法,而且要是方便,早就有人做了,但是应该是可以的,就不实现了,也省事了。
存在的问题
1.性能问题,反射的性能,所有的请求都集中在这几个接口上不知道行不行,如果有大佬知道跪求解答。
2.耦合
3.异常处理
项目接下来计划
开头说了表头表,以及菜单表,前端动态组件,减少重复工作,以及集成权限管理RBAC!计划是5.25之前完成应该可以,淦。
以上是关于快速开发平台 fast_security_admin:SpringBoot+Mybatis-Plus+反射 通用开发接口的主要内容,如果未能解决你的问题,请参考以下文章