利用Java框架实现Restful接口

作者: 司小幽 | 来源:发表于2016-11-01 16:20 被阅读2384次

    1.生产场景

    生产场景中,有一个PHP后台程序负责采集用户访问门户的数据,之前采用的是piwik+MySQL的采集存储架构,后来投产后,发现每天数据量将近30万条之多!!!显然,原生的mysql是跑不动了。而kafka又不提供php接口,所以将采集存储方案转换为了restful接口的方案。

    2.需求

    php采集程序,通过post请求将json数据格式发至该restful接口,负责提供该接口的程序,接收到该post请求后,解析该json数据,通过协商好的各字段值,和Hbase交互,执行该数据的增改删操作,并将该数据操作的结果封装成json返回给php采集程序。

    3.基本常识

    1. Java异常信息保存的一个简单方法
    2. Web Serveice百度百科
    3. 四种常见的 POST 提交数据方式
    4. 将数据封装为Json数据格式
    5. json-lib....jar 架包 jsonObject介绍
    6. java 各种类型数据,集合对象封装 成json

    关于Json的jar包有很多,Php采集程序post的json数据被转换为JSONObject格式,但经测试发现,如果导入的是org.json.JSONObject jar包是无法成功接收到的,需改用net.sf.json.JSONObject。前者与后者在JSONObject化的方法上还是有区别的。比如我有如下json类型的数据:
    data={"id":1,"content":"Hello, World!"}
    org.json.JSONObject将之转换为JSONObject,是通过如下方式:
    JSONObject dataObj=new JSONObject(data),此时dataObj即为data转换后的JSONObject格式。
    但是net.sf.json.JSONObject用之即会报错,它实现的方式如下:
    JSONObject dataObj = JSONObject.fromObject(data);
    需要注意一下。

    4.环境部署

    1. WIN7系统JavaEE(java+tomcat7+Eclipse)环境配置
    2. 修改tomcat默认的编码方式
    3. Linux下安装Tomcat服务器和部署Web应用
    4. 修改tomcat端口号
    5. 手把手图文教你eclipse下如何配置tomcat
    6. windows cmd窗口下tomcat关闭和重启的命令是什么?
    7. 搭建一个RESTFUL风格的Web Service (Maven版本)
    8. eclipse构建及运行maven web项目
    9. eclipse 创建maven 项目 动态web工程完整示例
    10. Eclipse+Maven创建webapp项目
    11. 如何用Maven创建web项目(具体步骤)
      按照上述文档,可能由于Maven版本等问题,可能会出现步骤展现不一致现象,试着通过如下三篇文章解决
    12. (转)利用Eclipse创建maven项目并生成META-INF和WEB-INF目录
    13. web.xml is missing and is set to true[解决]
    14. maven项目转web项目时Java Build path entrles里没有内容

    5.设计方案

    ①Jersey框架

    用Jersey开发RESTful服务
    com.sun.jersey.api.Container.ContainerException
    Web编程学习四: 使用Jersey来创建RESTful WebService

    ②Spring框架

    Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释
    使用spring框架实现RESTful
    SpringMVC写REST接口:第二篇 配置Maven的pom.xml文件

    ③Java与Hbase交互

    Hbase常用操作(增删改查)

    JAVA连接HBase

    public HBaseCommonUtil(String rootDir,String zooKeeperAddress,String clientPort) {  
        HBASE_CONFIG = new Configuration();  
        HBASE_CONFIG.set("hbase.rootdir", rootDir);  
        HBASE_CONFIG.set("hbase.zookeeper.quorum", zooKeeperAddress);  
        HBASE_CONFIG.set("hbase.zookeeper.property.clientPort", clientPort);  
        conf = HBaseConfiguration.create(HBASE_CONFIG);  
        try {  
            conn = ConnectionFactory.createConnection(conf);  
            hbaseAdmin = (HBaseAdmin) conn.getAdmin();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    

    新增操作

    //Hbase新增操作  
    public void insertData(String tableName,String rowKey,String column,String value) {  
        try {  
            HTable table = new HTable(conf, tableName);  
            Put put = new Put(Bytes.toBytes(rowKey));  
            put.add(Bytes.toBytes("detail"), Bytes.toBytes(column), Bytes.toBytes(value));  
            table.put(put);  
            table.close();  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  
    

    删除操作

    //Hbase删除操作  
    public void deleteData(String tableName, String rowKey) throws IOException {  
        HTable table;  
        table = new HTable(conf, tableName);  
        List list = new ArrayList();  
        Delete del = new Delete(rowKey.getBytes());  
        list.add(del);  
        table.delete(list);  
        table.close();  
    }  
    

    更新操作

    //Hbase更新操作  
    public void updateData(String tableName, String rowKey, String column, String value) throws IOException {  
        HTable table = new HTable(conf, tableName);  
        Put p = new Put(Bytes.toBytes(rowKey));  
        p.add(Bytes.toBytes("detail"), Bytes.toBytes(column), Bytes.toBytes(value));  
        table.put(p);  
        table.close();  
    }  
    

    6.性能优化

    初步设计方案在测试中发现Got ping response for sessionid,远程主机强制关闭一个连接以及您本机中的软件关掉一个连接,这样的错误。百思不得其解,后来小伙伴看了下之前的代码,找到了错误的源头:
    ①每提交一次,就会执行一次Controller方法,而连接Hbase的操作放在这个方法中,所以每次都会连接一次。
    ②而Hbase在通过java进行交互的时候,需要知道待操作的数据的表名,通过

    HTable table = new HTable(conf,tableName)
    

    这个可以通过放在一个map中,来避免每次的new的耗时;
    具体操作为,定义一个Map:Map<String,HTable> tableMap,在构造方法中初始化这个Map,执行到与Hbase交互时,首先判断tableMap.get(tableName)是否可以取到相应的HTable初始化方法,可以即直接从Map中get到这个初始化,不可以说明是第一次,需将tableName和初始化方式添加给这个Map。具体代码如下:

    if(tableMap.get(tableName)==null)
    {
        tableMap.put(tableName,
        new HTable(util.getConf,tableName));
    }
    HTable table = tableMap.get(tableName);
    

    ③同时之前有一个误区,就是在操作Hbase的时候,Hbase不能批量进行插入,以为每次在put的时候,只能一个value,所以将put操作放到了循环中,改良后的操作方式为将每次提交的数据中的value一次性添加到put中,一次性提交这个put。
    做到以上三点,基本上就没出现过上述错误,并且一万条数据耗时100秒,而生产场景的巅峰值是一秒60几条,绰绰有余。

    7.常见问题

    1. eclipse (kepler) 创建 maven 项目 添加src/main/java出问题
    2. maven 加入json-lib.jar 报错 Missing artifact net.sf.json-lib:json-lib:jar:2.4:compile
    3. 解决maven引用jdk中的tools.jar报Missing artifact的问题
    4. The processing instruction target matching "[xX][mM][lL]" is not allowed怎么办?
    5. eclipse导出jar包export-->runnable jar file的launch configuration里的内容不更新解决
    6. 经过web.xml加载spring容器时遇到java.lang.ClassNotFoundException: org.springframework.web
      (如若不行试着删除WebApp lib目录下的com.google.jar包)*

    相关文章

      网友评论

      本文标题:利用Java框架实现Restful接口

      本文链接:https://www.haomeiwen.com/subject/tommuttx.html