首页 文章 精选 留言 我的

精选列表

搜索[编译原理],共10000篇文章
优秀的个人博客,低调大师

LangChain原理学习笔记

最新越发觉得AI的发展,对未来是一场革命,LangChain已经在工程设计上有了最佳实践,类似于AI时代的编程模型或编程框架,有点Spring框架的意思。之前在LangChain上也有些最佳实践,所以在这里分享记录下。 LangChain解决什么问题 LangChain是基于LLM之上的,在应用层和底层LLM之前的一个很好的编程框架,如果把LLM比喻为各种类型的数据库、中间件等这些基础设施,应用层是各种业务逻辑的组合之外,那么LangChain就负责桥接与业务层和底层LLM模型,让开发者可以快速地实现对接各种底层模型和快速实现业务逻辑的软件开发框架。 那么LangChain是如何做到的呢?试想一下,现在底层有一个大模型的推理能力,除了在对话框手动输入跟他聊天之外。如何用计算机方式跟它互动呢?如果把一次LLM调用当作一个原子能力,如何编排这些原子能力来解决一些业务需求呢?Langchain就是来解决这个事情的。 LangChain的几个核心概念 ▐Model I/O 这里重点把背后的LLM模型做了一层封装,开发者可以通过更改配置的方式快速切换底层LLM模型,比如chatgpt,chatGLM、通义千问等模型。 同时还有些高阶功能:比如提供了缓存等功能,这样对于语义上类似的query,如果缓存有,那么langchain可以快速返回结果,而不需要调用大模型。 ▐Retriver 检索是为了解决大模型打通用户的本身数据,做一些面向业务属性的东西。这里的检索并非传统的关系型数据库,更多的是与大模型的本身逻辑相似的,比如向量数据库。 一个经典的结合LLM和外部用户的文档进行智能答疑的场景 文档->分词->embedding->向量数据库 query->向量数据库查询->TOP N->上下文+ 用户提问 + prompt -> LLM -> 返回结果 一个经典的图如下: 关键技术:文档如何拆分、embedding过程、 TOPN 向量距离的选择 embedding技术选型 embedding是将现实中的物体通过向量化的方法转化为高维向量,可被机器学习模型所识别。他是一种映射,同时也保证了能清晰地表达现实物体的特征。基于此,可以进行一些归类分析、回归分析等。 现在市面上常见的embedding方法有通义千问的embedding等方法。 向量数据库: 向量数据库底层存储的是一堆向量,它提供了根据向量相似度进行查询的能力,一般情况下,向量相似度代表了现实世界中物体的相似度。比如”我的名字是小明“ 和“我叫小明”这两句话所代表的含义几乎是相同的,那么在embedding之后,基于向量数据库进行查询的时候,它们俩的相似度就会很近。 ▐Chain 各种类型的chain,chain代表了各种业务类型的组合,类似于工作流的编排。 ▐Memory LLM本身提供了记忆的能力,同时提供了接口,开发者可以将历史的对话记录传入给LLM。LangChain需要使用外部存储保存这些历史的会话和记忆。可以使用数据库、缓存等进行保存。 ▐Agent 重点是代理工具 代理工具可以让应用程序基于大模型的推理能力,然后进行代理工具或代理服务的调用。因为LLM是没有“联网”的能力的,如果想解决特定的应用场景,代理工具是个完美的选择。 代理工具通常包含三个方面:用户输入、prompt编排LLM思考与路由代理的过程、背后的代理服务。其中难点可能就在于prompt设计了。通常的“套路”是这样的: ReAct 模型 输入:用户的问题 思考过程:如果是情况1(这个是需要LLM进行意图识别进行思考的),那么推理和提取出一些关键参数,调用agent1,如果是情况2,那么推理和提取出一些关键参数,调用agent2 Act:调用agent1对应一个JSON格式化的输入,调用function1,返回结果。 观察:观察调用后的结果,再结合推理的能力,再进行循环思考。 LangChain的在实际场景中的实践 集团内部开发了一个JAVA版本的LangChain框架,以下实践基于此框架与开源大模型chatGLM-6B进行。 ▐淘宝开放平台智能问答 淘宝开放平台对内托管了上万个API,每天在内部群里都会有开发者咨询API发布问题,之前我们是通过NLP来实现智能问答的,现将它升级为基于大模型的智能问答,以下是具体的技术实现过程。 知识库Embedding过程 由于之前已经沉淀好了很多知识库,都是Question-Answer的这种形式,这里我们对Question,也就是问题进行Embedding,此处采用通义千问提供的Embedding方法。 知识库embedding: TongYiEmbeddings embeddings = new TongYiEmbeddings();embeddings.setServerAccessId(ALINLP_EMBEDDINGS_ACCESSID);embeddings.setServerUrl(ALINLP_EMBEDDINGS_SERVER_URL);embeddings.setServerUuid(ALINLP_EMBEDDINGS_UUID);Document document = new Document();document.setPageContent(rawText);List<Document> documents = embeddings.embedDocument(Arrays.asList(document));Document vecDocument= documents.get(0);// 向量化知识String embeddingString = JSON.toJSONString(vecDocument.getEmbedding()).replaceAll("\\[", "{").replaceAll("\\]", "}");return embeddingString; 向量数据库存储和查询 此处采用hologres向量数据库,图中红框表示知识库问题与回答在数据库中具体的向量化存储数据。 向量距离数据库查询: select origin_content as originContent, origin_title as originTitle, pm_approx_squared_euclidean_distance(embedding_title, #{embeddingTitle}) as distancefrom vs_knowledgeorder by distance asclimit #{limit} 大模型问答链路 问答chain的基本实现: //1. 初始化ChatGLM的参数ChatGLMV2Internal chatGLMV2Internal = new ChatGLMV2Internal();chatGLMV2Internal.setTemperature(0.01d);chatGLMV2Internal.setMaxLength(2048);//2. 提示词编写PromptTemplate prompt = new PromptTemplate();String template = "已知信息:\n" +"{context} \n" +"\n" +"根据上述已知信息,简洁和专业的来回答用户的问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题” 或 “没有提供足够的相关信息”,不允许在答案中添加编造成分,答案请使用中文。问题是:{question}";prompt.setTemplate(template);//3. 向量数据库检索配置,比如最大向量距离RetrievalQA qa = new RetrievalQA();qa.setRecommend(5);qa.setMaxDistanceValue(10000.0d);qa.setLlm(chatGLMV2Internal);qa.setPrompt(prompt);qa.setRetriever(holoRetriver.asRetriever());qa.init();//4. LLM大模型问答Map<String, Object> inputs = new HashMap<>();inputs.put("question", question);inputs.put("input", question);Map<String, Object> outputs = qa.run(inputs);llmKonwledgeDO.setContent(String.valueOf(outputs.get("text")));// 补充 doclistreturn llmKonwledgeDO; ▐AI Agent实践 以下实现了一个网关API调用日志解析的agent。 Agent工具注册: this.setName("ApiLogTool");this.setDescription("这是一个调用日志查询接口,如果[{question}]中包含requestId关键字,你可以请求这个工具与日志系统进行交互,调用这个工具。\n" + "请先提取出requestId的值,将它赋值为value。调用参数:[{\"requestId\": \"value\", \"type\": \"String\", \"description\": \"调用请求id\"}]。"); 工具解析: Map<String,Object> parse = (Map<String,Object>)JSON.parse(toolInput);if(parse.get("requestId")==null){ return new ToolExecuteResult("");}String requestId = parse.get("requestId").toString();ApiLogSearchQuery apiLogSearchQuery = new ApiLogSearchQuery();//日志查询解析处理 思考决策逻辑: public static final String FORMAT_INSTRUCTIONS_CH ="用户提出了一个问题: {question} \n" +"你可以选择使用下面这些工具:\n"+"{tool_list_description}"+"\n"+"同时你的思考过程如下:"+"Thought: 每一次你需要首先思考你应该做什么\n" +"Action: 你需要决定是否使用工具,应该是[{tool_names}] 中的一个Action,格式为JSON。如果匹配不到工具,就不要思考了,直接返回结果,请不要把思考过程返回给用户。\n" +"Input: 如果匹配到工具,使用的工具的输入参数,赋值给params\n" +"Observation: 如果匹配到工具,工具的输出结果 格式为[]。\n" +"Answer: 每一步回答问题的答案,格式为JSON。你可以多次使用Thought/Action/Input/Observation/Answer来一步一步的思考如何回答问题。\n"; 个人小思考 未来微服务HSF这种形式会向上往 agent工厂或者agent服务框架这种形式演进,因为这个框架搭好了后,后面各个业务方快速集成到agent服务上,可被上层AI应用层调用 如果多个agent联动了,才是真正的智能 如何定义agent? Agent体系架构可以分为慎思型、反应型和混合型。 慎思型构建负责规划和推理行为,反应型构建处理需要快速响应的重要事件。 信念-期望-意图(Belief-Desire-ltension, BDI) 体系架构是混合型体系架构的一个重要类型。 Agent的表示形式,Agent的行为可以被描述成好像拥有信念、期望和意图等思维状态。信念表示Agent拥有的知识,期望描述Agent追求的目标,意图说明Agent选择计划以实现哪些目标。 openai提供的agent概念 团队介绍 我们是淘天集团商家与开放平台团队,目前主要围绕商家的日常经营场景,为中小商家提供高效易用的电商工具。 ¤ 拓展阅读 ¤ 3DXR技术| 终端技术| 音视频技术 服务端技术|技术质量|数据算法 本文分享自微信公众号 - 大淘宝技术(AlibabaMTT)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

网络编程与通信原理

总感觉这个概念,和研发有点脱节; 一、基础概念 不同设备之间通过网络进行数据传输,并且基于通用的网络协议作为多种设备的兼容标准,称为网络通信; 以C/S架构来看,在一次请求当中,客户端和服务端进行数据传输的交互时,在不同阶段和层次中需要遵守的网络通信协议也不一样; 应用层:HTTP超文本传输协议,基于TCP/IP通信协议来传递数据; 传输层:TCP传输控制协议,采用三次握手的方式建立连接,形成数据传输通道; 网络层:IP协议,作用是把各种传输的数据包发送给请求的接收方; 通信双方进行交互时,发送方数据在各层传输时,每通过一层就会添加该层的首部信息;接收方与之相反,每通过一次就会删除该层的首部信息; 二、JDK源码 在java.net源码包中,提供了与网络编程相关的基础API; 1、InetAddress 封装了对IP地址的相关操作,在使用该API之前可以先查看本机的hosts的映射,Linux系统中在/etc/hosts路径下; import java.net.InetAddress; public class TestInet { public static void main(String[] args) throws Exception { // 获取本机 InetAddress 对象 InetAddress localHost = InetAddress.getLocalHost(); printInetAddress(localHost); // 获取指定域名 InetAddress 对象 InetAddress inetAddress = InetAddress.getByName("www.baidu.com"); printInetAddress(inetAddress); // 获取本机配置 InetAddress 对象 InetAddress confAddress = InetAddress.getByName("nacos-service"); printInetAddress(confAddress); } public static void printInetAddress (InetAddress inetAddress){ System.out.println("InetAddress:"+inetAddress); System.out.println("主机名:"+inetAddress.getHostName()); System.out.println("IP地址:"+inetAddress.getHostAddress()); } } 2、URL 统一资源定位符,URL一般包括:协议、主机名、端口、路径、查询参数、锚点等,路径+查询参数,也被称为文件; import java.net.URL; public class TestURL { public static void main(String[] args) throws Exception { URL url = new URL("https://www.baidu.com:80/s?wd=Java#bd") ; printURL(url); } private static void printURL (URL url){ System.out.println("协议:" + url.getProtocol()); System.out.println("域名:" + url.getHost()); System.out.println("端口:" + url.getPort()); System.out.println("路径:" + url.getPath()); System.out.println("参数:" + url.getQuery()); System.out.println("文件:" + url.getFile()); System.out.println("锚点:" + url.getRef()); } } 3、HttpURLConnection 作为URLConnection的抽象子类,用来处理针对Http协议的请求,可以设置连接超时、读取超时、以及请求的其他属性,是服务间通信的常用方式; public class TestHttp { public static void main(String[] args) throws Exception { // 访问 网址 内容 URL url = new URL("https://www.jd.com"); HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection(); printHttp(httpUrlConnection); // 请求 服务 接口 URL api = new URL("http://localhost:8082/info/99"); HttpURLConnection apiConnection = (HttpURLConnection) api.openConnection(); apiConnection.setRequestMethod("GET"); apiConnection.setConnectTimeout(3000); printHttp(apiConnection); } private static void printHttp (HttpURLConnection httpUrlConnection) throws Exception{ try (InputStream inputStream = httpUrlConnection.getInputStream()) { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line ; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } } } 三、通信编程 1、Socket Socket也被称为套接字,是两台设备之间通信的端点,会把网络连接当成流处理,则数据以IO形式传输,这种方式在当前被普遍采用; 从网络编程直接跳到Socket套接字,概念上确实有较大跨度,概念过度抽象时,可以看看源码的核心结构,在理解时会轻松很多,在JDK中重点看SocketImpl抽象类; public abstract class SocketImpl implements SocketOptions { // Socket对象,客户端和服务端 Socket socket = null; ServerSocket serverSocket = null; // 套接字的文件描述对象 protected FileDescriptor fd; // 套接字的路由IP地址 protected InetAddress address; // 套接字连接到的远程主机上的端口号 protected int port; // 套接字连接到的本地端口号 protected int localport; } 套接字的抽象实现类,是实现套接字的所有类的公共超类,可以用于创建客户端和服务器套接字; 所以到底如何理解Socket概念?从抽象类中来看,套接字就是指代网络通讯中系统资源的核心标识,比如通讯方IP地址、端口、状态等; 2、SocketServer 创建Socket服务端,并且在8989端口监听,接收客户端的连接请求和相关信息,并且响应客户端,发送指定的数据; public class SocketServer { public static void main(String[] args) throws Exception { // 1、创建Socket服务端 ServerSocket serverSocket = new ServerSocket(8989); System.out.println("socket-server:8989,waiting connect..."); // 2、方法阻塞等待,直到有客户端连接 Socket socket = serverSocket.accept(); System.out.println("socket-server:8989,get connect:"+socket.getPort()); // 3、输入流,输出流 InputStream inStream = socket.getInputStream(); OutputStream outStream = socket.getOutputStream(); // 4、数据接收和响应 byte[] buf = new byte[1024]; int readLen = 0; while ((readLen=inStream.read(buf)) != -1){ // 接收数据 String readVar = new String(buf, 0, readLen) ; if ("exit".equals(readVar)){ break ; } System.out.println("recv:"+readVar+";time:"+DateTime.now().toString(DatePattern.NORM_DATETIME_PATTERN)); // 响应数据 outStream.write(("resp-time:"+DateTime.now().toString(DatePattern.NORM_DATETIME_PATTERN)).getBytes()); } // 5、资源关闭 outStream.close(); inStream.close(); socket.close(); serverSocket.close(); System.out.println("socket-server:8989,exit..."); } } 需要注意的是步骤2输出的端口号是随机不确定的,结合jps和lsof -i tcp:port命令查看进程和端口号的占用情况; 3、SocketClient 创建Socket客户端,并且连接到服务端,读取命令行输入的内容并发送到服务端,并且输出服务端的响应数据; public class SocketClient { public static void main(String[] args) throws Exception { // 1、创建Socket客户端 Socket socket = new Socket(InetAddress.getLocalHost(), 8989); System.out.println("server-client,connect to:8989"); // 2、输入流,输出流 OutputStream outStream = socket.getOutputStream(); InputStream inStream = socket.getInputStream(); // 3、数据发送和响应接收 int readLen = 0; byte[] buf = new byte[1024]; while (true){ // 读取命令行输入 BufferedReader bufReader = new BufferedReader(new InputStreamReader(System.in)); String iptLine = bufReader.readLine(); if ("exit".equals(iptLine)){ break; } // 发送数据 outStream.write(iptLine.getBytes()); // 接收数据 if ((readLen = inStream.read(buf)) != -1) { System.out.println(new String(buf, 0, readLen)); } } // 4、资源关闭 inStream.close(); outStream.close(); socket.close(); System.out.println("socket-client,get exit command"); } } 测试结果:整个流程在没有收到客户端的exit退出指令前,会保持连接的状态,并且可以基于字节流模式,进行持续的数据传输; 4、字符流使用 基于上述的基础案例,采用字符流的方式进行数据传输,客户端和服务端只进行一次简单的交互; -- 1、客户端 BufferedReader bufReader = new BufferedReader(new InputStreamReader(inStream)); BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(outStream)); // 客户端发送数据 bufWriter.write("hello,server"); bufWriter.newLine(); bufWriter.flush(); // 客户端接收数据 System.out.println("client-read:"+bufReader.readLine()); -- 2、服务端 BufferedReader bufReader = new BufferedReader(new InputStreamReader(inStream)); BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(outStream)); // 服务端接收数据 System.out.println("server-read:"+bufReader.readLine()); // 服务端响应数据 bufWriter.write("hello,client"); bufWriter.newLine(); bufWriter.flush(); 5、文件传输 基于上述的基础案例,客户端向服务端发送图片文件,服务端完成文件的读取和保存,在处理完成后给客户端发送结果描述; -- 1、客户端 // 客户端发送图片 FileInputStream fileStream = new FileInputStream("Local_File_Path/jvm.png"); byte[] bytes = new byte[1024]; int i = 0; while ((i = fileStream.read(bytes)) != -1) { outStream.write(bytes); } // 写入结束标记,禁用此套接字的输出流,之后再使用输出流会抛异常 socket.shutdownOutput(); // 接收服务端响应结果 System.out.println("server-resp:"+new String(bytes,0,readLen)); -- 2、服务端 // 接收客户端图片 FileOutputStream fileOutputStream = new FileOutputStream("Local_File_Path/new_jvm.png"); byte[] bytes = new byte[1024]; int i = 0; while ((i = inStream.read(bytes)) != -1) { fileOutputStream.write(bytes, 0, i); } // 响应客户端文件处理结果 outStream.write("file-save-success".getBytes()); 6、TCP协议 Socket网络编程是基于TCP协议的,TCP传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,在上述案例中侧重基于流的数据传输,其中关于连接还涉及两个核心概念: 三次握手:建立连接的过程,在这个过程中进行了三次网络通信,当连接处于建立的状态,就可以进行正常的通信,即数据传输;四次挥手:关闭连接的过程,调用close方法,即连接使用结束,在这个过程中进行了四次网络通信; 四、Http组件 在服务通信时依赖网络,而对于编程来说,更常见的是的Http的组件,在微服务架构中,涉及到Http组件工具有很多,例如Spring框架中的RestTemplate,Feign框架支持ApacheHttp和OkHttp;下面围绕几个常用的组件编写测试案例; 1、基础接口 @RestController public class BizWeb { @GetMapping("/getApi/{id}") public Rep<Integer> getApi(@PathVariable Integer id){ log.info("id={}",id); return Rep.ok(id) ; } @GetMapping("/getApi_v2/{id}") public Rep<Integer> getApiV2(HttpServletRequest request, @PathVariable Integer id, @RequestParam("name") String name){ String token = request.getHeader("Token"); log.info("token={},id={},name={}",token,id,name); return Rep.ok(id) ; } @PostMapping("/postApi") public Rep<IdKey> postApi(HttpServletRequest request,@RequestBody IdKey idKey){ String token = request.getHeader("Token"); log.info("token={},idKey={}", token,JSONUtil.toJsonStr(idKey)); return Rep.ok(idKey) ; } @PutMapping("/putApi") public Rep<IdKey> putApi(@RequestBody IdKey idKey){ log.info("idKey={}", JSONUtil.toJsonStr(idKey)); return Rep.ok(idKey) ; } @DeleteMapping("/delApi/{id}") public Rep<Integer> delApi(@PathVariable Integer id){ log.info("id={}",id); return Rep.ok(id) ; } } 2、ApacheHttp public class TestApacheHttp { private static final String BASE_URL = "http://localhost:8083" ; public static void main(String[] args) { BasicHeader header = new BasicHeader("Token","ApacheSup") ; // 1、发送Get请求 Map<String,String> param = new HashMap<>() ; param.put("name","cicada") ; Rep getRep = doGet(BASE_URL+"/getApi_v2/3",header,param, Rep.class); System.out.println("get:"+getRep); // 2、发送Post请求 IdKey postBody = new IdKey(1,"id-key-我") ; Rep postRep = doPost (BASE_URL+"/postApi", header, postBody, Rep.class); System.out.println("post:"+postRep); } /** * 构建HttpClient对象 */ private static CloseableHttpClient buildHttpClient (){ // 请求配置 RequestConfig reqConfig = RequestConfig.custom().setConnectTimeout(6000).build(); return HttpClients.custom() .setDefaultRequestConfig(reqConfig).build(); } /** * 执行Get请求 */ public static <T> T doGet (String url, Header header, Map<String,String> param, Class<T> repClass) { // 创建Get请求 CloseableHttpClient httpClient = buildHttpClient(); HttpGet httpGet = new HttpGet(); httpGet.addHeader(header); try { URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } httpGet.setURI(builder.build()); // 请求执行 HttpResponse httpResponse = httpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() == 200) { // 结果转换 String resp = EntityUtils.toString(httpResponse.getEntity()); return JSONUtil.toBean(resp, repClass); } } catch (Exception e) { e.printStackTrace(); } finally { IoUtil.close(httpClient); } return null; } /** * 执行Post请求 */ public static <T> T doPost (String url, Header header, Object body,Class<T> repClass) { // 创建Post请求 CloseableHttpClient httpClient = buildHttpClient(); HttpPost httpPost = new HttpPost(url); httpPost.addHeader(header); StringEntity conBody = new StringEntity(JSONUtil.toJsonStr(body),ContentType.APPLICATION_JSON); httpPost.setEntity(conBody); try { // 请求执行 HttpResponse httpResponse = httpClient.execute(httpPost); if (httpResponse.getStatusLine().getStatusCode() == 200) { // 结果转换 String resp = EntityUtils.toString(httpResponse.getEntity()); return JSONUtil.toBean(resp, repClass); } } catch (Exception e) { e.printStackTrace(); }finally { IoUtil.close(httpClient); } return null; } } 3、OkHttp public class TestOkHttp { private static final String BASE_URL = "http://localhost:8083" ; public static void main(String[] args) { Headers headers = new Headers.Builder().add("Token","OkHttpSup").build() ; // 1、发送Get请求 Rep getRep = execute(BASE_URL+"/getApi/1", Method.GET.name(), headers, null, Rep.class); System.out.println("get:"+getRep); // 2、发送Post请求 IdKey postBody = new IdKey(1,"id-key") ; Rep postRep = execute(BASE_URL+"/postApi", Method.POST.name(), headers, buildBody(postBody), Rep.class); System.out.println("post:"+postRep); // 3、发送Put请求 IdKey putBody = new IdKey(2,"key-id") ; Rep putRep = execute(BASE_URL+"/putApi", Method.PUT.name(), headers, buildBody(putBody), Rep.class); System.out.println("put:"+putRep); // 4、发送Delete请求 Rep delRep = execute(BASE_URL+"/delApi/2", Method.DELETE.name(), headers, null, Rep.class); System.out.println("del:"+delRep); } /** * 构建JSON请求体 */ public static RequestBody buildBody (Object body){ MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); return RequestBody.create(mediaType, JSONUtil.toJsonStr(body)) ; } /** * 构建OkHttpClient对象 */ public static OkHttpClient buildOkHttp () { return new OkHttpClient.Builder() .readTimeout(10, TimeUnit.SECONDS).connectTimeout(6, TimeUnit.SECONDS) .connectionPool(new ConnectionPool(15, 5, TimeUnit.SECONDS)) .build(); } /** * 执行请求 */ public static <T> T execute (String url, String method, Headers headers, RequestBody body, Class<T> repClass) { // 请求创建 OkHttpClient httpClient = buildOkHttp() ; Request.Builder requestBuild = new Request.Builder() .url(url).method(method, body); if (headers != null) { requestBuild.headers(headers); } try { // 请求执行 Response response = httpClient.newCall(requestBuild.build()).execute(); // 结果转换 InputStream inStream = null; if (response.isSuccessful()) { ResponseBody responseBody = response.body(); if (responseBody != null) { inStream = responseBody.byteStream(); } } if (inStream != null) { try { byte[] respByte = IoUtil.readBytes(inStream); if (respByte != null) { return JSONUtil.toBean(new String(respByte, Charset.defaultCharset()), repClass); } } catch (Exception e) { e.printStackTrace(); } finally { IoUtil.close(inStream); } } } catch (Exception e) { e.printStackTrace(); } return null; } } 4、RestTemplate public class TestRestTemplate { private static final String BASE_URL = "http://localhost:8083" ; public static void main(String[] args) { RestTemplate restTemplate = buildRestTemplate() ; // 1、发送Get请求 Map<String,String> paramMap = new HashMap<>() ; Rep getRep = restTemplate.getForObject(BASE_URL+"/getApi/1",Rep.class,paramMap); System.out.println("get:"+getRep); // 2、发送Post请求 IdKey idKey = new IdKey(1,"id-key") ; Rep postRep = restTemplate.postForObject(BASE_URL+"/postApi",idKey,Rep.class); System.out.println("post:"+postRep); // 3、发送Put请求 IdKey idKey2 = new IdKey(2,"key-id") ; restTemplate.put(BASE_URL+"/putApi",idKey2,paramMap); // 4、发送Delete请求 restTemplate.delete(BASE_URL+"/delApi/2",paramMap); // 5、自定义Header请求 HttpHeaders headers = new HttpHeaders(); headers.add("Token","AdminSup"); HttpEntity<IdKey> requestEntity = new HttpEntity<>(idKey, headers); ResponseEntity<Rep> respEntity = restTemplate.exchange(BASE_URL+"/postApi", HttpMethod.POST, requestEntity, Rep.class); System.out.println("post-header:"+respEntity.getBody()); } private static RestTemplate buildRestTemplate (){ // 1、参数配置 SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setReadTimeout(3000); factory.setConnectTimeout(6000); // 2、创建对象 return new RestTemplate(factory) ; } } 五、参考源码 编程文档: https://gitee.com/cicadasmile/butte-java-note 应用仓库: https://gitee.com/cicadasmile/butte-flyer-parent

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册