Spring Http调用的实现
springboot常见http请求url参数获取方法
springboot常见http请求url参数获取⽅法在定义⼀个Rest接⼝时通常会利⽤GET、POST、PUT、DELETE来实现数据的增删改查;这⼏种⽅式有的需要传递参数,后台开发⼈员必须对接收到的参数进⾏参数验证来确保程序的健壮性GET:⼀般⽤于查询数据,采⽤明⽂进⾏传输,⼀般⽤来获取⼀些⽆关⽤户信息的数据POST:⼀般⽤于插⼊数据PUT:⼀般⽤于数据更新DELETE:⼀般⽤于数据删除;⼀般都是进⾏逻辑删除(即:仅仅改变记录的状态,⽽并⾮真正的删除数据)1、@PathVaribale 获取url中的数据请求URL:localhost:8080/hello/id 获取id值实现代码如下:@RestControllerpublicclass HelloController {@RequestMapping(value="/hello/{id}/{name}",method= RequestMethod.GET)public String sayHello(@PathVariable("id") Integer id,@PathVariable("name") String name){return"id:"+id+" name:"+name;}}在浏览器中输⼊地址:localhost:8080/hello/100/hello输出:id:81name:hello2、@RequestParam 获取请求参数的值获取url参数值,默认⽅式,需要⽅法参数名称和url参数保持⼀致请求URL:localhost:8080/hello?id=1000@RestControllerpublicclass HelloController {@RequestMapping(value="/hello",method= RequestMethod.GET)public String sayHello(@RequestParam Integer id){return"id:"+id;}}输出:id:100url中有多个参数时,如:localhost:8080/hello?id=98&&name=helloworld具体代码如下:@RestControllerpublicclass HelloController {@RequestMapping(value="/hello",method= RequestMethod.GET)public String sayHello(@RequestParam Integer id,@RequestParam String name){return"id:"+id+ " name:"+name;}}获取url参数值,执⾏参数名称⽅式localhost:8080/hello?userId=1000@RestControllerpublicclass HelloController {@RequestMapping(value="/hello",method= RequestMethod.GET)public String sayHello(@RequestParam("userId") Integer id){return"id:"+id;}}输出:id:100到此这篇关于spring boot 常见http请求url参数获取⽅法的⽂章就介绍到这了,更多相关spring boot url参数获取内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
openfeign实现原理
openfeign实现原理OpenFeign是一个基于Java的轻量级HTTP客户端,它是Spring Cloud中的一个组件,用于简化微服务架构中的HTTP调用。
在本文中,我们将介绍OpenFeign的实现原理。
一、概述在微服务架构中,服务之间的交互是通过HTTP接口进行的。
因此,服务之间的调用需要使用HTTP客户端。
在传统的RESTful服务中,通常使用RestT emplate来实现HTTP客户端。
但是,RestTemplate需要手动配置,代码复杂度较高。
为了简化HTTP 客户端的使用,Spring Cloud提供了OpenFeign。
OpenFeign是一个基于注解的HTTP客户端,它使用了Spring MVC的注解来定义HTTP接口,简化了HTTP客户端的使用。
二、实现原理OpenFeign的实现原理可以分为两个部分:接口定义和代理实现。
1. 接口定义在使用OpenFeign时,我们需要定义一个接口,用于描述HTTP 接口。
这个接口中使用了Spring MVC的注解来定义HTTP请求的URL、请求方法、请求参数、请求体等信息。
这个接口就是我们需要调用的HTTP接口。
例如,在下面的代码中,我们定义了一个名为"UserService"的接口,用于描述用户服务的HTTP接口。
```@FeignClient(name = "user-service")public interface UserService {@GetMapping("/users/{id}")User getUserById(@PathVariable("id") Long id);}```在这个代码中,@FeignClient注解用于定义服务的名称,name属性指定了服务的名称为"user-service"。
@GetMapping注解用于定义HTTP请求的URL,这个请求的URL为"/users/{id}",其中"{id}"是一个路径参数。
简述springmvc工作原理
简述springmvc工作原理Spring MVC 是一个基于 Java 的轻量级的 web 框架,用来开发灵活、可扩展的 web 应用程序。
Spring MVC 的工作原理如下:1. 客户发出 HTTP 请求到前端控制器 DispatcherServlet。
2. DispatcherServlet 是应用的前端控制器,根据请求 URL 找到对应的处理器 Handler。
3. HandlerMapping 根据请求 URL 找到对应的处理器适配器HandlerAdapter,HandlerAdapter 是一个策略接口,负责执行具体的 Handler 。
4. HandlerAdapter 将处理器 Handler 封装成一个适配器,使其具备执行 Handler 的能力。
5. Handler 调用业务逻辑进行处理,并返回一个ModelAndView 对象。
6. ModelAndView 是 Spring MVC 的模型和视图对象,它包含处理结果数据和视图名称。
7. Handler 将处理结果数据存入 ModelAndView 中,并将视图名称返回给 HandlerAdapter。
8. HandlerAdapter 将 ModelAndView 传递给前端控制器DispatcherServlet。
9. DispatcherServlet 调用视图解析器 ViewResolver 解析视图名称,得到具体的视图对象 View。
10. View 是一个接口,负责渲染 ModelAndView 对象,将处理结果生成 HTML 返回给客户端。
11. 客户端浏览器接收到 HTML 文档,并将其呈现给用户。
以上是 Spring MVC 的工作流程,它的核心原理是通过前端控制器 DispatcherServlet 来实现请求的分发和处理,以及视图的解析和渲染。
通过 HandlerMapping、HandlerAdapter、视图解析器 ViewResolver 的配合,可以实现灵活的请求处理和视图展示,同时也能够很好地与 Spring 的依赖注入和面向切面编程等特性进行整合。
Java调用HttpHttps接口(1)--编写服务端
Java调⽤HttpHttps接⼝(1)--编写服务端 Http接⼝输⼊的数据⼀般是键值对或json数据,返回的⼀般是json数据。
本系列⽂章主要介绍Java调⽤Http接⼝的各种⽅法,本⽂主要介绍服务端的编写,⽅便后续⽂章⾥的客户端的调⽤。
⽂中所使⽤到的软件版本:Java 1.8.0_191、SpringBoot 2.2.1.RELEASE。
1、服务端Controllerpackage com.inspur.demo.http.server;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.multipart.MultipartFile;import mon.entity.CallResult;import mon.util.FileUtil;import er;@Controller@RequestMapping(value="/httptest/", method = {RequestMethod.GET, RequestMethod.POST})public class HttpTestController {private static Logger logger = LoggerFactory.getLogger(HttpTestController.class);@RequestMapping(value = "getUser", produces = "application/json;charset=UTF-8")@ResponseBodypublic CallResult<User> getUser(String userId, String userName) {("userId={},userName={}", userId, userName);User user = new User();user.setUserId(userId);user.setUserName(userName);CallResult<User> result = new CallResult<User>(0, "OK", user);return result;}/*** 传⼊json* @param user* @return*/@RequestMapping("addUser")@ResponseBodypublic CallResult<User> addUser(@RequestBody User user) {(user.toString());CallResult<User> result = new CallResult<User>(0, "OK", user);return result;}/*** 上传⽂件* 这种⽅式不适合页⾯form表单上传⽂件,适合客户端调⽤* @param request* @return*/@RequestMapping(value = "upload", produces = "application/json;charset=UTF-8")@ResponseBodypublic CallResult<String> upload(HttpServletRequest request) {InputStream in = null;OutputStream out = null;CallResult<String> result = new CallResult<String>(0, "OK", "上传成功");try {in = new BufferedInputStream(request.getInputStream(), 16 * 1024);//假设上传的就是jpg⽂件String fileName = "d:/temp/upload_" + System.currentTimeMillis() + ".jpg";out = new BufferedOutputStream(new FileOutputStream(fileName), 16 * 1024);byte[] buffer = new byte[16 * 1024];int len = 0;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);}} catch (Exception e) {result = new CallResult<String>(-1, "发⽣异常", "");e.printStackTrace();} finally {FileUtil.close(in);FileUtil.close(out);}("upload返回结果:{}", result);return result;}/*** 上传⽂件及发送键值对数据* @param file* @param param1* @param param2* @return*/@RequestMapping("multi")@ResponseBodypublic CallResult<String> multi(@RequestParam("file") MultipartFile file, String param1, String param2) { ("file={},param1={},param2={}", file.getOriginalFilename(), param1, param2);InputStream in = null;OutputStream out = null;CallResult<String> result = new CallResult<String>(0, "OK", "上传成功");try {in = new BufferedInputStream(file.getInputStream(), 16 * 1024);String originalFilename = file.getOriginalFilename();//ie上传⽂件该值是全路径,处理下if (originalFilename.indexOf("\\") > -1) {originalFilename = originalFilename.substring(originalFilename.indexOf("\\") + 1);}String fileName = "d:/temp/multi_" + System.currentTimeMillis() + "_" + originalFilename;out = new BufferedOutputStream(new FileOutputStream(fileName), 16 * 1024);byte[] buffer = new byte[16 * 1024];int len = 0;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);}} catch (Exception e) {result = new CallResult<String>(-1, "发⽣异常", "");e.printStackTrace();} finally {FileUtil.close(in);FileUtil.close(out);}("multi返回结果:{}", result);return result;}/*** 下载⽂件* @param request* @param response*/@RequestMapping("download")public void download(HttpServletRequest request, HttpServletResponse response) {int BUFFER_SIZE = 16 * 1024;BufferedInputStream bis = null;OutputStream out = null;try {String fileName = "a.jpg";String urlFileName = "";if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {urlFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");} else {urlFileName = .URLEncoder.encode(fileName, "UTF-8");}response.reset();response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment; filename=\"" + urlFileName + "\"");response.setHeader("Connection", "close");bis = new BufferedInputStream(new FileInputStream("d:/" + fileName), BUFFER_SIZE);out = new BufferedOutputStream(response.getOutputStream(), BUFFER_SIZE);byte buf[] = new byte[BUFFER_SIZE];int len;while ((len = bis.read(buf)) != -1) {out.write(buf, 0, len);}} catch (Exception e) {e.printStackTrace();} finally {FileUtil.close(bis);FileUtil.close(out);}}}2、其他辅助类2.1、CallResult类package mon.entity;import java.io.Serializable;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;/*** @param <T>*/public class CallResult<T> implements Serializable {private static final long serialVersionUID = 1L;/*** 返回码* 0 正常,其他异常*/private int returnCode = 0;/*** 描述*/private String description = "OK";/*** 结果数据*/private T result;public CallResult(){}public CallResult(int returnCode, String description) {this.returnCode = returnCode;this.description = description;}public CallResult(int returnCode, String description, T result) {this.returnCode = returnCode;this.description = description;this.result = result;}public int getReturnCode() {return returnCode;}public void setReturnCode(int returnCode) {this.returnCode = returnCode;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public T getResult() {return result;}public void setResult(T result) {this.result = result;}@Overridepublic String toString() {//return JSON.toJSONString(this, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty);try {return new ObjectMapper().writeValueAsString(this);} catch (JsonProcessingException e) {e.printStackTrace();}return "";}}View Code2.2、User类package com.inspur.demo.http.entity;public class User {private String userId;private String userName;public String getUserId() {return userId;}public void setUserId(String userId) {erId = userId;}public String getUserName() {return userName;}public void setUserName(String userName) {erName = userName;}@Overridepublic String toString() {return "User [userId=" + userId + ", userName=" + userName + "]"; }}View Code2.2、FileUtil类package mon.util;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;/*** ⽂件操作⼯具*/public class FileUtil {private FileUtil() {}public static void close(InputStream in) {try {if (in != null) {in.close();}} catch (IOException e) {e.printStackTrace();}}public static void close(OutputStream out) {try {if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}}View Code3、接⼝地址在本地部署后,访问地址为:4、Https接⼝Https接⼝可以通过openssl⽣成证书、nginx设置⽅向代理来实现;由于这不是本系列⽂章的重点,这⾥就不详细介绍了,感兴趣的可以搜索研究。
JAVA代码实现HTTP请求的常用方法
JAVA代码实现HTTP请求的常用方法在Java中,有多种方法可以实现HTTP请求。
下面将介绍几种常用的方法。
1. 使用Java内置的URL类和HttpURLConnection类:```javaimport java.io.BufferedReader;import java.io.InputStreamReader;public class HTTPRequestExamplepublic static void main(String[] args) throws ExceptionURL obj = new URL(url);HttpURLConnection con = (HttpURLConnection)obj.openConnection(;//设置请求方法con.setRequestMethod("GET");//添加请求头con.setRequestProperty("User-Agent", "Mozilla/5.0");//获取响应码int responseCode = con.getResponseCode(;System.out.println("Response Code: " + responseCode);BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream());String inputLine;StringBuffer response = new StringBuffer(;while ((inputLine = in.readLine() != null)response.append(inputLine);}in.close(;//打印响应内容System.out.println(response.toString();}```2. 使用第三方库HttpClient:```javapublic class HTTPRequestExamplepublic static void main(String[] args) throws Exception //创建GET请求//发送请求并获取响应//解析响应实体内容//打印响应内容System.out.println(response);// 关闭HttpClient连接}```3. 使用第三方库OkHttp:```javapublic class HTTPRequestExamplepublic static void main(String[] args) throws Exception// 创建OkHttpClient对象OkHttpClient okHttpClient = new OkHttpClient(;// 创建Request对象Request request = new Request.Builder.url(url).build(;//发送请求并获取响应Response response = okHttpClient.newCall(request).execute(;String responseBody = response.body(.string(;//打印响应内容System.out.println(responseBody);}```4. 使用第三方库RestTemplate(Spring框架的一部分):```javaimport org.springframework.web.client.RestTemplate;public class HTTPRequestExamplepublic static void main(String[] args)// 创建RestTemplate对象RestTemplate restTemplate = new RestTemplate(;//发送GET请求,并获取响应ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);//获取响应内容String response = responseEntity.getBody(;//打印响应内容System.out.println(response);}```这些方法提供了不同的方式来实现HTTP请求,使用Java内置的URL 类和HttpURLConnection类相对简单,但是需要自己处理底层连接和数据读取。
SpringBoot实现本地存储文件上传及提供HTTP访问服务的方法
SpringBoot实现本地存储文件上传及提供HTTP访问服务的方法在Spring Boot中,实现本地存储文件上传及提供HTTP访问服务的方法主要包括以下步骤:1. 依赖配置:在`pom.xml`文件中添加所需依赖。
```xml<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency></dependency></dependencies>```2. 文件上传配置:在`application.properties`文件中配置文件上传相关属性。
```propertiesspring.servlet.multipart.max-file-size=10MB # 最大文件大小spring.servlet.multipart.max-request-size=10MB # 最大请求大小```3.文件上传控制器:创建一个控制器类来处理文件上传请求,并将文件保存到本地目录中。
```javapublic class FileUploadControllerprivate static final String UPLOAD_DIR = "uploads";try//获取文件名String fileName = file.getOriginalFilename(;//保存文件到本地目录file.transferTo(new File(UPLOAD_DIR + File.separator + fileName));//返回成功消息return ResponseEntity.ok(.body("File uploaded successfully");} catch (Exception e)//返回错误消息returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Fa iled to upload file");}}```4.文件访问控制器:创建一个控制器类来提供通过HTTP访问上传的文件的功能。
feignclient调用原理
feignclient调用原理FeignClient调用原理FeignClient是Spring Cloud中一个常用的服务调用工具,它是基于Netflix开发的声明式HTTP客户端,主要用于简化微服务之间的通信。
本文将介绍FeignClient的调用原理及其工作流程。
一、FeignClient概述FeignClient是基于动态代理技术实现的,它可以根据接口定义自动地生成实现类,并且通过注解的方式来完成服务的调用。
在使用FeignClient时,只需要定义一个接口,并通过@FeignClient注解指定对应的服务名,FeignClient会根据接口及注解的配置自动创建实现类,并完成服务的调用。
二、FeignClient工作原理1. 创建代理对象在应用启动时,FeignClient会通过动态代理技术生成代理对象。
代理对象中包含了服务的请求信息,以及对请求进行处理的相关方法。
2. 解析注解FeignClient会解析接口上的注解,包括@FeignClient、@RequestMapping等。
@FeignClient注解用于指定服务的名称,而@RequestMapping注解用于指定服务的请求路径。
3. 发起请求当应用调用FeignClient接口的方法时,代理对象会根据方法的注解信息自动生成HTTP请求。
FeignClient会根据请求路径、请求方式等信息,使用底层的HTTP客户端发送请求到指定的服务。
4. 负载均衡在发送请求时,FeignClient还会结合Ribbon进行负载均衡。
Ribbon是一个负载均衡器,它可以根据一定的策略选择一个可用的服务实例。
5. 服务调用当请求到达目标服务后,FeignClient会将请求转发给服务的对应方法进行处理。
服务对请求进行处理后,将结果返回给FeignClient。
6. 结果处理FeignClient接收到服务的响应后,会对响应进行处理,包括状态码的判断、异常的处理等。
SpringBoot配置okhttp3的操作
SpringBoot配置okhttp3的操作1. Maven 添加依赖<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.10.0</version></dependency>2. application.properties 配置⽂件ok.http.connect-timeout=30ok.http.read-timeout=30ok.http.write-timeout=30# 连接池中整体的空闲连接的最⼤数量ok.http.max-idle-connections=200# 连接空闲时间最多为 300 秒ok.http.keep-alive-duration=3003. OkHttpConfiguration 配置类import okhttp3.ConnectionPool;import okhttp3.OkHttpClient;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import .ssl.*;import java.security.*;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.concurrent.TimeUnit;/*** @author Answer.AI.L* @date 2019-04-09*/@Configurationpublic class OkHttpConfiguration {@Value("${ok.http.connect-timeout}")private Integer connectTimeout;@Value("${ok.http.read-timeout}")private Integer readTimeout;@Value("${ok.http.write-timeout}")private Integer writeTimeout;@Value("${ok.http.max-idle-connections}")private Integer maxIdleConnections;@Value("${ok.http.keep-alive-duration}")private Long keepAliveDuration;@Beanpublic OkHttpClient okHttpClient() {return new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory(), x509TrustManager())// 是否开启缓存.retryOnConnectionFailure(false).connectionPool(pool()).connectTimeout(connectTimeout, TimeUnit.SECONDS).readTimeout(readTimeout, TimeUnit.SECONDS).writeTimeout(writeTimeout,TimeUnit.SECONDS).hostnameVerifier((hostname, session) -> true)// 设置代理// .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)))// 拦截器// .addInterceptor().build();}@Beanpublic X509TrustManager x509TrustManager() {return new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}};}@Beanpublic SSLSocketFactory sslSocketFactory() {try {// 信任任何链接SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());return sslContext.getSocketFactory();} catch (NoSuchAlgorithmException | KeyManagementException e) {e.printStackTrace();}return null;}@Beanpublic ConnectionPool pool() {return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);}}4. OkHttp 类import lombok.extern.slf4j.Slf4j;import okhttp3.*;import ng3.exception.ExceptionUtils;import org.springframework.beans.factory.annotation.Autowired;import ponent;import java.util.Map;/*** @author Answer.AI.L* @date 2019-04-09*/@Slf4j@Componentpublic class OkHttpCli {private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8"); @Autowiredprivate OkHttpClient okHttpClient;/*** get 请求* @param url 请求url地址* @return string* */public String doGet(String url) {return doGet(url, null, null);}/*** get 请求* @param url 请求url地址* @param params 请求参数 map* @return string* */public String doGet(String url, Map<String, String> params) {return doGet(url, params, null);}/*** get 请求* @param url 请求url地址* @param headers 请求头字段 {k1, v1 k2, v2, ...}* @return string* */public String doGet(String url, String[] headers) {return doGet(url, null, headers);}/*** get 请求* @param url 请求url地址* @param params 请求参数 map* @param headers 请求头字段 {k1, v1 k2, v2, ...}* @return string* */public String doGet(String url, Map<String, String> params, String[] headers) {StringBuilder sb = new StringBuilder(url);if (params != null && params.keySet().size() > 0) {boolean firstFlag = true;for (String key : params.keySet()) {if (firstFlag) {sb.append("?").append(key).append("=").append(params.get(key));firstFlag = false;} else {sb.append("&").append(key).append("=").append(params.get(key));}}}Request.Builder builder = new Request.Builder();if (headers != null && headers.length > 0) {if (headers.length % 2 == 0) {for (int i = 0; i < headers.length; i = i + 2) {builder.addHeader(headers[i], headers[i + 1]);}} else {log.warn("headers's length[{}] is error.", headers.length);}}Request request = builder.url(sb.toString()).build();("do get request and url[{}]", sb.toString());return execute(request);}/*** post 请求* @param url 请求url地址* @param params 请求参数 map* @return string*/public String doPost(String url, Map<String, String> params) {FormBody.Builder builder = new FormBody.Builder();if (params != null && params.keySet().size() > 0) {for (String key : params.keySet()) {builder.add(key, params.get(key));}}Request request = new Request.Builder().url(url).post(builder.build()).build();("do post request and url[{}]", url);return execute(request);}/*** post 请求, 请求数据为 json 的字符串* @param url 请求url地址* @param json 请求数据, json 字符串* @return string*/public String doPostJson(String url, String json) {("do post request and url[{}]", url);return exectePost(url, json, JSON);}/*** post 请求, 请求数据为 xml 的字符串* @param url 请求url地址* @param xml 请求数据, xml 字符串* @return string*/public String doPostXml(String url, String xml) {("do post request and url[{}]", url);return exectePost(url, xml, XML);}private String exectePost(String url, String data, MediaType contentType) {RequestBody requestBody = RequestBody.create(contentType, data);Request request = new Request.Builder().url(url).post(requestBody).build();return execute(request);}private String execute(Request request) {Response response = null;try {response = okHttpClient.newCall(request).execute();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error(ExceptionUtils.getStackTrace(e));} finally {if (response != null) {response.close();}}return "";}}5. 使⽤验证@RestControllerpublic class AnswerController {@Autowiredprivate OkHttpCli okHttpCli;@RequestMapping(value = "show", method = RequestMethod.GET)public String show() {String url = "https:///";String message = okHttpCli.doGet(url);return message;}}6. 双向认证(待证)@Beanpublic SSLSocketFactory sslSocketFactory() {String certPath = "";String caPath = "";String certPwd = "";String caPwd = "";try {ClassPathResource selfcertPath = new ClassPathResource(certPath);ClassPathResource trustcaPath = new ClassPathResource(caPath);KeyStore selfCert = KeyStore.getInstance("pkcs12");selfCert.load(selfcertPath.getInputStream(), certPwd.toCharArray());KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");kmf.init(selfCert, certPwd.toCharArray());KeyStore caCert = KeyStore.getInstance("jks");caCert.load(trustcaPath.getInputStream(), caPwd.toCharArray());TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");tmf.init(caCert);SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);return sslContext.getSocketFactory();} catch (Exception e) {e.printStackTrace();}return null;}补充:Spring Cloud Feign 总结问题,注意点,性能调优,切换okhttp3 Feign常见问题总结FeignClient接⼝如使⽤@PathVariable ,必须指定value属性//在⼀些早期版本中, @PathVariable("id") 中的 "id" ,也就是value属性,必须指定,不能省略。
fegin 的实现类编写
fegin 的实现类编写在Spring Cloud中,Feign是一种声明式的HTTP客户端,它使得编写Web服务客户端变得更加简单。
要编写Feign的实现类,首先需要在项目的pom.xml文件中引入相应的依赖。
然后,创建一个接口并使用Feign的注解来定义需要调用的远程服务的方法。
接着,编写Feign的实现类来实现这些接口方法。
下面我将从这些方面来详细说明。
首先,在pom.xml文件中引入Feign的依赖,通常是在spring-cloud-starter-openfeign这个依赖中引入Feign。
在Maven项目中,你可以这样做:xml.<dependency>。
<groupId>org.springframework.cloud</groupId>。
<artifactId>spring-cloud-starter-openfeign</artifactId>。
</dependency>。
接下来,创建一个接口,使用@FeignClient注解来指定需要调用的远程服务的名称以及fallback等属性。
例如:java.@FeignClient(name = "remote-service", fallback = RemoteServiceFallback.class)。
public interface RemoteService {。
@RequestMapping(value = "/api/someMethod", method = RequestMethod.GET)。
String someMethod();}。
然后,编写Feign的实现类来实现这个接口。
在实现类中,你可以通过调用远程服务的方法来实现具体的业务逻辑。
例如:java.@Component.public class RemoteServiceImpl implements RemoteService {。
resttemplate原理
resttemplate原理
RestTemplate是Spring框架提供的一个用于进行HTTP请求的工具类。
它通过HTTP协议,在不同的系统间进行数据传输和信息交互。
RestTemplate提供了一系列请求方法,包括GET、POST、PUT、DELETE 等,可以快速方便地进行HTTP通信。
RestTemplate的工作原理是通过底层的HTTP客户端实现发送HTTP请求,并通过HTTP协议与目标服务器进行通信。
RestTemplate 封装了HTTP请求的构建和发送过程,提供了一系列方法进行不同类型的请求,并提供了一些自定义配置实现更灵活、可定制的请求。
在使用RestTemplate发送HTTP请求时,需要指定请求的方法、URL、请求头、请求参数等信息,然后向目标服务器发送请求。
服务器处理请求后,将响应结果返回给客户端,RestTemplate接收响应结果并封装成相应的Java对象返回给请求的调用方。
总的来说,RestTemplate的原理就是封装了底层的HTTP客户端实现,提供了一套简单易用的API接口,帮助Java程序方便地进行HTTP通信。
feign的实现方法
feign的实现方法Feign是一个声明式的HTTP客户端,它使得编写Web服务客户端变得更加简单。
Feign的实现方法涉及到以下几个方面:1. 接口定义,Feign要求我们定义一个接口来描述我们要访问的远程服务的方法和参数。
这个接口可以使用类似于Spring MVC的注解来描述HTTP请求的细节,比如URL、HTTP方法、请求头等。
2. 注解支持,Feign提供了一系列的注解来帮助我们定义接口,比如`@RequestMapping`、`@RequestParam`、`@RequestHeader`等。
这些注解可以让我们在接口中定义HTTP请求的各种细节。
3. 代理实现,Feign使用动态代理技术来生成实际的HTTP请求代码。
在运行时,Feign会根据我们定义的接口,动态生成一个实现了该接口的代理类。
这个代理类中包含了具体的HTTP请求逻辑,包括参数的序列化、请求的发送、响应的解析等。
4. 整合Spring,在Spring应用中,我们可以使用`@EnableFeignClients`注解来启用Feign客户端,并通过`@FeignClient`注解来指定要访问的远程服务的接口。
Spring会在启动时扫描这些注解,并自动为我们生成Feign客户端的实例。
5. 可插拔的编解码器,Feign支持可插拔的编解码器,可以方便地扩展支持其他的序列化协议,比如Protocol Buffers、Thrift 等。
我们可以通过配置来指定使用哪种编解码器。
总的来说,Feign的实现方法涉及到接口定义、注解支持、动态代理、Spring整合以及可插拔的编解码器等方面。
通过这些特性,Feign使得编写Web服务客户端变得更加简单和优雅。
resttemplate execute的使用
一、概述在Java开发中,RestTemplate是一个非常常用的类,它是Spring框架中的一部分,用于实现对RESTful API的调用。
它提供了许多便捷的方法来执行HTTP请求,比如GET、POST、PUT、DELETE等。
其中,execute方法是RestTemplate中最为灵活和强大的方法之一,它可以用来执行任何类型的HTTP请求,并且可以自定义请求头、请求体、URI参数等,非常适合复杂的场景。
二、execute方法的基本用法1. 使用execute方法发送GET请求下面是一个使用execute方法发送GET请求的示例:```javaRestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.exchange("", HttpMethod.GET, null, String.class);String body = response.getBody();```在这个示例中,我们首先创建了一个RestTemplate实例,然后调用exchange方法来发送GET请求,其中第一个参数是请求的URL,第二个参数是请求方法类型,第三个参数是请求体,这里我们使用null 表示没有请求体,第四个参数则是响应的类型,这里我们使用String.class表示希望将响应体转换为字符串。
2. 使用execute方法发送POST请求除了发送GET请求之外,execute方法也可以用来发送POST请求,示例如下:```javaRestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON); String requestBody = "{\"username\": \"john\", \"password\": \"123456\"}";HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);ResponseEntity<String> response = restTemplate.exchange("", HttpMethod.POST, entity, String.class);String body = response.getBody();```在这个示例中,我们首先创建了一个包含请求体的HttpEntity对象,然后调用exchange方法发送POST请求。
resttemplateutil 怎么调用get方法 -回复
resttemplateutil 怎么调用get方法-回复使用RestTemplate调用GET方法RestTemplate是Spring框架中的一个HTTP客户端,用于将HTTP请求发送到远程服务器,并接收和解析服务器的响应。
它提供了多种方法来发送不同类型的HTTP请求,包括GET、POST、PUT和DELETE等。
在本文中,我们将重点介绍如何使用RestTemplate调用GET方法。
我们将一步一步地回答问题,以帮助读者了解如何使用RestTemplate进行GET请求。
在开始之前,我们需要确保项目已经引入了Spring框架及其相关依赖。
可以使用Maven或Gradle来管理项目的依赖关系。
步骤1:创建RestTemplate实例使用RestTemplate发送HTTP请求之前,首先需要创建一个RestTemplate对象。
可以通过new关键字来实例化RestTemplate类,也可以通过依赖注入的方式获取RestTemplate对象。
以下是通过new关键字创建RestTemplate对象的示例代码:RestTemplate restTemplate = new RestTemplate();步骤2:发送GET请求发送GET请求时,需要指定请求的URL以及响应的类型。
RestTemplate 提供了多种方法来发送GET请求,可以根据需要选择合适的方法。
例如,我们可以使用以下代码发送一个简单的GET请求:String url = "String response = restTemplate.getForObject(url, String.class);在上面的示例中,我们将要请求的URL指定为字符串"步骤3:处理响应收到响应后,我们需要对响应进行处理。
可以根据需要将响应转换为不同的类型,例如String、JSON对象或自定义的Java对象。
RestTemplate提供了多种处理响应的方法,包括getForObject()、getForEntity()和exchange()等。
resttemplate高级用法
resttemplate高级用法
RestTemplate是Spring framework提供的一个用于访问REST 服务的模板类,它包含了多种HTTP请求方法的实现,可以方便地进行RESTful服务的调用。
以下是一些RestTemplate的高级用法:
1.自定义请求头:可以使用HttpHeaders对象设置自定义的请
求头信息,然后将其传递给RestTemplate的方法中,以实
现带有自定义请求头的HTTP请求。
2.携带认证信息:可以使用HttpEntity对象来携带认证信息,
例如Basic Auth、Bearer Token等,将HttpEntity对象传递
给RestTemplate的方法中,以实现带有认证信息的HTTP
请求。
3.错误处理:使用ResponseErrorHandler接口自定义错误处理
逻辑,当REST请求返回错误状态码时,可以进行自定义
的错误处理操作。
4.拦截器:通过实现ClientHttpRequestInterceptor接口,可以
创建自定义的请求/响应拦截器,对请求和响应进行修改或
者记录日志等操作。
5.异步请求:RestTemplate也支持异步请求,可以使用
ListenableFuture或CompletableFuture等实现异步调用
REST服务。
6.使用Exchange方法:exchange方法可以发送任意类型的
HTTP请求,并接收ResponseEntity作为响应,这种方式比较灵活,可以满足各种场景下的需求。
以上是RestTemplate的一些高级用法,通过灵活运用这些功能,可以更好地满足复杂的REST服务调用需求。
SpringBoot实现任意位置获取HttpServletRequest对象
SpringBoot实现任意位置获取HttpServletRequest对象⽬录任意位置获取HttpServletRequest对象⽅法⼀⽅法⼆HttpServletRequest只能读取⼀次的解决任意位置获取HttpServletRequest对象⽅法⼀//获取RequestAttributesRequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//从获取RequestAttributes中获取HttpServletRequest的信息HttpServletRequest request = (HttpServletRequest)requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);⽅法⼆ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();HttpServletRequest只能读取⼀次的解决业务逻辑,通过filter读取请求的request,获取token,并将token传递后⾯流程使⽤BodyReaderHttpServletRequestWrapper:public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() throws IOException {return byteArrayInputStream.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};}}RepeatReadFilter:/*** 封装HttpServletRequest为可重复读取请求**/public class RepeatReadFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) request;// 防⽌流读取⼀次后就没有了, 所以需要将流继续写出去ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);//获取⽤户凭证String token = httpServletRequest.getHeader(ER_TOKEN);if(StringUtils.isBlank(token)){token = httpServletRequest.getParameter(ER_TOKEN);}//=================获取json格式的token字段=========================String body = HttpHelper.getBodyString(requestWrapper);if (StringUtils.isNotBlank(body)) {JSONObject jsonObject = JSONObject.parseObject(body);Object obj = jsonObject.get("token");if (null != obj) {token = obj.toString();}}requestWrapper.setAttribute(ER_TOKEN,token);chain.doFilter(requestWrapper, response);}@Overridepublic void destroy() {}}FilterConfig:@Configurationpublic class FilterConfig {@Beanpublic FilterRegistrationBean registFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new RepeatReadFilter());registration.addUrlPatterns("/app/*");registration.setName("UrlFilter");registration.setOrder(1);return registration;}}AuthorizationInterceptor:@Componentpublic class AuthorizationInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { AuthIgnore annotation;if(handler instanceof HandlerMethod) {annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);}else{return true;}//如果有@AuthIgnore注解,则不验证tokenif(annotation != null){return true;}//获取⽤户凭证String token = request.getHeader(ER_TOKEN);if(StringUtils.isBlank(token)){token = request.getParameter(ER_TOKEN);}if(StringUtils.isBlank(token)){Object obj = request.getAttribute(ER_TOKEN);if(null!=obj){token=obj.toString();}}//token凭证为空if(StringUtils.isBlank(token)){throw new AuthException(ER_TOKEN + "不能为空", HttpStatus.UNAUTHORIZED.value());}return true;}WebMvcConfig:@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter {@Autowiredprivate AuthorizationInterceptor authorizationInterceptor;// @Autowired// private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**");super.addInterceptors(registry);}@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {//argumentResolvers.add(loginUserHandlerMethodArgumentResolver);}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {super.configureMessageConverters(converters);}@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {}}在filter中读取token,在interceptor中进⾏读取判断使⽤HttpHelper:public class HttpHelper {/*** 获取请求Body** @param request* @return*/public static String getBodyString(ServletRequest request) {StringBuilder sb = new StringBuilder();InputStream inputStream = null;BufferedReader reader = null;try {inputStream = request.getInputStream();reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return sb.toString();}}以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
如何使用springResponseEntity处理http响应
如何使⽤springResponseEntity处理http响应简介使⽤spring时,达到同⼀⽬的通常有很多⽅法,对处理http响应也是⼀样。
本⽂我们学习如何通过ResponseEntity设置http相应内容、状态以及头信息。
ResponseEntityResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。
因此我们可以使⽤其对http响应实现完整配置。
如果需要使⽤ResponseEntity,必须在请求点返回,通常在spring rest中实现。
ResponseEntity是通⽤类型,因此可以使⽤任意类型作为响应体:@GetMapping("/hello")ResponseEntity<String> hello() {return new ResponseEntity<>("Hello World!", HttpStatus.OK);}可以通过编程⽅式指明响应状态,所以根据不同场景返回不同状态:@GetMapping("/age")ResponseEntity<String> age(@RequestParam("yearOfBirth") int yearOfBirth) {if (isInFuture(yearOfBirth)) {return new ResponseEntity<>("Year of birth cannot be in the future",HttpStatus.BAD_REQUEST);}return new ResponseEntity<>("Your age is " + calculateAge(yearOfBirth),HttpStatus.OK);}另外,还可以设置http响应头:@GetMapping("/customHeader")ResponseEntity<String> customHeader() {HttpHeaders headers = new HttpHeaders();headers.add("Custom-Header", "foo");return new ResponseEntity<>("Custom header set", headers, HttpStatus.OK);}⽽且, ResponseEntity提供了两个内嵌的构建器接⼝: HeadersBuilder 和其⼦接⼝ BodyBuilder。
Spring中MultipartHttpServletRequest实现文件上传
Spring中MultipartHttpServletRequest实现⽂件上传xml 代码1. <bean id="multipartResolver"2. class="monsMultipartResolver">3. <!-- 设置上传⽂件的最⼤尺⼨为1MB -->4. <property name="maxUploadSize">5. <value>1048576</value>6. </property>7. </bean>这样⼀旦某个Request是⼀个MultipartRequest,它就会⾸先被MultipartResolver处理,然后再转发相应的Controller。
在UploadImageController中,将HttpServletRequest转型为MultipartHttpServletRequest,就能⾮常⽅便地得到⽂件名和⽂件内容:java 代码1. public ModelAndView handleRequest(HttpServletRequest request,2. HttpServletResponse response) throws Exception {3. // 转型为MultipartHttpRequest:4. MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;5. // 获得⽂件:6. MultipartFile file = multipartRequest.getFile(" file ");7. // 获得⽂件名:8. String filename = file.getOriginalFilename();9. // 获得输⼊流:10. InputStream input = file.getInputStream();11. // 写⼊⽂件12.13. // 或者:14. File source = new File(localfileName.toString());15. multipartFile.transferTo(source);16. }⽣成缩略图 (⽬录) 当⽤户上传了图⽚后,必须⽣成缩略图以便⽤户能快速浏览。
SpringBoothttppost请求数据大小设置操作
SpringBoothttppost请求数据⼤⼩设置操作背景:使⽤http post请求⽅式的接⼝,使⽤request.getParameter("XXX");的⽅法获取参数的值,当数据量超过⼏百k的时候,接⼝接收不到数据或者接收为null。
@RequestMapping(value = "/rcv",method = RequestMethod.POST)public ResInfo<String> pullApi(HttpServletRequest request) {String channel = request.getParameter("channel");}在application.properties⾥添加:spring.http.multipart.max-file-size=-1spring.http.multipart.max-request-size=-1默认值:private String maxFileSize = "1MB"; private String maxRequestSize = "10MB";这个设置是⼤⼩不限制,主要是这个设置。
server.tomcat.max-http-post-size=-1补充知识:spring boot post请求数据太⼤接收不到参数(参数为空)报400错误。
spirng boot发送的请求,有的参数数据量⼤,有的参数数据量⼩。
数据量⼤的发送不到后端,报400错误。
⾸先说以jetty为内嵌服务器的时候:1、修改yml⽂件或者properties⽂件,server.max-http-post-size=200*1024*1024,设置为200m,总够了吧,可以按照量设置⼩⼀点。
Spring Boot 1.4.0.M2之后就可以使⽤这个属性。
resttemplate redirect
resttemplate redirectRestTemplate是Spring框架中用于实现RESTful服务调用的模板类,它有一个非常常用的功能就是自动重定向。
当RestTemplate发送请求遇到重定向时,它便会自动地去跟随重定向,并将最终响应结果返回给调用方。
在本文中,将介绍一些RestTemplate重定向的相关细节。
1. RestTemplate定义RestTemplate是Spring框架中的一个HTTP客户端。
它简化了与RESTful服务的交互,同时还支持许多HTTP操作,例如GET,POST,PUT和DELETE。
它使用HTTPMessageConverter来转换请求和响应数据。
2. RestTemplate自动跟随重定向实现RestTemplate使用默认的HttpURLConnection或Apache HttpClient来发送HTTP请求。
当RestTemplate遇到重定向时,它将自动跟随重定向。
默认情况下,RestTemplate会自动处理所有类型的HTTP 3xx状态码,但重定向的URL必须在同一个域名下。
如果要禁用自动重定向,需要通过设置RestTemplate的相应属性来实现。
例如,设置setRequestFactory属性并使用SimpleClientHttpRequestFactory对象禁用自动重定向:```RestTemplate restTemplate = new RestTemplate(); SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setOutputStreaming(false);factory.setConnectTimeout(60000);factory.setReadTimeout(60000);restTemplate.setRequestFactory(factory);```3. RestTemplate重定向报错处理在RestTemplate遇到重定向时,如果目标URL的域名与源URL的域名不同,会抛出异常:```ng.IllegalStateException: Redirect URI cannot be absolute if client is not configured to redirect```在这种情况下,可以通过设置setUriTemplateHandler来处理URI的转换,将URI的相对路径用绝对路径重新构建URI:```RestTemplate restTemplate = new RestTemplate();restTemplate.setUriTemplateHandler(newDefaultUriBuilderFactory());```4. 示例代码下面是一个使用RestTemplate发送请求并自动处理重定向的示例代码:```RestTemplate restTemplate = new RestTemplate();HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity requestEntity = new HttpEntity(headers); ResponseEntity<String> responseEntity =restTemplate.exchange(url, HttpMethod.GET,requestEntity, String.class);String responseBody = responseEntity.getBody();```在这个示例中,当RestTemplate发送请求时,它会自动处理重定向,并将最终的响应结果返回给调用方。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring Http调用的实现1:Spring Http设计思想最近在研究公司自己的一套rpc远程调用框架,看到其内部实现的设计思想依赖于spring的远端调用的思想,所以闲来无事,就想学习下,并记录下。
作为spring远端调用的实现,最为简单的应该是通过http调用的实现,在这种依赖中不会依赖第三方等相关组件,调用者只需要配置相关http的协议就可以实现,简单的配置,就可以使用spring的IOC 容器的bean的定义等等思想去调用,简单,方便,无需写更多的http相关的代码,比较适合内部通信系统之间的调用。
在日常开发中,经常会遇到各种内部系统之间的通讯调用,其实可以使用如下几种设计方式。
不过,最简单的应该是spring自带的http模式,然后自己封装打包成客户端jar等等,共客户端调用image其实在日常调用实现中,可以通过若干种设计都可以完成客户端与服务端之间的调用,如阿里的db中间件就是使用的是类似的通讯模式,不过没有研究过image公司内部使用的是如下的方式进行通讯,可以通过监控软件来进行对Q的跟踪,在处理大数据高并发的时候,良好的Q中间件及Java中封装异步处理,解决了数据库以及各方面的瓶颈压力,不过,也有缺点,各个应用之间的事务是无法控制,只能通过事后补偿处理。
综合来看,还是很好的设计image先来说说springHttp协议吧.2:客户端在客户端中设计了HttpInvokerProxyFactoryBean ,这是一个代理工厂bean(ProxyFactoryBean),它会使用spring aop来对http调用器的客户端进行封装,既然使用了aop,就会使用到代理对象,并为代理方法设置相应的拦截器。
HttpInvokerProxyFactoryBean 中,通过afterPropertiesSet来启动远端调用基础设施的建立等,代理拦截器HttpInvokerClientInterceptor,HttpInvokerClientInterceptor中会封装客户端的基本实现,如http请求链接,请求对象序列化,请求传送到服务端,在收到拦截器的时候,同样也会将服务器端发送过来http响应反序列化,并且把远端调用的服务器端返回的对象交给应用使用,完成一个http请求的基本实现。
Http调用器是基于http协议提供的远端调用方案,使用http调用器和使用Java rmi一样的基础配置模块HttpInvokerProxyFactoryBean 具体实现如下图继承了FactoryBean,使用HttpInvokerProxyFactoryBean 需要设置相应的bean对代理工厂的配置设置远程服务的url地址,设置远端服务的的接口,然后把这个代理工厂设置到客户端应用的bean的remoteService属性中,有了这个设置,客户端应用配置就已经配置好了,就可以像调用本地一样,享用远端服务了复制代码<bean id="proxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"><property name="serviceUrl">http://localhost:8080/xxxx/xxx</property><!--请求的服务端url--><property name="serviceInterface">.ddd.ee</property><!--具体的服务端调用接口路径--></bean><bean id="test" class="abc.sss.ssss"><property name="remoteService" ref="proxy"/> <!--引入到代理工厂中--></bean>复制代码HttpInvokerProxyFactoryBean中封装对应的远端服务信息,域名,端口,服务所在URL,这些都是远端服务调用所需要的信息,同时,由于使用httpInvoker,所以在URL指定的协议中是http协议,对访问远端服务调用的客户端而言,只要持有HttpInvokerProxyFactoryBean提供的代理对象,就可以方便的使用远端调用,使用起来如本地一样,远端调用发送的数据通信及远端服务交互,都被proxy代理类进行了封装,对客户端是透明的,这些封装主要都是在HttpInvokerProxyFactoryBean进行封装处理的。
image从图可以知道,当服务启动,系统在spring容器里面自动初始化该代理对象,自动执行afterPropertiesSet相关方法HttpInvokerProxyFactoryBean 是如何封装并将数据传输到服务端的?复制代码public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean<Object> {private Object serviceProxy;//代码省去若干代码省去若干代码省去若干代码省去若干@Overridepublic void afterPropertiesSet() {//初始化执行http配置加载等,为后续发送到服务端做准备工作super.afterPropertiesSet();//获取在客户端配置的接口,判断接口是否配置,此处的父类进行了类的加载配置等,//在此处,不是一个配置,而是一个具体的接口类if (getServiceInterface() == null) {throw new IllegalArgumentException("Property 'serviceInterface' is required");}//将相关参数,相应的类加载的信息,以及指定具体的客户端实现类代理this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader());}public Object getObject() {return this.serviceProxy;}public Class<?> getObjectType() {return getServiceInterface();}public boolean isSingleton() {return true;}}复制代码ProxyFactory所指定的HttpInvokerClientInterceptor 拦截器中执行的invoke方法复制代码//具体调用执行的方法public Object invoke(MethodInvocation methodInvocation) throws Throwable {if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {return "HTTP invoker proxy for service URL [" + getServiceUrl() + "]";}//创建远端服务所需要的参数信息等,格式是spring自己实现的,创建工厂等RemoteInvocation invocation = createRemoteInvocation(methodInvocation);RemoteInvocationResult result;try {//调用服务端,发送请求result = executeRequest(invocation, methodInvocation);}catch (Throwable ex) {throw convertHttpInvokerAccessException(ex);}try {//将服务端的返回信息所需要的对象等return recreateRemoteInvocationResult(result);}catch (Throwable ex) {if (result.hasInvocationTargetException()) {throw ex;}else {throw new RemoteInvocationFailureException("Invocation of method [" + methodInvocation.getMethod() + "] failed in HTTP invoker remote service at [" + getServiceUrl() + "]", ex);}}}复制代码上述代码中主要操作:封装发送的接口等RemoteInvocationFactory >> createRemoteInvocation(MethodInvocation methodInvocation);RemoteInvocation >>(RemoteInvocation(String methodName, Class[] parameterTypes, Object[] arguments))DefaultRemoteInvocationFactory >> createRemoteInvocation(MethodInvocation methodInvocation)复制代码/*** Create a new RemoteInvocation for the given AOP method invocation.* @param methodInvocation the AOP invocation to convert*/RemoteInvocation >>(RemoteInvocation(String methodName, Class[] parameterTypes, Object[] arguments))具体实现public RemoteInvocation(MethodInvocation methodInvocation) {this.methodName = methodInvocation.getMethod().getName();this.parameterTypes = methodInvocation.getMethod().getParameterTypes();this.arguments = methodInvocation.getArguments();}执行发送HttpInvokerRequestExecutor -->> AbstractHttpInvokerRequestExecutor类具体实现public final RemoteInvocationResult executeRequest(HttpInvokerClientConfiguration config, RemoteInvocation invocation) throws Exception {ByteArrayOutputStream baos = getByteArrayOutputStream(invocation);if (gEnabled()) {logger.debug("Sending HTTP invoker request for service at [" + config.getServiceUrl() +"], with size " + baos.size());}return doExecuteRequest(config, baos);}复制代码具体流程图如下:客户端请求配置发送请求image3:服务端在服务端中设计了HttpInvokerServiceExporter,通过ServiceExporter来导出远端的服务对象,由于需要处理http请求,所以其需要依赖springMVC模块来实现,会封装mvc框架的dispatchServlet,并设置相应的控制器。