博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dubbo学习笔记 第十章dubbo服务实现http调用
阅读量:5823 次
发布时间:2019-06-18

本文共 25485 字,大约阅读时间需要 84 分钟。

 

      之前在网上有看一篇文章,觉得场景描述的很切合实际,就是dubbo经常是内部协作提供服务用的,但是如果涉及到对外服务调用,更多还是提供http,这样就必须实现服务转换为http调用,这篇文章设计还是很巧妙,利用了spring mvc的特性。

     文章的出处:http://blog.csdn.net/qq_18661793/article/details/71156210

     在这我们根据实际的使用,对它进行更进一步的调整,先配置pom.xml

4.0.0
com.crossoverJie
dubbo-http
war
0.0.1-SNAPSHOT
dubbo-http Maven Webapp
http://maven.apache.org
UTF-8
src/main/resources
**/*.properties
**/*.xml
**/*.ini
false
src/main/java
**/*.properties
**/*.xml
false
junit
junit
4.7
test
javax.servlet
jstl
1.2
javax.servlet
jsp-api
2.0
provided
org.apache.tomcat
tomcat-juli
7.0.27
org.apache.httpcomponents
httpclient-cache
4.2.5
org.apache.httpcomponents
httpmime
4.2.5
org.springframework
spring-context
4.2.5.RELEASE
org.springframework
spring-test
4.2.5.RELEASE
org.springframework
spring-webmvc
4.2.5.RELEASE
org.springframework
spring-context-support
4.2.5.RELEASE
org.springframework
spring-core
4.2.5.RELEASE
com.alibaba
druid
1.0.18
org.aspectj
aspectjweaver
1.7.1
org.codehaus.jackson
jackson-mapper-asl
1.9.11
commons-fileupload
commons-fileupload
1.2.2
log4j
log4j
1.2.17
org.slf4j
slf4j-log4j12
1.7.16
com.alibaba
fastjson
1.1.26
commons-attributes
commons-attributes-api
2.1
commons-attributes
commons-attributes-compiler
2.1
ant
ant
1.6.5
commons-beanutils
commons-beanutils-core
1.8.0
commons-codec
commons-codec
1.10
commons-collections
commons-collections
3.2.2
commons-dbcp
commons-dbcp
1.4
commons-httpclient
commons-httpclient
3.1
commons-io
commons-io
2.4
commons-lang
commons-lang
2.6
commons-logging
commons-logging
1.1.3
commons-pool
commons-pool
1.6
net.sf.ezmorph
ezmorph
1.0.6
org.javassist
javassist
3.21.0-GA
com.alibaba
dubbo
2.8.5.1
spring
org.springframework
redis.clients
jedis
2.8.0
com.google.inject
guice
4.1.0
com.netflix.curator
curator-framework
1.1.10
org.apache.curator
curator-framework
2.5.0

spring 相关的配置如下下图:

132538_xFY7_3702.png

dubbo的xml配置如下:spring-dubbo-config.xml的内容:

spring-dubbo-provider.xml的内容:

spring-mvc的内容:

com.crossoverJie.api

下面截图这块的内容实际使用中可以改为从数据库获取服务名的方式,

132600_wow2_3702.png

com.crossoverJie.api和spring-dubbo-provider种的“com.crossoverJie.api.DemoApi”是有对应关系的。

java代码中,有一个核心控制http请求的control类,我对其进行了改写,能更适应多参数的post请求,即把请求的参数都放入map中类似一个表单的请求。

package com.crossoverJie.api.controller;import com.alibaba.fastjson.JSON;import com.crossoverJie.dubbo.http.conf.HttpProviderConf;import com.crossoverJie.dubbo.http.req.HttpRequest;import com.crossoverJie.dubbo.http.rsp.HttpResponse;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.HashMap;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.BeansException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Controller;import org.springframework.util.CollectionUtils;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import java.lang.reflect.Field; @Controller@RequestMapping({"/dubboapi"})public class DubboController  implements ApplicationContextAware{  private static final Logger logger = LoggerFactory.getLogger(DubboController.class);    @Autowired  private HttpProviderConf httpProviderConf;    private final Map
> cacheMap = new HashMap(); protected ApplicationContext applicationContext; @ResponseBody @RequestMapping(value={"/{service}/{method}"}, method={org.springframework.web.bind.annotation.RequestMethod.POST}) public String api(HttpRequest httpRequest, HttpServletRequest request, @RequestParam Map
map,@PathVariable String service, @PathVariable String method) { logger.debug("ip:{}-httpRequest:{}", getIP(request), JSON.toJSONString(httpRequest)); String invoke = invoke(httpRequest, service, method,map); logger.debug("callback :" + invoke); return invoke; } private String invoke(HttpRequest httpRequest, String service, String method,Map
map) { httpRequest.setService(service); httpRequest.setMethod(method); HttpResponse response = new HttpResponse(); logger.debug("input param:" + JSON.toJSONString(httpRequest)); if (!CollectionUtils.isEmpty(httpProviderConf.getUsePackage())) { boolean isPac = false; for (String pac : httpProviderConf.getUsePackage()) { if (service.startsWith(pac)) { isPac = true; break; } } if (!isPac) { logger.error("service is not correct,service=" + service); response.setCode("2"); response.setSuccess(false); response.setDescription("service is not correct,service=" + service); } } try { Class
serviceCla = (Class)cacheMap.get(service); if (serviceCla == null) { serviceCla = Class.forName(service); logger.debug("serviceCla:" + JSON.toJSONString(serviceCla)); cacheMap.put(service, serviceCla); } Method[] methods = serviceCla.getMethods(); Method targetMethod = null; for (Method m : methods) { if (m.getName().equals(method)) { targetMethod = m; break; } } if (method == null) { logger.error("method is not correct,method=" + method); response.setCode("2"); response.setSuccess(false); response.setDescription("method is not correct,method=" + method); } Object bean = applicationContext.getBean(serviceCla); Object result = null; Class
[] parameterTypes = targetMethod.getParameterTypes(); if (parameterTypes.length == 0) { result = targetMethod.invoke(bean, new Object[0]); } /*else if (parameterTypes.length == 1) { Object json = JSON.parseObject(httpRequest.getParam(), parameterTypes[0]); result = targetMethod.invoke(bean, new Object[] { json }); } */else { result = targetMethod.invoke(bean, map); logger.info("Can have map parameter"); response.setSuccess(true); response.setCode("1"); response.setDescription("Can only have one parameter"); } return JSON.toJSONString(result); } catch (ClassNotFoundException e) { logger.error("class not found", e); response.setSuccess(false); response.setCode("2"); response.setDescription("class not found"); } catch (InvocationTargetException e) { logger.error("InvocationTargetException", e); response.setSuccess(false); response.setCode("2"); response.setDescription("InvocationTargetException"); } catch (IllegalAccessException e) { logger.error("IllegalAccessException", e); response.setSuccess(false); response.setCode("2"); response.setDescription("IllegalAccessException"); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } return JSON.toJSONString(response); } private String getIP(HttpServletRequest request) { if (request == null) return null; String s = request.getHeader("X-Forwarded-For"); if ((s == null) || (s.length() == 0) || ("unknown".equalsIgnoreCase(s))) { s = request.getHeader("Proxy-Client-IP"); } if ((s == null) || (s.length() == 0) || ("unknown".equalsIgnoreCase(s))) { s = request.getHeader("WL-Proxy-Client-IP"); } if ((s == null) || (s.length() == 0) || ("unknown".equalsIgnoreCase(s))) { s = request.getHeader("HTTP_CLIENT_IP"); } if ((s == null) || (s.length() == 0) || ("unknown".equalsIgnoreCase(s))) { s = request.getHeader("HTTP_X_FORWARDED_FOR"); } if ((s == null) || (s.length() == 0) || ("unknown".equalsIgnoreCase(s))) { s = request.getRemoteAddr(); } if (("127.0.0.1".equals(s)) || ("0:0:0:0:0:0:0:1".equals(s))) try { s = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException unknownhostexception) { return ""; } return s; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}

被这个control类引用的还有:

package com.crossoverJie.dubbo.http.conf;  import java.util.List;     public class HttpProviderConf {   private List
usePackage; public List
getUsePackage() { return usePackage; } public void setUsePackage(List
usePackage) { this.usePackage = usePackage; } }

上面这个类跟相对应,个人觉得使用意义不是太大。

132600_wow2_3702.png

package com.crossoverJie.dubbo.http.req;public class HttpRequest{  private String param;    private String service;    private String method;    public String getParam()  {    return param;  }    public void setParam(String param) {    this.param = param;  }    public String getService() {    return service;  }    public void setService(String service) {    this.service = service;  }    public String getMethod() {    return method;  }    public void setMethod(String method) {    this.method = method;  }}
package com.crossoverJie.dubbo.http.rsp;import java.io.Serializable;public class HttpResponse  implements Serializable{  private static final long serialVersionUID = -552828440320737814L;  private boolean success;  private String code;  private String description;    public boolean isSuccess()  {    return success;  }    public void setSuccess(boolean success) {    this.success = success;  }    public String getCode() {    return code;  }    public void setCode(String code) {    this.code = code;  }    public String getDescription() {    return description;  }    public void setDescription(String description) {    this.description = description;  }}

接下来我们写一下测试相关类:

package com.crossoverJie.api.impl;import java.util.Map;import com.alibaba.dubbo.config.annotation.Service;import com.alibaba.fastjson.JSON;import com.crossoverJie.api.DemoApi;/** * Function: * @author chenjiec * Date: 2017/3/1 下午11:42 * @since JDK 1.7 */@Servicepublic class DemoApiImpl implements DemoApi {    /**     * 获取用户信息     *     * @param userId     * @return     * @throws RuntimeException     */    public String readMsg(Map
arg) throws RuntimeException { String json_str=JSON.toJSONString(arg); return json_str; }}
package com.crossoverJie.api;import java.util.Map;public interface DemoApi {	   String readMsg(Map
arg)throws RuntimeException;}

以上是服务器接口相关类

http请求工具类

package com.crossoverJie.dto;import java.io.BufferedReader;  import java.io.InputStreamReader;  import java.io.OutputStreamWriter;  import java.net.HttpURLConnection;  import java.net.URL;  import java.util.Map;  import java.util.Map.Entry;    public class HttpUtil {        public static String http(String url, Map
params) { URL u = null; HttpURLConnection con = null; // 构建请求参数 StringBuffer sb = new StringBuffer(); if (params != null) { for (Entry
e : params.entrySet()) { sb.append(e.getKey()); sb.append("="); sb.append(e.getValue()); sb.append("&"); } sb.substring(0, sb.length() - 1); } System.out.println("send_url:" + url); System.out.println("send_data:" + sb.toString()); // 尝试发送请求 try { u = new URL(url); con = (HttpURLConnection) u.openConnection(); POST 只能为大写,严格限制,post会不识别 con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8"); osw.write(sb.toString()); osw.flush(); osw.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.disconnect(); } } // 读取返回内容 StringBuffer buffer = new StringBuffer(); try { //一定要有返回值,否则无法把请求发送给server端。 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); String temp; while ((temp = br.readLine()) != null) { buffer.append(temp); buffer.append("\n"); } } catch (Exception e) { e.printStackTrace(); } return buffer.toString(); } }

http请求调用类

package com.crossoverJie.api.controller;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.URL;import java.net.URLConnection;import java.util.HashMap;import java.util.List;import java.util.Map;import com.crossoverJie.dto.HttpUtil;public class HttpRequestTest {    /**     * 向指定URL发送GET方法的请求     *      * @param url     *            发送请求的URL     * @param param     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。     * @return URL 所代表远程资源的响应结果     */    public static String sendGet(String url, String param) {        String result = "";        BufferedReader in = null;        try {            String urlNameString = url + "?" + param;            URL realUrl = new URL(urlNameString);            // 打开和URL之间的连接            URLConnection connection = realUrl.openConnection();            // 设置通用的请求属性            connection.setRequestProperty("accept", "*/*");            connection.setRequestProperty("connection", "Keep-Alive");            connection.setRequestProperty("user-agent",                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");            // 建立实际的连接            connection.connect();            // 获取所有响应头字段            Map
> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } public void testMaprequest() { Map parames = new HashMap
(); parames.put("num", "456"); parames.put("id", "123"); parames.put("name", "srp"); // 如果地址栏中有aaa这个参数,则默认选择地址栏的,如果没有则选择添加的参数 parames.put("userid", "aaa_value"); String sr=HttpUtil.http("http://localhost:8080/dubbo-http/dubboapi/com.crossoverJie.api.DemoApi/readMsg", parames); System.out.println(sr); } public static void main(String[] args) { HttpRequestTest rs =new HttpRequestTest(); rs.testMaprequest(); }}

上面代码中:http://localhost:8080/dubbo-http/dubboapi/com.crossoverJie.api.DemoApi/readMsg

dubbo-http是我取的项目名称,dubboapi就是对于上面那个control类的注解内容,com.crossoverJie.api.DemoApi对于接口服务,readMsg对应类中被调用的方法,parames是一个map参数。在实际使用中应该还要有证书之类的,保证接口被调用的安全性。

最后看下web.xml的内容配置:

Archetype Created Web Application
turnToIndex.jsp
contextConfigLocation
classpath*:spring/*.xml
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
true
encoding
UTF-8
encodingFilter
/*
org.springframework.web.context.ContextLoaderListener
org.springframework.web.util.IntrospectorCleanupListener
SpringMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
true
SpringMVC
/
index.jsp
30
DruidWebStatFilter
com.alibaba.druid.support.http.WebStatFilter
exclusions
*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,/download/*
DruidWebStatFilter
/*
DruidStatView
com.alibaba.druid.support.http.StatViewServlet
loginUsername
druid
loginPassword
druid
DruidStatView
/druid/*
default
*.jpg
default
*.png
default
*.gif
default
*.js
default
*.css
default
*.swf
default
*.html
default
*.txt
default
*.ico
404
/notfound.jsp

整体项目运行结果如下:

134300_XyHE_3702.png

返回了一json 字符串

转载于:https://my.oschina.net/u/3702/blog/1570415

你可能感兴趣的文章
CentOS 7 装vim遇到的问题和解决方法
查看>>
JavaScript基础教程1-20160612
查看>>
ios xmpp demo
查看>>
python matplotlib 中文显示参数设置
查看>>
【ros】Create a ROS package:package dependencies报错
查看>>
通过容器编排和服务网格来改进Java微服务的可测性
查看>>
re:Invent解读:没想到你是这样的AWS
查看>>
PyTips 0x02 - Python 中的函数式编程
查看>>
阿里云安全肖力:安全基础建设是企业数字化转型的基石 ...
查看>>
使用《Deep Image Prior》来做图像复原
查看>>
Linux基础命令---rmdir
查看>>
Android图片添加水印图片并把图片保存到文件存储
查看>>
BigDecimal 舍入模式(Rounding mode)介绍
查看>>
开源 免费 java CMS - FreeCMS1.2-标签 infoSign
查看>>
Squid 反向代理服务器配置
查看>>
Java I/O操作
查看>>
Tomcat性能调优
查看>>
Android自学--一篇文章基本掌握所有的常用View组件
查看>>
灰度图像和彩色图像
查看>>
FreeMarker-Built-ins for strings
查看>>