spring整合hessian簡化rpc呼叫
阿新 • • 發佈:2018-12-16
maven配置:略
服務端 HessianServiceExporterController.java
/** * web.xml中不需要額外的servlet. * 對於hessian呼叫的理解,實際上就是http請求,然後在請求頭加了特殊的Header, * 請求體的內容使用hessian協議序列化和反序列化。 * spring提供了HessianServiceExporter,封裝了協議處理的部分, * 我們只需要注入service和serviceInterface即可。 * 所以實現將hessian呼叫簡化的邏輯是, * 接收/hessian/**請求,根據請求的uri獲取對應的HessianServiceExporter。 * 每一個HessianServiceExporter封裝一個service。 * 將service的name和uri也對應起來(使用了HessianService註解的service), * 那麼我們只需要提供service,就可以將多個service暴露為hessian服務了。 * */ @Controller @RequestMapping("/hessian") public class HessianServiceExporterController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private Map<String, HessianServiceExporter> uri2Exporter = new HashMap<>(); private Map<String, Object> beanName2Service; @PostConstruct public void init() throws ClassNotFoundException { ApplicationContext appContext = AppContextHolder.getApplicationContext(); WebApplicationContext webappContext = AppContextHolder.getWebApplicationContext(); beanName2Service = appContext.getBeansWithAnnotation(HessianService.class); beanName2Service.putAll(webappContext.getBeansWithAnnotation(HessianService.class)); logger.info("beanName2Service:"+beanName2Service.toString()); String contextPath = webappContext.getServletContext().getContextPath(); for (String beanname : beanName2Service.keySet()) { Object service = beanName2Service.get(beanname); Class<?> serviceInterface = findServiceInterface(service); HessianServiceExporter exporter = new HessianServiceExporter(); exporter.setService(service); exporter.setServiceInterface(serviceInterface); exporter.prepare(); uri2Exporter.put(contextPath+"/hessian/"+beanname, exporter); } logger.info("uri2Exporter:"+uri2Exporter.toString()); } private Class<?> findServiceInterface(Object service) throws ClassNotFoundException{ Class<?> serviceClazz = service.getClass(); String serviceClassName = serviceClazz.getName(); if (serviceClassName.contains("$")) { serviceClazz = Class.forName(serviceClassName.substring(0, serviceClassName.indexOf("$"))); } Class<?>[] interfaces = serviceClazz.getInterfaces(); if (interfaces == null || interfaces.length != 1) { throw new RuntimeException("service must implements one and only one interfaces!"); } Class<?> serviceInterface = interfaces[0]; return serviceInterface; } @RequestMapping("/**") public Object replay(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ClassNotFoundException { String uri = request.getRequestURI(); // 根據uri獲取exporter,每個exporter包含一個服務。 HessianServiceExporter exporter = uri2Exporter.get(uri); if(exporter==null){ throw new RuntimeException("hessian exporter not found for uri: "+uri); } exporter.handleRequest(request, response); return null; } }
HessianService.java
@Target({ java.lang.annotation.ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HessianService {
}
AppContextHolder.java
@Component public class AppContextHolder implements ApplicationContextAware{ private static WebApplicationContext webApplicationContext; private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ApplicationContext parent = applicationContext.getParent(); if(parent==null){ AppContextHolder.applicationContext = applicationContext; }else{ AppContextHolder.applicationContext = parent; AppContextHolder.webApplicationContext = (WebApplicationContext) applicationContext; } } public static ApplicationContext getApplicationContext(){ return applicationContext; } public static WebApplicationContext getWebApplicationContext(){ return webApplicationContext; } }
對於service,需要實現一個介面,並且新增@HessianService註解,即可被當成hessian服務。
客戶端
public class JobTest { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Test public void test() throws MalformedURLException { HessianProxyFactory factory = new HessianProxyFactory(); MyJob api = (MyJob) factory.create(MyJob.class, "http://127.0.0.1:8081/jyd-interface-mock/hessian/myJob"); JSONObject res = api.test("abc"); System.out.println(res); logger.info("" + res); } }