将 Hessian 集成到 Smart 中

Hessian是一种轻量级的二进制WebService协议,适用于跨平台的服务交互。它无需庞大框架支持,通过HTTP发送二进制数据实现高效通信。

Hessian,啥东西?

第一次见到这个单词的时候,我真不知道它是什么意思,虽然我的英语功底已经相当牛逼了。最后查了一下有道词典才知道,原来 Hessian 就是“麻布袋子”啊!

我真搞不懂,为什么一个麻布袋子就能通过 HTTP 发送二进制数据?可能麻布袋子不是一般的袋子,因为它密密麻麻,不是一般的数据可以穿透它,除了二进制数据 0 和 1。

如果您不想使用笨重的 SOAP WebService,也不想使用流行的 REST WebService,或许当您看到 Hessian 的功能后,它一定会让您惊呆!


一般我们是这样玩的,在服务端发布 Hessian 服务,让客户端调用已发布的 Hessian 服务。

请不要把 Hessian 想象得过于复杂与神秘,其实它不过是一个麻布袋子而已。

在服务端我们可以这样来发布 Hessian 服务:

@WebServlet("/hessian/user_service")
public class UserServiceImpl extends HessianServlet implements UserService {

    @Override
    public User login(String username, String password) {
        return DataSet.select(User.class, "username = ? and password = ?", username, password);
    }
}

我们可以将 Service 实现类发布为 Servlet(在类上使用 @WebServlet 注解,Servlet 3 规范,无需配置 web.xml 文件),并且让它继承 HessianServlet 类,那么 Hessian 服务就发布啦!

有没有搞错?真的这么简单?—— 没有搞错!果真就这么简单!

客户端如何调用呢?

public class UserServiceHessianTest {

    @Test
    public void loginTest() throws Exception {
        String username = "admin";
        String password = "admin";

        String url = "http://localhost:8080/smart-sample/hessian/user_service";
        HessianProxyFactory factory = new HessianProxyFactory();
        UserService userService = (UserService) factory.create(UserService.class, url);

        User user = userService.login(username, password);
        Assert.assertNotNull(user);
    }
}

我们使用 HessianProxyFactory 这个工厂类,借助 UserService 接口与一个 HTTP 请求 URL,就可以创建客户端代理对象,通过这个代理对象来调用目标方法。

简单而优雅!我只能这样来形容 Hessian 了,而且它还安全且高效!因为我们通过 HTTP 传递的实际上是二进制数据,而并非文本数据。

想进一步了解 Hessian 可以阅读一下它的官网:http://hessian.caucho.com/

官网还提供了一个入门指南,也不错哦!http://hessian.caucho.com/doc/hessian-overview.xtp

当您打开 Hessian 官网,在您眼前一定会看到:

hessian binary web service protocol

The Hessian binary web service protocol makes web services usable without requiring a large framework, and without learning yet another alphabet soup of protocols. Because it is a binary protocol, it is well-suited to sending binary data without any need to extend the protocol with attachments.

翻译一下大概是说:Hessian 是一种二进制 WebService 协议,它无需借助一个牛逼框架来使用 WebService,也无需学习其它乱七八糟的协议。因为它是一种二进制协议,它非常适合于发送二进制数据,没有任何必要来对现有协议进行扩展。

看来体育老师没有白教我英语,我总算一口气翻译出来了。

它宣称自己是 WebService,怪不得它敢说自己是跨平台的,而且针对许多主流的开发语言都有相应的技术实现。

看来作为一名开发人员,错过了 Hessian 实属不幸啊!但错过了 Hessian 与 Smart 的集成,那就更为不幸了。


众所周知,Smart 的 Service 一般都是封装业务逻辑的地方,包括复杂的计算与数据库操作,可以进行控制事务,也可以进行数据缓存,还可以进行方法拦截。这么好的东西,如果带上了 Servlet 这顶帽子,似乎对于它真的有些亏!

为了不失 Smart Service 的种种特性,我们需要进行一些巧妙的架构设计,就可以解决这个问题。

怎么做呢?

借鉴 DispatcherServlet 的思想,我们也可以搞一个 HessianDispatcherServlet 出来,让它拦截所有的 Hessian 请求,根据 URL 来分发到指定的 Service 上。

说起来简单,做起来如何呢?


第一步:创建 @Hessian 注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Hessian {

    String value(); // Hessian URL
}

我们创建了一个 @Hessian 注解,可将它标注在接口上,它只有一个 value 属性,用于设置 Hessian URL。

帽子有了,带在头上看看效果如何呢?


第二步:配置需要发布的 Hessian 服务

@Hessian("/user_service")
public interface UserService {

    User login(String username, String password);
}

我们需要发布哪个 Service,就将这个 @Hessian 帽子戴在谁的头上。

需要说明的是,如果戴在了某个 Service 接口头上的话,那么该接口的所有方法都会被发布出来,其实这也正是我们想做的事情。

需要注意的是,接口方法的参数或返回值都必须可被序列化,数据类型肯定是可以的,但对于 JavaBean 而言,我们必须实现 Serializable 接口。我们这里的 User 是一个 Smart Entity,它一定是实现了 Serializable 接口的(由于 User 继承于 BaseEntity,它继承于 BaseBean,它实现了 Serializable 接口)。


第三步:创建 HessianDispatcherServlet

@WebServlet(urlPatterns = HessianConstant.URL_PREFIX + "/*", loadOnStartup = 0)
public class HessianDispatcherServlet extends HessianServlet {

    // 定义一个 Hessian Servlet Map,用于管理 Hessian URL 与 Hessian Servlet 之间的映射关系
    private final Map<String, HessianServlet> hessianServletMap = new HashMap<String, HessianServlet>();

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // 获取所有标注了 @Hessian 注解的类(接口)
        List<Class<?>> hessianInterfaceList = ClassHelper.getClassListByAnnotation(Hessian.class);
        if (CollectionUtil.isNotEmpty(hessianInterfaceList)) {
            // 遍历所有 Hessian 接口
            for (Class<?> hessianInterface : hessianInterfaceList) {
                // 获取 Hessian URL
                String url = hessianInterface.getAnnotation(Hessian.class).value();
                // 获取 Hessian 接口的实现类
                Class<?> implClass = IOCHelper.findImplementClass(hessianInterface);
                // 获取实现类实例
                Object implInstance = BeanHelper.getBean(implClass);
                // 创建 Hessian Servlet
                HessianServlet hessianServlet = new HessianServlet();
                hessianServlet.setHomeAPI(hessianInterface); // 设置接口
                hessianServlet.setHome(implInstance); // 设置实现类实例
                hessianServlet.init(config); // 初始化 Servlet
                // 将 Hessian URL 与 Hessian Servlet 放入 Hessian Servlet Map 中
                hessianServletMap.put(HessianConstant.URL_PREFIX + url, hessianServlet);
            }
        }
    }

    @Override
    public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        // 获取请求 URL
        HttpServletRequest req = (HttpServletRequest) request;
        String url = WebUtil.getRequestPath(req);
        // 从 Hessian Servlet Map 中获取 Hessian Servlet
        HessianServlet hessianServlet = hessianServletMap.get(url);
        if (hessianServlet != null) {
            // 执行 Servlet
            hessianServlet.service(request, response);
        }
    }
}

为了让 Hessian URL 与其它 URL 不同,我们故意给它增加了一个前缀,在常量接口 HessianConstant 中提供了一个 URL_PREFIX 常量,代码如下:

public interface HessianConstant {

    String URL_PREFIX = "/hessian";
}

其实 URL_PREFIX 叫什么名字真的无所谓,关键是需要有别于其它普通 URL 才行,以免被 Smart 的 DispatcherServlet 给截获了。

通过阅读 HessianDispatcherServlet 代码及其相关注释,不难理解:

  • 最核心的就是 Map<String, HessianServlet> hessianServletMap,有了它就能保证不同的 Hessian URL 可以映射到不同的 Hessian Servlet 上。

  • 我们通过遍历所有带有 @Hessian 注解的接口,来找到它们各自的实现类。通过创建 HessianServlet 实例,并设置 Home API(接口)与 Home(实现类实例),最后一定要调用 init 方法来初始化 Servlet。

  • 在 HessianDispatcherServlet 的 service 方法中,只是通过 URL 找到对应的 HessianServlet,并调用它的 service 方法来执行 Servlet。


通过以上三个步骤,就可以实现 Smart Hessian 插件了,我们只需要在 Maven 的 pom.xml 中这样做即可使用该插件:

...
        <dependency>
            <groupId>com.smart</groupId>
            <artifactId>smart-plugin-hessian</artifactId>
            <version>${smart.version}</version>
        </dependency>
...

您可以在 Smart Sample 中尝试一下该功能,如果您打算将 Hessian 集成到您自己的框架中,相信本文会为您提供一些帮助。


如果您也和我一样有些洁癖,不喜欢看到太多的代码细节,或许您会这样提供一个 Hessian 客户端 API:

public class HessianHelper {

    private static final Logger logger = LoggerFactory.getLogger(HessianHelper.class);

    @SuppressWarnings("unchecked")
    public static <T> T createClient(String hessianURL, Class<T> interfaceClass) {
        T client = null;
        try {
            HessianProxyFactory factory = new HessianProxyFactory();
            client = (T) factory.create(interfaceClass, hessianURL);
        } catch (MalformedURLException e) {
            logger.error("创建 Hessian 客户端出错!", e);
        }
        return client;
    }
}

有了 HessianHelper 我们的 Hessian 客户端编写起来会更加轻松:

public class UserServiceHessianTest {

    @Test
    public void loginTest() throws Exception {
        String username = "admin";
        String password = "admin";

        String url = "http://localhost:8080/smart-sample/hessian/user_service";
        UserService userService = HessianHelper.createClient(url, UserService.class);

        User user = userService.login(username, password);
        Assert.assertNotNull(user);
    }
}

客户端需要知道的就两样东西:接口与 URL。Hessian 这麻布袋子还不错吧?


非常感谢 哈库纳 提供的技术指导!有了他的帮助,让我少走了许多弯路。恰巧他今天也写了一篇关于 Hessian 的文章,借此向大家推荐一下:

http://my.oschina.net/u/1166271/blog/187509


相关代码链接

Smart Hessian Plugin 代码:http://git.oschina.net/huangyong/smart-plugin-hessian

Smart Framework 代码:http://git.oschina.net/huangyong/smart-framework

Smart Sample 代码:http://git.oschina.net/huangyong/smart-sample

转载于:https://my.oschina.net/huangyong/blog/187561

开始LED光谱优化... 数据加载完成,开始优化... 使用差分进化算法进行全局优化... differential_evolution step 1: f(x)= inf differential_evolution step 2: f(x)= inf differential_evolution step 3: f(x)= inf differential_evolution step 4: f(x)= inf differential_evolution step 5: f(x)= inf differential_evolution step 6: f(x)= inf differential_evolution step 7: f(x)= inf differential_evolution step 8: f(x)= inf differential_evolution step 9: f(x)= inf differential_evolution step 10: f(x)= inf differential_evolution step 11: f(x)= inf differential_evolution step 12: f(x)= inf differential_evolution step 13: f(x)= inf differential_evolution step 14: f(x)= inf differential_evolution step 15: f(x)= inf differential_evolution step 16: f(x)= inf differential_evolution step 17: f(x)= inf differential_evolution step 18: f(x)= inf differential_evolution step 19: f(x)= inf differential_evolution step 20: f(x)= inf differential_evolution step 21: f(x)= inf differential_evolution step 22: f(x)= inf differential_evolution step 23: f(x)= inf differential_evolution step 24: f(x)= inf differential_evolution step 25: f(x)= inf differential_evolution step 26: f(x)= inf differential_evolution step 27: f(x)= inf differential_evolution step 28: f(x)= inf differential_evolution step 29: f(x)= inf differential_evolution step 30: f(x)= inf differential_evolution step 31: f(x)= inf differential_evolution step 32: f(x)= inf differential_evolution step 33: f(x)= inf differential_evolution step 34: f(x)= inf differential_evolution step 35: f(x)= inf differential_evolution step 36: f(x)= inf differential_evolution step 37: f(x)= inf differential_evolution step 38: f(x)= inf differential_evolution step 39: f(x)= inf differential_evolution step 40: f(x)= inf differential_evolution step 41: f(x)= inf differential_evolution step 42: f(x)= inf differential_evolution step 43: f(x)= inf differential_evolution step 44: f(x)= inf differential_evolution step 45: f(x)= inf differential_evolution step 46: f(x)= inf differential_evolution step 47: f(x)= inf differential_evolution step 48: f(x)= inf differential_evolution step 49: f(x)= inf differential_evolution step 50: f(x)= inf differential_evolution step 51: f(x)= inf differential_evolution step 52: f(x)= inf differential_evolution step 53: f(x)= inf differential_evolution step 54: f(x)= inf differential_evolution step 55: f(x)= inf differential_evolution step 56: f(x)= inf differential_evolution step 57: f(x)= inf differential_evolution step 58: f(x)= inf differential_evolution step 59: f(x)= inf differential_evolution step 60: f(x)= inf differential_evolution step 61: f(x)= inf differential_evolution step 62: f(x)= inf differential_evolution step 63: f(x)= inf differential_evolution step 64: f(x)= inf differential_evolution step 65: f(x)= inf differential_evolution step 66: f(x)= inf differential_evolution step 67: f(x)= inf differential_evolution step 68: f(x)= inf differential_evolution step 69: f(x)= inf differential_evolution step 70: f(x)= inf differential_evolution step 71: f(x)= inf differential_evolution step 72: f(x)= inf differential_evolution step 73: f(x)= inf differential_evolution step 74: f(x)= inf differential_evolution step 75: f(x)= inf differential_evolution step 76: f(x)= inf differential_evolution step 77: f(x)= inf differential_evolution step 78: f(x)= inf differential_evolution step 79: f(x)= inf differential_evolution step 80: f(x)= inf differential_evolution step 81: f(x)= inf differential_evolution step 82: f(x)= inf differential_evolution step 83: f(x)= inf differential_evolution step 84: f(x)= inf differential_evolution step 85: f(x)= inf differential_evolution step 86: f(x)= inf differential_evolution step 87: f(x)= inf differential_evolution step 88: f(x)= inf differential_evolution step 89: f(x)= inf differential_evolution step 90: f(x)= inf differential_evolution step 91: f(x)= inf differential_evolution step 92: f(x)= inf differential_evolution step 93: f(x)= inf differential_evolution step 94: f(x)= inf differential_evolution step 95: f(x)= inf differential_evolution step 96: f(x)= inf differential_evolution step 97: f(x)= inf differential_evolution step 98: f(x)= inf differential_evolution step 99: f(x)= inf differential_evolution step 100: f(x)= inf Polishing solution with 'trust-constr' D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_differentialevolution.py:502: UserWarning: differential evolution didn't find a solution satisfying the constraints, attempting to polish from the least infeasible solution ret = solver.solve() D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_trustregion_constr\equality_constrained_sqp.py:203: UserWarning: Singular Jacobian matrix. Using SVD decomposition to perform the factorizations. Z, LS, Y = projections(A, factorization_method) D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_differentiable_functions.py:504: UserWarning: delta_grad == 0.0. Check if the approximated function is linear. If the function is linear better results can be obtained by defining the Hessian as zero instead of using quasi-Newton approximations. self.H.update(delta_x, delta_g) D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_differentiable_functions.py:231: UserWarning: delta_grad == 0.0. Check if the approximated function is linear. If the function is linear better results can be obtained by defining the Hessian as zero instead of using quasi-Newton approximations. self.H.update(self.x - self.x_prev, self.g - self.g_prev) D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_trustregion_constr\equality_constrained_sqp.py:80: UserWarning: Singular Jacobian matrix. Using SVD decomposition to perform the factorizations. Z, LS, Y = projections(A, factorization_method) 全局优化失败,尝试备用算法... Positive directional derivative for linesearch (Exit mode 8) Current function value: 11.85740523891356 Iterations: 12 Function evaluations: 86 Gradient evaluations: 8 所有优化失败,使用均匀权重 最终性能评估: 1. 色温准确度: |4849.9 - 6000| = 1150.1K 2. 色度坐标误差: 0.0525 3. 保真度指数: 96.94 (目标>88) 4. 色域指数: 21.91 (目标95-105) ⚠️ Rg约束未满足: 21.91 ✅ Rf约束满足 D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_slsqp_py.py:437: RuntimeWarning: Values in x were outside bounds during a minimize step, clipping to bounds fx = wrapped_fun(x) D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_slsqp_py.py:441: RuntimeWarning: Values in x were outside bounds during a minimize step, clipping to bounds g = append(wrapped_grad(x), 0.0) D:\anacondaxiaz\Lib\site-packages\scipy\optimize\_slsqp_py.py:501: RuntimeWarning: Values in x were outside bounds during a minimize step, clipping to bounds a_ieq = vstack([con['jac'](x, *con['args'])
08-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值