RestTemplate.exchange()构造Http请求
〇、配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/*
restTemplate 配置类 —— 基础配置写法
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
/**
* 配置一个简单的 HTTP 请求工厂, 设置 HTTP 请求的超时时间
* @return
*/
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(150000); // ms
factory.setConnectTimeout(150000); // ms
return factory;
}
}
一、GET请求
1.1 GET返回String
RestTemplate
接口
// 1.1 get请求返回基本类型
@GetMapping("/name")
public String getName(@RequestParam("id") Integer id) {
String url = "http://localhost:8080/name/Rest?id=" + id;
return restTemplate.exchange(url, HttpMethod.GET, null, String.class).getBody();
//getBody() 得到数据
}
被调用接口
@GetMapping("/name/Rest")
public String mockName(@RequestParam("id") Integer id) {
return "接口提供数据 " + id;
}
1.2 GET返回Pojo
请求接口
// 1.2 get请求返回对象类型
@GetMapping("/user")
public UserDto getUser(@RequestParam("id") Integer id) {
String url = "http://localhost:8080/user/Rest?id=" + id;
return restTemplate.exchange(url, HttpMethod.GET, null, User.class).getBody();
}
被调用接口
@GetMapping("/user/Rest")
public UserDto mockUser(@RequestParam("id") Integer id) {
return UserDto.builder().id(id)
.name("name" + id)
.age(id + 18)
.birthday(new Date()).build();
}
1.3 GET返回List<>
调用接口
// 1.3 get请求返回List<T>类型
@GetMapping("/user/list")
public List<UserDto> getUserList(@RequestParam("name") String name) {
String url = "http://localhost:8080/user/list/Rest?name=" + name;
ParameterizedTypeReference<List<UserDto>> responseBodyType = new ParameterizedTypeReference<List<UserDto>>() {};
return restTemplate.exchange(url, HttpMethod.GET, null, responseBodyType).getBody();
//restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<UserDto>>() {}).getBody();
}
被调用接口
@GetMapping("/user/list/Rest")
public List<UserDto> mockUserList(@RequestParam("name") String name) {
...
return list;
}
1.4 GET返回Map<key, value>
调用接口
// 1.4 get请求返回Map类型
@GetMapping("/user/map")
public Map<String, Object> getUserMap(@RequestParam(value = "type", required = true) Integer type, @RequestParam("key") String key) {
String url = "http://localhost:8080/user/Rest?type=" + type + "&key=" + key;
ParameterizedTypeReference<Map<String, Object>> responseBodyType = new ParameterizedTypeReference<Map<String, Object>>() {};
return restTemplate.exchange(url, HttpMethod.GET, null, responseBodyType).getBody();
}
被调用接口
@GetMapping("/user/map/mock")
public Map<String, Object> mockUserMap(@RequestParam(value = "type", required = true) Integer type, @RequestParam("key") String key) {
Map<String, Object> map = new HashMap<>();
if (type.equals(1)) {
map.put("id", 1);
map.put("name" + type, "hello" + key);
} else {
map.put("id", 2);
map.put("name" + type, "hello" + key);
}
return map;
}
1.5 GET返回Result<>
调用接口
// 1.5 get请求返回自定义泛型类型
@GetMapping("/user/result")
public Result<UserDto> getUserResult(@RequestParam("id") Integer id) {
String url = "http://localhost:8080/user/result/Rest?id=" + id;
ParameterizedTypeReference<Result<UserDto>> responseBodyType = new ParameterizedTypeReference<Result<UserDto>>() {};
return restTemplate.exchange(url, HttpMethod.GET, null, responseBodyType).getBody();
}
被调用接口
@GetMapping("/user/result/mock")
public Result<UserDto> mockUserResult(@RequestParam("id") Integer id) {
...
return Result.success("200", "成功", user);
}
二、POST请求
2.1 header+body返回Pojo
调用函数
@GetMapping("/user/body")
public UserDto postUser(@RequestParam("id") Integer id) {
String url = "http://localhost:8080/user/body/Rest";
UserDto body = UserDto.builder().id(id)
.name("body" + id)
.age(id + 18)
.birthday(new Date()).build();
// header根据实际情况设置,没有就空着
HttpHeaders headers = new HttpHeaders();
headers.add("AccessKey", "自定义的API访问key");
headers.add("Content-Type", "application/json");
HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
return restTemplate.exchange(url, HttpMethod.POST, requestEntity, UserDto.class).getBody();
//被调用函数是用@RequestBody 实体类来接受的参数
}
被调用函数
@PostMapping("/user/body/Rest")
public UserDto mockPostUser(@RequestBody UserDto userParam) {
return userParam;
}
2.2 header+body返回Result<>
只需要和GET请求一样,更改类型即可
ParameterizedTypeReference<Result<UserDto>> responseBodyType = new ParameterizedTypeReference<Result<UserDto>>(){};
return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseBodyType).getBody();
三、JSON格式处理
依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.6</version>
</dependency>
// 提取 JSON 字符串
String jsonString = responseEntity.getBody();
try {
// 创建 ObjectMapper 对象
ObjectMapper objectMapper = new ObjectMapper();
// 将 JSON 字符串转换为实体类对象
RestRegionDTO restRegionDTO = objectMapper.readValue(jsonString, RestRegionDTO.class);
// 打印转换后的实体类对象
System.out.println(restRegionDTO);
} catch (Exception e) {
//e.printStackTrace();
log.error("JSON格式处理发生异常");
}
完整代码
/**
* 请求太平洋 获得ip归属地信息
* @param ipAddress
* @return
*/
public RestRegionDTO getIpAddr(String ipAddress) {
String url = "http://whois.pconline.com.cn/ipJson.jsp?ip="+ipAddress+"&json=true";
// 发送 HTTP GET 请求并获取响应
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
// 提取 JSON 字符串
String jsonString = exchange.getBody();
RestRegionDTO restRegionDTO = new RestRegionDTO();
try {
// 创建 ObjectMapper 对象
ObjectMapper objectMapper = new ObjectMapper();
// 将 JSON 字符串转换为实体类对象
restRegionDTO = objectMapper.readValue(jsonString, RestRegionDTO.class);
// 打印转换后的实体类对象
log.info(String.valueOf(restRegionDTO));
} catch (Exception e) {
e.printStackTrace();
}
return restRegionDTO;
}
四、异常处理
try {
ResponseEntity<List<AppModel>> responseEntity = restTemplate.exchange(getApps, HttpMethod.GET, null, new ParameterizedTypeReference<List<AppModel>>() {});
//返回的状态码 == 200
if (responseEntity.getStatusCode() == HttpStatus.OK) {
List<AppModel> result = responseEntity.getBody();
if (result != null && !result.isEmpty()) {
return result;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
五、参考
使用RestTemplate发请求时自动拼接header信息(一学就会系列)_resttemplate 拦截器加header-CSDN博客
RestTemplate.exchange各种用法(包括泛型等 --全)-腾讯云开发者社区-腾讯云 (tencent.com)
RestTemplate总结_resttemple-CSDN博客
restTemplate配置及使用 - 简书 (jianshu.com)
六、结合AOP实现登录日志存储
自定义注解loginLog
/**
* 自定义注解,实现 登录日志 ip 记录
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface loginLog {
}
切面
/**
* 实现登陆用户 日志的记录
*/
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class LoginLogAspect {
private final LoginLogService loginLogService;
private final RestTemplateController restTemplateController;
//扫描加注释的方法
@Pointcut("@annotation(com.example.demoip.Annotation.loginLog)")
public void loginLog() {
}
@AfterReturning(pointcut = "loginLog()")
public void afterReturning(JoinPoint joinPoint) {
LocalDateTime now = LocalDateTime.now();
//获得签名
Signature signature = joinPoint.getSignature();
//获得切入的包名
String declaringTypeName = signature.getDeclaringTypeName();
//拿到方法名
String name = signature.getName();
// 也可以用来记录一些信息,比如获取请求的 URL 和 IP
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 请求里面获得ip
String ip = IpUtils.getIpAddr(request);
// 获取请求 URL
String url = request.getRequestURL().toString();
log.info("执行切点的包名:"+declaringTypeName+" 方法名:"+name+" url:"+url);
// 获得所有参数
Object[] args = joinPoint.getArgs();
User user = (User) args[0];
// ip归属地
String cityInfo = null;
//发送http请求
cityInfo = restTemplateController.getIpAddr(ip).getCity();
System.out.println(cityInfo);
loginLogService.saveLoginLog(
LoginLog.builder()
.ip(ip)
.ipAttribution(cityInfo)
.name(user.getUserName())
.createTime(now)
.build());
log.info("日志存入数据库");
}
}
构造RestTemplate Http请求
/**
* 请求太平洋 获得ip归属地信息 返回的是JSON数据
* @param ipAddress
* @return
*/
public RestRegionDTO getIpAddr(String ipAddress) {
String url = "http://whois.pconline.com.cn/ipJson.jsp?ip="+ipAddress+"&json=true";
// 发送 HTTP GET 请求并获取响应
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
// 提取 JSON 字符串
String jsonString = exchange.getBody();
RestRegionDTO restRegionDTO = new RestRegionDTO();
try {
// 创建 ObjectMapper 对象
ObjectMapper objectMapper = new ObjectMapper();
// 将 JSON 字符串转换为实体类对象
restRegionDTO = objectMapper.readValue(jsonString, RestRegionDTO.class);
// 打印转换后的实体类对象
log.info(String.valueOf(restRegionDTO));
} catch (Exception e) {
e.printStackTrace();
}
return restRegionDTO;
}