使用swift进行thrift文件的生成

RPC 同时被 2 个专栏收录
2 篇文章 0 订阅
3 篇文章 0 订阅

使用swift由java类生成thrift文件,再用thrift生成js文件

1.什么是swift
首先,这个swift指的的Facebook的另一个开源项目,thrift的子项目,不是ios的那个swift;swift用于将已有的java代码生成thrift文件,支持java中的string、int、long、double、boolean等基本类型以及枚举、类、异常,不支持java.sql.Timestamp、java.util.Date,但是可以用long替代;相比于thrift,swift可以使用自己定义的实体类,而thrift需要在.thrift文件里定义struct等,生成的代码冗长,不利于重用。
2.如何使用swift
2.1下载swift
swift2thrift-generator,用于将java代码生成thrift文件,下载地址:
http://central.maven.org/maven2/com/facebook/swift/swift2thrift-generator-cli
我自己试的时候首先用的版本是0.23.1,生成thrift的时候莫名其妙报错,后来用的0.15.6才能够正常生成,建议使用0.15.6,较为稳定。
2.2编写java代码
在swift中service一般以接口的形式存在,整个类用@ThriftService注解,方法用@ThriftMethod注解,如果方法可能抛出异常则用@ThriftMethod(exception = {@ThriftException(type = InvalidException.class, id = 1)}),在括号里定义exception,如下:

import com.facebook.swift.service.ThriftMethod;
import com.facebook.swift.service.ThriftService;
import com.facebook.swift.service.ThriftException;
@ThriftService
public interface DbSourceTableMgr {

    @ThriftMethod
    public ReturnResult add(DbType dbType, String address, int port, String user, String pwd, String desc,
            String tablename, boolean ismulti, String multirule, FieldInfo fieldInfo);
    @ThriftMethod(exception = {@ThriftException(type = InvalidException.class, id = 1)})
    public ReturnResult delTable(String id)throws InvalidException;
}

定义好了服务类,接下来需要定义服务类里面用到的相关实体类和枚举以及异常。用@ThriftStruct注解类、枚举、异常,成员变量的get方法用@ThriftField(1)注解,括号里面的表示字段的ID,这个在thrift文件里有体现。set方法不需要ID。
FieldInfo.java

import com.facebook.swift.codec.ThriftField;
import com.facebook.swift.codec.ThriftStruct;

@ThriftStruct
public final class FieldInfo {
    private String fieldName;
    private String aliesName;
    private String desc;
    private int order;
    private FieldType fieldType;
    @ThriftField(1)
    public String getFieldName() {
        return fieldName;
    }
    @ThriftField
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }
    @ThriftField(2)
    public String getAliesName() {
        return aliesName;
    }
    @ThriftField
    public void setAliesName(String aliesName) {
        this.aliesName = aliesName;
    }
    @ThriftField(3)
    public String getDesc() {
        return desc;
    }
    @ThriftField
    public void setDesc(String desc) {
        this.desc = desc;
    }
    @ThriftField(4)
    public int getOrder() {
        return order;
    }
    @ThriftField
    public void setOrder(int order) {
        this.order = order;
    }
    @ThriftField(5)
    public FieldType getFieldType() {
        return fieldType;
    }
    @ThriftField
    public void setFieldType(FieldType fieldType) {
        this.fieldType = fieldType;
    }
}

DbType.java

import com.facebook.swift.codec.ThriftEnum;

@ThriftEnum
public enum DbType {
    ORACLE,POSTGRESQL;
}

FieldType.java

import com.facebook.swift.codec.ThriftEnum;

@ThriftEnum
public enum FieldType {
    LONGLAT,IMAGE,ID;
}

InvalidException.java

import com.facebook.swift.codec.ThriftConstructor;
import com.facebook.swift.codec.ThriftField;
import com.facebook.swift.codec.ThriftStruct;


@ThriftStruct
public final class InvalidException extends Exception{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String why;
    @ThriftField(1)
    public String getId() {
        return id;
    }
    @ThriftField
    public void setId(String id) {
        this.id = id;
    }
    @ThriftField(2)
    public String getWhy() {
        return why;
    }
    @ThriftField
    public void setWhy(String why) {
        this.why = why;
    }
    @ThriftConstructor
    public InvalidException(String id, String why) {
        super();
        this.id = id;
        this.why = why;
    }

}

构造器用@ThriftConstructor注解
ReturnResult.java

import com.facebook.swift.codec.ThriftConstructor;
import com.facebook.swift.codec.ThriftField;
import com.facebook.swift.codec.ThriftStruct;

@ThriftStruct
public final class ReturnResult {
    private String id;
    private boolean status;
    private String message;
    @ThriftConstructor
    public ReturnResult(String id, boolean status, String message) {
        super();
        this.id = id;
        this.status = status;
        this.message = message;
    }
    @ThriftField(1)
    public String getId() {
        return id;
    }
    @ThriftField
    public void setId(String id) {
        this.id = id;
    }
    @ThriftField(2)
    public boolean isStatus() {
        return status;
    }
    @ThriftField
    public void setStatus(boolean status) {
        this.status = status;
    }
    @ThriftField(3)
    public String getMessage() {
        return message;
    }
    @ThriftField
    public void setMessage(String message) {
        this.message = message;
    }
}

2.3生成thrift文件
类全部定义好了,接下来用swift2thrift生成thrift文件, ^ 是windows下的分割符,-package 后跟你java类的包名,-recursive是递归生成,在这里只体现了生成DbSourceTableMgr 相应的thrift文件,但是这个类里面用到了其他的很多实体类,使用了-recursive 命令,就会自动的把用到的类全部生成。命令如下:

java -cp libs/swift2thrift-generator-cli-0.15.6-standalone.jar;bin^ com.facebook.swift.generator.swift2thrift.Main^ -package com.link2map.swift^  DbSourceTableMgr ^  -namespace java com.link2map.swift^ -out DbSourceTableMgr.thrift^ -recursive 

其中libs/swift2thrift-generator-cli-0.15.6-standalone.jar;是jar包的位置,bin是class文件的位置。
最后生成的swift文件如下:

namespace java.swift com.link2map.swift
namespace java com.link2map.swift


enum DbType {
  ORACLE, POSTGRESQL
}

enum FieldType {
  LONGLAT, IMAGE, ID
}

struct ReturnResult {
  1:  string id;
  2:  bool status;
  3:  string message;
}

exception InvalidException {
  1:  string id;
  2:  string why;
}

struct FieldInfo {
  1:  string fieldName;
  2:  string aliesName;
  3:  string desc;
  4:  i32 order;
  5:  FieldType fieldType;
}

service DbSourceTableMgr {
  ReturnResult add(1:  DbType arg0, 2:  string arg1, 3:  i32 arg2, 4:  string arg3, 5:  string arg4, 6:  string arg5, 7:  string arg6, 8:  bool arg7, 9:  string arg8, 10:  FieldInfo arg9);
  ReturnResult delTable(1:  string arg0) throws (1: InvalidException ex1);
}

如何通过thrift文件生成js代码请看前一篇博文。这样前端代码也有了,下面就是使用了。
3.搭建后端服务
3.1实现服务接口
之前定义好了DbSourceTableMgr 这个接口,现在需要将其实现,实现类为MgrImp.java

package com.link2map.swift;
import com.link2map.swift.DbSourceTableMgr;
import com.link2map.swift.FieldInfo;

public class MgrImp implements DbSourceTableMgr{

    @Override
    public ReturnResult add(DbType dbType, String address, int port, String user, String pwd, String desc,
            String tablename, boolean ismulti, String multirule, FieldInfo fieldInfo) {
        System.out.println(address+"||");
        System.out.println(fieldInfo.getAliesName());
        System.out.println(fieldInfo.getFieldName());
        System.out.println(dbType==null);
        System.out.println(fieldInfo.getFieldType());
        return new ReturnResult("12340987",true,"sucess");
    }

    @Override
    public ReturnResult delTable(String id) throws InvalidException{
        if(id.equals("10000")) {
            throw new InvalidException("10000", "cuole");
        }
        return new ReturnResult("11111",false,"fail");
    }

}

具体的服务就是MgrImp这个类来处理了。接下来是Vertx服务:

package service;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TMemoryBuffer;

import com.facebook.nifty.processor.NiftyProcessor;
import com.facebook.nifty.processor.NiftyProcessorAdapters;
import com.facebook.swift.codec.ThriftCodecManager;
import com.facebook.swift.service.ThriftEventHandler;
import com.facebook.swift.service.ThriftServiceProcessor;
import com.google.common.collect.ImmutableList;
import com.link2map.swift.MgrImp;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.CorsHandler;

public class VertxService extends AbstractVerticle{
    public static void main(String[] args) {
        Vertx vertx=Vertx.vertx();
        Router router = Router.router(vertx);
        // 解决跨域问题
                router.route().handler(
                        CorsHandler.create("*").allowedMethod(HttpMethod.GET)
                                .allowedMethod(HttpMethod.POST)
                                .allowedMethod(HttpMethod.OPTIONS)
                                .allowedHeader("X-PINGARUNER")
                                .allowedHeader("Content-Type"));
                router.route("/server/*").handler(context->{
                    context.request().bodyHandler(buffer->{
                        byte[] arr=buffer.getBytes();
                        vertx.executeBlocking(future->{
                            String result=thriftRequest(arr);
                            future.complete(result);
                        }, res->{
                            try {
                                if(res.succeeded()) {
                                    context.response().end(res.result().toString());
                                }else {
                                    context.response().end(res.cause().getMessage());
                                }
                            }catch(Exception exception) {
                                exception.printStackTrace();
                            }
                        });
                    });
                });
                vertx.createHttpServer().requestHandler(router::accept).listen(8088, res->{
                    if(res.succeeded()) {
                        System.out.println("Server starts successfully!");
                    }else {
                        System.out.println("Server fails to start!");
                    }
                });
                vertx.deployVerticle(new VertxService());
    }
    private static String thriftRequest(byte[] input){
        try{

            //Input
            TMemoryBuffer inbuffer = new TMemoryBuffer(input.length);   
            System.out.println("input-length:"+input.length);
            inbuffer.write(input);              
            TProtocol  inprotocol   = new TJSONProtocol(inbuffer);                   

            //Output
            TMemoryBuffer outbuffer = new TMemoryBuffer(100);           
            TProtocol outprotocol   = new TJSONProtocol(outbuffer);
            //这里是关键的地方,与之前的thrift不同,需要先构建一个NiftyProcessor ,然后用适配器转化为thrift的TProcessor
            NiftyProcessor processor_nifty = new ThriftServiceProcessor(new ThriftCodecManager(),ImmutableList.<ThriftEventHandler>of(),MgrImp.class);
            //适配NiftyPorcessor——>Tprocessor
            TProcessor processor =  NiftyProcessorAdapters.processorToTProcessor(processor_nifty);    
            processor.process(inprotocol, outprotocol);
            byte[] output = new byte[outbuffer.length()];
            outbuffer.readAll(output, 0, output.length);
            return new String(output,"UTF-8");
        }catch(Throwable t){
            return "Error:"+t.getMessage();
        }
    }
}

在这个过程中可能是swift打包jar的问题吧,找不到com.facebook.nifty.core.RequestContext、com.facebook.nifty.processor.NiftyProcessor这两个类,自己下一个nifty-core-0.18.0就行了。
后端构建好了,前端如何使用还是请看前一篇博文,用法完全一样。
4.有关swift和thrift的一点说明
4.1
swift和thrift支持的类型有interface、class、enum、exception,以下基本类型boolean、byte、byte[]、int、long、float、double,String,以及map、list、set。
4.2
thrift的实体类的成员变量不支持java.sql.Timestamp和java.util.Date,在这里我们可以用一个long来保存日期的毫秒数,进行替换。
4.3
实体类的成员变量名与方法名避开thrift的保留字,否则生成thrift文件出错,我现在发现的有delete、list、function;

  • 1
    点赞
  • 0
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值