简单优雅的mybatis接口化组件

batis-rest是一个简单而优雅的组件,可以将mybatis的mapper操作方法暴露为rest接口,从而减少service和controller的代码开发。

使用方法和源码详见https://gitee.com/wangbaishi_libi/data-rest

本组件实现过程:

  1. 组件初始化(BatisRestAutoConfig);
  2. 扫描mybatis mapper方法(MapperComponentScanAndRegister);
  3. 将mapper方法代理对象注册为rest接口。

 

SpringCloud的data-rest组件功能令我印象深刻,于是打算参考该组件给mybatis做一个自动rest化的组件,毕竟国内用mybatis还是蛮多的。

先扫描mapper。mybatis内部mapper的管理类是MapperRegistry,它可以通过mybatis的configuration对象取到。为了方便,本组件内只引用了SqlSessionTemplate,通过这个bean对象获取mapper。注册Spring的ContextRefreshedEvent事件,待mybatis初始化之后就可以获取到mapper了。

sqlSessionTemplate.getConfiguration().getMapperRegistry().getMappers().forEach(mapperCls -> {
    if(mapperCls.getAnnotation(EnableRestMapper.class) != null){
        restInterfaceRegister.register(mapperCls);
    }
});

 

构建代理mapper代理。一般情况下,接口(Interface)方法是不能执行的,为了能调用mapper方法,需要用到代理对象Proxy(实际上,mybatis也是给mapper方法构建了代理对象),用于处理mapper方法对应的实际逻辑。

执行操作。Mybatis中每个mapper方法会有一个对应的MapperMethod对象来执行,这里我们可以通过构造MapperMethod来实现mapper的具体逻辑。

public class RestMapperProxy implements InvocationHandler, Serializable {

    Class<?> mapperInterface;

    SqlSessionTemplate sqlSessionTemplate;


    public RestMapperProxy(Class<?> mapperInterface, SqlSessionTemplate sqlSessionTemplate) {
        this.mapperInterface = mapperInterface;
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        MapperMethod mapperMethod = new MapperMethod(mapperInterface, method, sqlSessionTemplate.getConfiguration());
        return mapperMethod.execute(sqlSessionTemplate, args);
    }

}

rest接口注册。Spring中接口映射管理对象为requestMappingHandlerMapping,注册方法参数中,mapper方法的代理对象作为handler参数,mapper方法名称作为RequestMappingInfo的映射地址,sql类型转化为请求类型。

public Object register(Class<?> mapperInterface){

        EnableRestMapper enableRestMapper = mapperInterface.getAnnotation(EnableRestMapper.class);

        RestMapperProxy restMapperProxy = new RestMapperProxy(mapperInterface, sqlSessionTemplate);
        //注册代理
        Object proxy = Proxy.newProxyInstance(RestInterfaceRegister.class.getClassLoader(), new Class[]{mapperInterface}, restMapperProxy);

        //注册接口
        for(Method method : mapperInterface.getMethods()){

            String uri = enableRestMapper.value() + "/" + method.getName();
            log.info("mapper rest [{} - {}]", uri, method.getDeclaringClass());

            RequestMappingInfo mappingInfo = new RequestMappingInfo(
                    new PatternsRequestCondition(uri),
                    new RequestMethodsRequestCondition(commandTypeToRequestMethod(method)),
                    null, null, null, null, null);

            requestMappingHandlerMapping.registerMapping(mappingInfo, proxy, method);

        }

        return proxy;

    }

    private RequestMethod commandTypeToRequestMethod(Method method){
        MappedStatement statement = sqlSessionTemplate.getConfiguration().getMappedStatement(method.getName());
        SqlCommandType commandType = statement.getSqlCommandType();

        if(SqlCommandType.SELECT == commandType){
            return RequestMethod.GET;
        }
        return RequestMethod.POST;
    }

 

参数匹配。正常编译情况下,Spring的几个ParameterNameDiscoverer是无法获取Interface方法参数名称的。mybatis为确保获取参数名称,增加了@Param注解。于是我自定义了BatisParameterNameDiscoverer,用于适配mybatis的ParamNameResolver。虽然没有经过完整测试,但我试了多参数、对象参数等情况,都是完美支持的。

结果装配。@EnableRestMapper继承了@ResponseBody,意味着加了EnableRestMapper注解的mapper返回结果会使用ResponseBody组装。

 

后续。本来想多花点时间好好做一下,为此专门研究了data-rest和mybatis的源码,实际却很快搞定了上述核心功能,这或许就是Spring强大的框架集成和扩展能力吧。当然,还有诸如事务、异常处理、结果封装等场景尚未经过测试和处理,敬请期待!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,作为AI语言模型,我无法手写代码,但我可以简单地介绍一下MyBatis框架的基本原理和核心组件MyBatis是一款Java持久层框架,它的主要作用是将Java对象和关系型数据库之间的操作映射起来,从而实现数据的持久MyBatis的核心组件包括: 1. SqlSessionFactoryBuilder:用于创建SqlSessionFactory。通过读取MyBatis的配置文件和Mapper文件,生成SqlSessionFactory,从而获取SqlSession。 2. SqlSessionFactory:是MyBatis框架的核心组件,用于创建SqlSession。通过SqlSessionFactory,我们可以获取SqlSession对象,从而进行数据库的操作。 3. SqlSession:是MyBatis框架中的一个关键组件,它表示和数据库之间的会话。SqlSession提供了一系列方法,用于执行SQL语句、提交事务、关闭连接等操作。 4. Mapper:是MyBatis框架中的另一个重要组件,它用于定义数据库操作的接口Mapper接口中定义了一系列方法,每个方法对应一个SQL语句。在Mapper接口中,我们可以使用注解或XML文件来配置SQL语句。 基于以上核心组件,我们可以通过编写Mapper接口和对应的SQL语句,使用MyBatis框架来进行数据库的操作。下面是一个简单Mapper接口示例: ``` public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{id}") User getUserById(int id); @Insert("INSERT INTO user(name, age) VALUES (#{name}, #{age})") void addUser(User user); @Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}") void updateUser(User user); @Delete("DELETE FROM user WHERE id = #{id}") void deleteUser(int id); } ``` 在这个示例中,我们定义了一个UserMapper接口,其中包含了4个方法,分别对应了查询、插入、更新和删除操作。每个方法都使用@Select、@Insert、@Update、@Delete注解来配置对应的SQL语句。使用MyBatis框架时,我们只需要通过SqlSession.getMapper(UserMapper.class)方法获取UserMapper接口的实例,然后调用其中的方法即可完成对数据库的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值