一、http工具类
package com.shop.ums.config; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.io.IOException; public class HttpRequestUtil { private static final OkHttpClient client = new OkHttpClient(); private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); public static String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(url) .post(body) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } } }
二、实现方法
- 初始化与依赖注入:
- 在应用启动时,Spring容器会创建
SwaggerUserServiceImpl
的实例,并通过构造器注入RestTemplate
和StringRedisTemplate
依赖。这些依赖分别用于发起HTTP请求和缓存访问令牌。 -
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.9.0</version> <!-- 使用最新的版本 --> </dependency>
- 在应用启动时,Spring容器会创建
- 获取访问令牌:
- 在
list()
方法被调用之前,首先会调用getToken()
方法来尝试获取一个有效的访问令牌。 getToken()
方法首先尝试从Redis缓存中检索名为access_token
的键值。如果找到了令牌并且它仍然有效(尽管在这个示例中我们没有直接检查令牌的有效性,但在实际应用中这是必要的),则直接使用这个令牌。- 如果Redis中没有令牌或者令牌被认为已过期,
getToken()
方法将调用refreshToken()
方法来获取一个新的令牌。
- 在
- 刷新访问令牌:
refreshToken()
方法负责通过HTTP POST请求向认证服务(如OAuth2授权服务器)发送登录凭据(用户名和密码),以换取一个新的访问令牌。- 发送请求前,会构造一个包含登录信息的JSON字符串。然后,使用
HttpRequestUtil.post
方法(尽管这个方法在类中没有定义,但我们可以假设它是一个辅助工具类中的静态方法,用于发送HTTP POST请求)发送请求到认证服务的登录端点。 - 收到响应后,解析JSON响应体以提取访问令牌,并将其存储在Redis缓存中,设置过期时间为10分钟。这样,后续的请求就可以在缓存中快速获取到令牌,而无需每次都向认证服务发送登录请求。
- 调用第三方API获取用户列表:
- 一旦有了有效的访问令牌,
list()
方法将继续执行。它构造一个HTTP GET请求,该请求包含必要的授权头(Authorization: Bearer <access_token>
),并指向第三方API的用户列表端点。 - 使用
RestTemplate
的exchange
方法发送请求,并指定返回类型为Result<TableDataInfo>
,以便Spring能够自动将JSON响应体反序列化为该类型的对象。 - 最后,
list()
方法返回从第三方API检索到的用户列表数据。
- 一旦有了有效的访问令牌,
三、yml配置文件
third: party: api: url: http://139.224.214.38:8080/system/user1
四、实现方法
package com.shop.ums.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.shop.common.core.domain.Result; import com.shop.common.core.web.page.TableDataInfo; import com.shop.ums.config.HttpRequestUtil; import com.shop.ums.service.SwaggerUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.beans.factory.annotation.Value; import java.io.IOException; import java.util.HashMap; import java.util.concurrent.TimeUnit; /** * @Author:luyuhang * @Package:com.shop.ums.service.impl * @Project:fourproject * @name:SwaggerUserServiceImpl */ @Service public class SwaggerUserServiceImpl implements SwaggerUserService { private final RestTemplate restTemplate; private final StringRedisTemplate redisTemplate; @Value("${third.party.api.url}") private String apiUrl; private String token; private static final Logger log = LoggerFactory.getLogger(SwaggerUserServiceImpl.class); private String accessToken; public SwaggerUserServiceImpl(RestTemplate restTemplate, StringRedisTemplate redisTemplate) { this.restTemplate = restTemplate; this.redisTemplate = redisTemplate; } @Override public Result<TableDataInfo> list() { getToken(); String url = apiUrl + "/list"; HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + accessToken); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<Result<TableDataInfo>> response = restTemplate.exchange( url, HttpMethod.GET, entity, new ParameterizedTypeReference<Result<TableDataInfo>>() {} ); return response.getBody(); } private void getToken() { // 尝试从Redis获取token accessToken = redisTemplate.opsForValue().get("access_token"); if (accessToken != null) { log.info("获取token值为:{}", accessToken); return; } // 如果没有获取到token,或者token已经过期(这里假设你有一个方法来判断token是否过期),则重新获取 refreshToken(); } private void refreshToken() { HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("username", "admin"); hashMap.put("password", "admin123"); String url = "http://139.224.214.38:8080/auth/login"; String json = JSON.toJSONString(hashMap); try { token = HttpRequestUtil.post(url, json); JSONObject jsonObject = JSON.parseObject(token); JSONObject dataObject = jsonObject.getJSONObject("data"); accessToken = dataObject.getString("access_token"); // 将token存入Redis,设置10分钟有效期 redisTemplate.opsForValue().set("access_token", accessToken, 10, TimeUnit.MINUTES); log.info("Access Token refreshed: {}", accessToken); } catch (IOException e) { throw new RuntimeException("Failed to refresh access token", e); } } }