快速开发平台 fast_security_admin(一):SpringBoot+Mybatis-Plus+反射 通用开发接口

快速开发平台 fast_security_admin(一):SpringBoot+Mybatis-Plus+反射 通用开发接口

fast_security_admin在gitee地址

需求提出

之前使用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之前完成应该可以,淦。

个多模块的 Spring Boot 项目中,获取用户登录信息可以通过 Spring Security 来实现。首先,在 Spring Security 的配置类中,需要配置个 AuthenticationProvider,用于验证用户的身份信息。在这个 AuthenticationProvider 中,可以通过注入 HttpServletRequest 对象来获取用户的登录信息,例如用户名和密码等。具体的代码实现可以参考以下示例: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() .and() .formLogin() .and() .logout().logoutSuccessUrl("/"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationProvider authenticationProvider() { return new AuthenticationProvider() { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String username = request.getParameter("username"); String password = request.getParameter("password"); UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (passwordEncoder().matches(password, userDetails.getPassword())) { return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities()); } else { throw new BadCredentialsException("Invalid username or password"); } } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }; } } ``` 在这个示例中,我们通过注入 HttpServletRequest 对象来获取用户的登录信息,然后使用 UserDetails 对象来验证用户的身份信息。这个 UserDetails 对象可以通过实现 UserDetailsService 接口来获取,例如从数据库中查询用户信息。最后,我们返回个 UsernamePasswordAuthenticationToken 对象来表示用户已经通过身份验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值