前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mock12-拦截器服务实现(三) 接口匹配逻辑

Mock12-拦截器服务实现(三) 接口匹配逻辑

作者头像
MegaQi
发布2023-12-28 17:03:06
1340
发布2023-12-28 17:03:06
举报

上两节我们学习了 HandlerInterceptor 和 WebMvcConfigurer 基础知识,接下我们就可以利用此模块进行拦截服务的逻辑实现了。在此之前我这边先给出一个本项目要实现的一个简化版逻辑处理图,大家可以根据此图先自己构思所要设计数据库表和代码块。

路径匹配数据表

通过创建一个接口基本要素的表来对mock接口进行管理,其中方法、路径,状态码为最基本字段,其他选项则根据需要进行扩展。比如我这里有标签进行一级分类,是否其中,以及在没有规则匹配的默认返回值等。

代码语言:javascript
复制
create table mock_api
(
    api_id               int auto_increment                 primary key,
    api_tag_id           int                                null comment '接口标签',
    api_project_id       int                                null comment '所属项目',
    api_title            varchar(50)                        null comment '自定义名称',
    api_method           varchar(10)                        null comment '接口方法',
    api_path             varchar(200)                       null comment '接口路径',
    api_enabel           tinyint                            null comment '是否启用',
    api_desc             varchar(100)                       null comment '描述',
    api_response_code    int                                null comment '返回状态码',
    api_response_default text                               null comment '接口默认值,用户没有规则的默认返回',
    api_create_user      varchar(50)                        null,
    api_create_date      datetime default CURRENT_TIMESTAMP null,
    api_update_user      varchar(50)                        null,
    api_update_date      datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP
)
    comment '接口管理表';

表创建完后我们再往里插入两条数据方便后边的接口开发调试。

Img

路径匹配逻辑代码

在之前的分享中已经讲过层级架构和Spring Boot接口请求的基本套路,分别创建实体类和服务类。

实体类

编写数据库表mock_api的字段匹配的实体类。

代码语言:javascript
复制
@Data
@NoArgsConstructor
@AllArgsConstructor
public class QMockApiEntity extends QBaseEntity implements Serializable {

    private Long id;
    private Long tagId;
    private Long projectId;
    private String title;
    private String method;
    private String path;
    private Integer enable;
    private String desc;
    private Integer resCode;
    private JSONObject resDefault;

}

基于返回对象QMockApiEntity在QMockService写个待实现业务处理方法。本项目中查询返回的是一个list,在后续的逻辑处理根据数据进行判断。其实正常情况下如果前后端实现时,控制了多条件下的不能重复录入,那么这里完全可以只返回单对象。

代码语言:javascript
复制
@Service("QMockService")
public class QMockService{

    public List<QMockApiEntity> selectApiByPath(String path, String method) {
        return null;
    }
}

数据操作

紧接着就是要写个条件查询语句,为了快速实现验证,我们这里先只通过 api_pathapi_method 两个参数进行条件查询。因为查询SQL相对简单,这里我们直接用@select注解完成查询,多加一个@Results进行数据类型和JAVA中的类型绑定和转换。

代码语言:javascript
复制
@Mapper
public interface QMockApiMapper {

    @Select("SELECT * from mock_api WHERE api_path = #{path} AND api_method=#{method};")
    @Results(id = "apiMap",value = {
            @Result(column = "api_id", property = "id"),
            @Result(column = "api_tag_id", property="tagId"),
            @Result(column = "api_project_id", property="projectId"),
            @Result(column = "api_title", property="title"),
            @Result(column = "api_method", property = "method"),
            @Result(column = "api_path", property="path"),
            @Result(column = "api_enable", property="enable"),
            @Result(column = "api_desc", property = "desc"),
            @Result(column = "api_response_code", property="resCode"),
            @Result(column = "api_response_default", property="resDefault",jdbcType = JdbcType.VARCHAR, typeHandler = JSONObjectTypeHandler.class),
            @Result(column = "api_create_user", property = "createUser"),
            @Result(column = "api_create_date", property = "createDate"),
            @Result(column = "api_update_user", property = "updateUser"),
            @Result(column = "api_update_date", property = "updateDate")
    })
    List<QMockApiEntity> getMockApiListByPath(String path, String method);

}

特别指出Results标记中有一处 typeHandler = JSONObjectTypeHandler.class 是用到了MyBatis的自定义类型处理器,代码如下,具体技术点大家可以先自行学习下,后边有扩展内容的也会给大家说一说。

代码语言:javascript
复制
@MappedTypes(JSONObject.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JSONObjectTypeHandler extends BaseTypeHandler<JSONObject> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, String.valueOf(parameter.toJSONString()));
    }

    @Override
    public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    @Override
    public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getString(columnIndex);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }
}

业务逻辑

以上都准备好后,就可以调用逻辑了,注意这里之前说过因为网关服务没有太多的类和方法,所以没有写接口类,以及将所有service实现也都集成在一个类中了。

代码语言:javascript
复制
@Service("QMockService")
public class QMockService{

    @Autowired
    private QMockApiMapper qMockApiMapper;

    public List<QMockApiEntity> selectApiByPath(String path, String method) {
        List<QMockApiEntity> mockApiEntities = qMockApiMapper.getMockApiListByPath(path, method);
        return mockApiEntities;
    }
}

截止到目前所有的JAVA代码文件的目录结构供大家参考如下:

Img

最后一个步骤,对其之前的文章中的QMockInterceptor.java进行升级改造,将拦截返回的逻辑处理部分变更调用API服务类,实现真正的配置查询和返回。

代码语言:javascript
复制
@Slf4j
public class QMockInterceptor implements HandlerInterceptor{

    @Autowired
    QMockService qMockService;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 此处省略重复代码... //
            JSONObject resResult = new JSONObject();
            Integer resCode = 200;
            JSONObject reqParamsOrBody = null;

            // 匹配查询URI的数据,当等于1的时候进行规则查询,否则其他错误请求处理
            List<QMockApiEntity> mockApiEntities = qMockService.findApiByPath(requestURI, requestMethod);

            if(mockApiEntities.size() == 1) {
                // 唯一匹配返回默认配置值
                resResult = mockApiEntities.get(0).getResDefault();
                resCode = mockApiEntities.get(0).getResCode();

            } else if (mockApiEntities.size() > 1) {
                resResult.put("code", 5000);
                resResult.put("data", new JSONObject());
                resResult.put("msg", "MOCK匹配多个URI请检查配置");
            }
            else {
                resResult.put("code", 5000);
                resResult.put("data", new JSONObject());
                resResult.put("msg", "MOCK未匹配任何URI请先添加把");
            }
    }

保存全部代码,启动网关服务做个PostMan请求验证下接口拦截功能是否一切OK

Img

至此,本篇教程实现到这里,基本上我们已经实现一个mock网关服务的从请求-拦截-匹配-返回结果的这样的流程。在下一篇中我们去实现更深一层的规则匹配。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 非典型性程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 路径匹配数据表
  • 路径匹配逻辑代码
    • 实体类
      • 数据操作
        • 业务逻辑
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档