客户端必须具备以下几点:

  • java客户端包含Hessian.jar的包。
  • 具有和服务器端结构一样的接口。
  • 利用HessianProxyFactory调用远程接口。
  • 使用spring方式需要配置HessianProxyFactoryBean

注意:使用resin容器时,resin已经包含了hessian.jar包

JAVA服务器端必须具备以下几点:

  • 包含Hessian的jar包。
  • 设计一个接口,用来给客户端调用。
  • 实现该接口的功能。
  • 配置web.xml,配好相应的servlet。
  • 对象必须实现Serializable 接口。
  • 对于spring方式DispatcherServlet拦截url,HessianServiceExporter提供Bean服务

完整代码下载

https://gitee.com/zml2015/HessianDemo

引入必要jar包

<dependency>
      <groupId>com.caucho</groupId>
      <artifactId>hessian</artifactId>
      <version>4.0.51</version>
</dependency>

定义接口

package top.wuyongshi.service;
/**
 * Created by zml2015 on 2017/10/10 16:28.
 */

import java.util.List;

import top.wuyongshi.model.CommonVO;
import top.wuyongshi.model.PageInfo;
import top.wuyongshi.model.TaskEntity;

/**
 * @author zml2015
 * @version 1.0
 * @time 2017/10/10 16:28
 * @description <p> </p>
 */
public interface ITaskRPC {

    /**
     * 根据作业名称查询作业信息
     * @param taskName
     * @return
     */
    PageInfo<TaskEntity> queryTaskByName(String taskName, CommonVO commonVO);

    /**
     * 查询作业列表
     * @return
     */
    PageInfo<TaskEntity> queryAll(CommonVO commonVO);

    List<TaskEntity> queryAll();

    /**
     * 查询 源连接池 列表
     * @return
     */
    List<String> querySourcePools();

    /**
     * 查询 目标连接池 列表
     * @return
     */
    List<String> queryTargetPools();


}

实现接口

package top.wuyongshi.service.impl;
/**
 * Created by zml2015 on 2017/10/10 16:27.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import top.wuyongshi.model.CommonVO;
import top.wuyongshi.model.PageInfo;
import top.wuyongshi.model.TaskEntity;
import top.wuyongshi.service.ITaskRPC;


/**
 * @author zml2015   @email mpro@vip.qq.com
 * @version 1.0
 * @time 2017/10/10 16:27
 * @description <p> </p>
 */
public class TaskRPCImpl implements ITaskRPC {

    @Override
    public PageInfo<TaskEntity> queryTaskByName(String taskName, CommonVO commonVO) {
        return null;
    }

    @Override
    public PageInfo<TaskEntity> queryAll(CommonVO commonVO) {
        return getTask(commonVO);
    }

    @Override
    public List<TaskEntity> queryAll() {
        return getTask();
    }

   static final String frequentness[] = {"日报","月报","季报","半年报","年报"};


    @Override
    public List<String> querySourcePools() {
       return getSourcePools();
    }

    @Override
    public List<String> queryTargetPools() {
        return getTargetPools();
    }

    /**
     * 模拟作业数据
     * @return
     */
    public static List<TaskEntity> getTask(){
        List<TaskEntity> list = new ArrayList<>();
        Random random = new Random();
        initTask(list, frequentness[random.nextInt(1000) % 5]);
        return list;
    }

    private static void initTask(List<TaskEntity> list, String frequentness) {
        for (int i = 0; i < 30; i++) {
            TaskEntity task = new TaskEntity();
            task.setId(""+i);
            task.setTaskName("task"+ getRandomCode(4));
            task.setTaskDesc("作业描述"+ UUID.randomUUID().toString());
            task.setTaskCreator("zml2015");
            task.setTaskFrequentness(frequentness);
            task.setLimitTime(10);
            list.add(task);
        }
    }

    public static PageInfo<TaskEntity> getTask(CommonVO commonVO){
        List<TaskEntity> list = new ArrayList<>();
        Random random = new Random();
        initTask(list, frequentness[random.nextInt(1000)%5]);
        PageInfo pageInfo = new PageInfo();
        pageInfo.setList(list);
        pageInfo.setPageSize(commonVO.getPageSize());
        pageInfo.setTotal(30);
        pageInfo.setPages(((int) Math.ceil(30.0 / commonVO.getPageSize())));
        pageInfo.setPageNum(commonVO.getPageNo());
        return pageInfo;
    }
    public static List<String> getSourcePools() {
        List<String> soucePools = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            soucePools.add("源连接池"+(i+1));
        }
        return soucePools;
    }

    public List<String> getTargetPools() {
        List<String> targetPools = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            targetPools.add("目标连接池"+(i+1));
        }
        return targetPools;
    }

    public static String getRandomCode(int number) {
        String codeNum = "";
        int[] code = new int[3];
        Random random = new Random();
        for (int i = 0; i < number; i++) {
            int num = random.nextInt(10) + 48;
            int uppercase = random.nextInt(26) + 65;
            int lowercase = random.nextInt(26) + 97;
            code[0] = num;
            code[1] = uppercase;
            code[2] = lowercase;
            codeNum += (char) code[random.nextInt(3)];
        }
        System.out.println(codeNum);

        return codeNum;
    }
}

传输对象

需要实现java.io.Serializable接口进行序列化

package top.wuyongshi.model;
import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

@Table(name = "T_TASK")
public class TaskEntity implements Serializable {
    /**
     * 任务ID,32位uuid
     */
    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "UUID")
    private String id;

    /**
     * 调度任务id
     */
    @Column(name = "SCHEDULE_ID")
    private String scheduleId;


    /**
     * 任务名称
     */
    @Column(name = "TASK_NAME")
    private String taskName;

    /**
     * 任务描述
     */
    @Column(name = "TASK_DESC")
    private String taskDesc;

    /**
     * 任务频度描述||如月报、季报、年报
     */
    @Column(name = "TASK_FREQUENTNESS")
    private String taskFrequentness;

    /**
     * 源连接池
     */
    @Column(name = "SOURCE_POOL")
    private String sourcePool;

    /**
     * 目标连接池
     */
    @Column(name = "TARGET_POOL")
    private String targetPool;

    /**
     * 任务创建者
     */
    @Column(name = "TASK_CREATOR")
    private String taskCreator;

    /**
     * 任务创建时间
     */
//    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "CREATE_TIME")
    private Date createTime;

    /**
     * 任务修改者
     */
    @Column(name = "TASK_MENDER")
    private String taskMender;

    /**
     * 任务修改时间
     */
//    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "TASK_UPDATE_TIME")
    private Date taskUpdateTime;

    /**
     * 任务参数  以json集合形式存储;类型为List<Map>
     */
    @Column(name = "TASK_PARAMS")
    private String taskParams;

    /**
     * 超时时间,时间单位分钟,默认值 10分钟
     */
    @Column(name = "LIMIT_TIME")
    private Integer limitTime;

     /**
     * 记录id,主要用于标记调度任务计划执行过程中,某次运行的记录id
     */
    @Transient
    private String scheduleRecordId;



    private static final long serialVersionUID = 1L;


    /**
     * 获取 任务ID,32位uuid
     */
    public String getId() {
        return this.id;
    }

    /**
     * 设置 任务ID,32位uuid
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * 获取 任务名称
     */
    public String getTaskName() {
        return this.taskName;
    }

    /**
     * 设置 任务名称
     */
    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }

    /**
     * 获取 任务描述
     */
    public String getTaskDesc() {
        return this.taskDesc;
    }

    /**
     * 设置 任务描述
     */
    public void setTaskDesc(String taskDesc) {
        this.taskDesc = taskDesc;
    }

    /**
     * 获取 任务频度描述||如月报、季报、年报
     */
    public String getTaskFrequentness() {
        return this.taskFrequentness;
    }

    /**
     * 设置 任务频度描述||如月报、季报、年报
     */
    public void setTaskFrequentness(String taskFrequentness) {
        this.taskFrequentness = taskFrequentness;
    }


    /**
     * 获取 任务创建者
     */
    public String getTaskCreator() {
        return this.taskCreator;
    }

    /**
     * 设置 任务创建者
     */
    public void setTaskCreator(String taskCreator) {
        this.taskCreator = taskCreator;
    }

    /**
     * 获取 任务创建时间
     */
    public Date getCreateTime() {
        return this.createTime;
    }

    /**
     * 设置 任务创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    /**
     * 获取 任务修改者
     */
    public String getTaskMender() {
        return this.taskMender;
    }

    /**
     * 设置 任务修改者
     */
    public void setTaskMender(String taskMender) {
        this.taskMender = taskMender;
    }

    /**
     * 获取 任务修改时间
     */
    public Date getTaskUpdateTime() {
        return this.taskUpdateTime;
    }

    /**
     * 设置 任务修改时间
     */
    public void setTaskUpdateTime(Date taskUpdateTime) {
        this.taskUpdateTime = taskUpdateTime;
    }

    /**
     * 获取 任务参数  以json集合形式存储;类型为List<Map>
     */
    public String getTaskParams() {
        return this.taskParams;
    }

    /**
     * 设置 任务参数  以json集合形式存储;类型为List<Map>
     */
    public void setTaskParams(String taskParams) {
        this.taskParams = taskParams;
    }

    /**
     * 获取 源连接池
     */
    public String getSourcePool() {
        return this.sourcePool;
    }

    /**
     * 设置 源连接池
     */
    public void setSourcePool(String sourcePool) {
        this.sourcePool = sourcePool;
    }

    /**
     * 获取 源连接池
     */
    public String getTargetPool() {
        return this.targetPool;
    }

    /**
     * 设置 源连接池
     */
    public void setTargetPool(String targetPool) {
        this.targetPool = targetPool;
    }

    /**
     * 获取 调度任务id
     */
    public String getScheduleId() {
        return this.scheduleId;
    }

    /**
     * 设置 调度任务id
     */
    public void setScheduleId(String scheduleId) {
        this.scheduleId = scheduleId;
    }

    /**
     * 获取 超时时间  时间单位分钟,默认值 10分钟
     */
    public Integer getLimitTime() {
//        if (this.limitTime == null){
//            limitTime = 10;
//        }
        return this.limitTime;
    }

    /**
     * 设置 超时时间 时间单位分钟,默认值 10分钟
     */
    public void setLimitTime(Integer limitTime) {
        this.limitTime = limitTime;
    }

    @Override
    public String toString() {
        return "TaskEntity{" +
                "id='" + id + '\'' +
                ", scheduleId='" + scheduleId + '\'' +
                ", taskName='" + taskName + '\'' +
                ", taskDesc='" + taskDesc + '\'' +
                ", taskFrequentness='" + taskFrequentness + '\'' +
                ", sourcePool='" + sourcePool + '\'' +
                ", targetPool='" + targetPool + '\'' +
                ", taskCreator='" + taskCreator + '\'' +
                ", createTime=" + createTime +
                ", taskMender='" + taskMender + '\'' +
                ", taskUpdateTime=" + taskUpdateTime +
                ", taskParams='" + taskParams + '\'' +
                ", limitTime=" + limitTime +
                "} " + super.toString();
    }

    /**
     * 获取 记录id,主要用于标记调度任务计划执行过程中,某次运行的记录id
     */
    public String getScheduleRecordId() {
        return this.scheduleRecordId;
    }

    /**
     * 设置 记录id,主要用于标记调度任务计划执行过程中,某次运行的记录id
     */
    public void setScheduleRecordId(String scheduleRecordId) {
        this.scheduleRecordId = scheduleRecordId;
    }
}

web.xml配置hessian

  • 注意要将对外暴露的接口接口实现声明到配置文件中,接口可以缺省配置,这个网上的好多资料都比较坑,说多了都是泪...
  • 查看过HessianServlet其实就会注意到,它里面方法public void init(ServletConfig config)在实例化的时候默认会取的初始化参数名为home-class、service-class、object-class(接口实现类)、home-api、api-class、object-api(接口)
<servlet>
    <servlet-name>hessianServlet</servlet-name>
    <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
    <init-param>
    <!--接口实现类,此处param-name可配置的名称有:home-class、service-class、object-class-->
      <param-name>home-class</param-name>
      <param-value>top.wuyongshi.service.impl.TaskRPCImpl</param-value>
    </init-param>
      <init-param>
      <!--接口,param-name可配置的名称有:home-api、api-class、object-api(可不配置)-->
          <param-name>home-api</param-name>
          <param-value>top.wuyongshi.service.ITaskRPC</param-value>
      </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>hessianServlet</servlet-name>
    <url-pattern>/hessian</url-pattern>
 </servlet-mapping>

客户端调用

先启动服务器端,浏览器访问配置的路径,出现以下图片内容,说明配置成功

private String url;

    @Test
    public void testQueryAll() throws MalformedURLException {
        HessianProxyFactory factory = new HessianProxyFactory();
        url = "http://localhost:8088/HessianDemo2/hessian";
//        url = "http://localhost:8087/ScheduleTask/hessian";
        ITaskRPC taskRPC = (ITaskRPC) factory.create(ITaskRPC.class, url);
        List<TaskEntity> taskEntityPageInfo = taskRPC.queryAll();
        System.out.println(JSON.toJSONString(taskEntityPageInfo,true));
        List<String> strings = taskRPC.querySourcePools();
        for (String string : strings) {
            System.out.println(string);
        }
    }

测试结果

2021/02/01/ea4d40201102953.png

出处

文章首次发布于个人博客:吾勇士的博客http://wuyongshi.top/hessian-basic-use

Q.E.D.


寻门而入,破门而出