个人主页:金鳞踏雨
个人简介:大家好,我是金鳞,一个初出茅庐的Java小白
目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作
我的博客:这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进步 ~
前言
前一段时间,跟着视频学习了策略模式,总结如下:
【23种设计模式】策略模式(State Pattern)_金鳞踏雨的博客-CSDN博客https://harmony.blog.csdn.net/article/details/131078118这几天公司的项目中正好使用到了策略模式!由于项目中经常需要调HTTP请求,所以使用策略模式来处理不同的HTTP请求。
策略模式
简单来说,就是为了解决多重 if 的问题,优化代码结构
环境(Context)/ 上下文:环境是策略模式的核心,它持有一个策略对象的引用,并在需要执行特定算法时,调用策略对象的方法。环境类负责将客户端的请求委派给具体的策略对象。
抽象策略(Strategy):抽象策略定义了策略类的公共接口,它可以是一个接口或抽象类。它声明了策略类应该实现的方法,以便环境类能够通过统一的接口调用不同的策略。
具体策略(Concrete Strategy):具体策略是抽象策略的具体实现,它实现了策略接口定义的方法,并封装了具体的算法逻辑。在不同的具体策略中,算法的实现可以有所不同。
策略模式实现通用的HTTP接口
1. 抽象策略(Strategy)
public abstract class AbstractXXXInterface {private static final Logger logger = Logger .getLogger("XXX");protected Context ctx;protected String otherJsonParam;protected int type;/** 查询接口配置信息的sql */private static final String querySql = "SELECT interfaceUrl, isOpen, typeLabel from T_RH_InterfaceConfig where interfaceType = %s";/** 单据编号 */protected String billNumber;/** 接口配置信息 */private InterfaceConfigEntity info;private String result;/** 请求方式:get、post */protected String httpMethodType;private JSONObject jsonObject;protected JSONObject otherParam;private boolean isCheckOpen = true;public AbstractXXXInterface setIsCheckOpen(boolean isCheckOpen) {this.isCheckOpen = isCheckOpen;return this;}protected abstract void initData();public AbstractXXXInterface call() throws Exception {if (StringUtils.isNotBlank(otherJsonParam)) {otherParam = JSONObject.parseObject(otherJsonParam);}// 校验validator();if (!isCall()) {return this;}initData();// 获取接口信息info = getInterfaceInfo();if (info == null) {throw new BOSException("接口信息为空");}if (isCheckOpen && !isOpen(info.getIsOpen())) {logger.error("接口:【" + info.getInterfaceLabel() + "】未开启");setResult("接口:【" + info.getInterfaceLabel() + "】未开启");return this;}// 设置接口参数info.setParamJson(createParamJson());// 调用接口jsonObject = HttpClientNewUtil.doHttp(ctx, info, httpMethodType);// 处理响应结果callBack();return this;}protected boolean isCall() throws Exception {return true;}/*** 通用校验,可以重写该方法实现自己的校验*/protected void validator() throws Exception {if (StringUtils.isBlank(billNumber)) {logger.error("接口:【" + info.getInterfaceLabel() + "】单据编号为空");throw new BOSException("单据编号不能为空");}}/*** 执行sql获取接口信息*/private InterfaceConfigEntity getInterfaceInfo() throws Exception {try {IRowSet rowSet = DbUtil.executeQuery(ctx, String.format(querySql, type));while (rowSet.next()) {InterfaceConfigEntity info = new InterfaceConfigEntity();info.setInterfaceUrl(rowSet.getString("interfaceUrl"));info.setIsOpen(rowSet.getInt("isOpen"));info.setInterfaceLabel(rowSet.getString("typeLabel"));return info;}} catch (Exception e) {logger.error("sql: " + type + "执行异常.", e);throw new Exception(e.getMessage());}return null;}/*** 处理响应结果*/protected void callBack() throws Exception {JSONObject result = getJsonObject();if (result == null) {logger.error("单据【" + billNumber + "】响应结果为空");return;}if (isSuccess(result.getString("code"))) {successAfter(result);} else {failAfter(result);}}/*** 成功后调用*/protected abstract void successAfter(JSONObject result) throws Exception;/*** 失败后调用*/protected abstract void failAfter(JSONObject result) throws Exception;/*** 根据具体单据创建请求参数*/protected abstract String createParamJson() throws Exception;/*** 判断是否开启:1-开启,返回true*/private boolean isOpen(int isOpen) {return CommonUtils.convertBoolean(isOpen);}protected boolean isSuccess(String code) {return XXXConstant.InterfaceReturnCode.SUCCESSE.equals(code) || XXXConstant.InterfaceReturnCode.SUCCESSE1.equals(code) || XXXConstant.InterfaceReturnCode.SUCCESSE2.equals(code);}/*** getter、setter方法*/protected void setXXX(String XXX) {this.XXX= XXX;}public String getXXX() {return XXX;}
}
2. 抽象工厂
public class XXXFactory {private XXXFactory() {}public static AbstractXXXInterface getStrategy(int type) {if (XXXConstant.InterfaceType.TYPE1 == type) {return new DEMO1();} else if (XXXConstant.InterfaceType.TYPE2 == type) {return new DEMO2();} else if (...) {return ...;} else {return null;}}
}
3. 具体策略(Concrete Strategy)
public class DEMO1 extends AbstractXXXInterface {private static Logger logger = Logger.getLogger("XXX");@Overrideprotected String createParamJson() throws BOSException, SQLException {// 拼接请求报文(body) return null;}@Overrideprotected void failAfter(JSONObject result) throws BOSException,SQLException {// 调用接口失败的处理逻辑,处理响应setResult("同步失败"); }@Overrideprotected void initData() {this.httpMethodType = CommonConstant.HttpType.POST;this.type = XXXConstant.InterfaceType.TYPE1; }@Overrideprotected void successAfter(JSONObject result) throws BOSException,SQLException {// 调用接口成功的处理逻辑,处理响应setResult("同步成功");}
}
4. HTTP工具类
/*** HTTP工具类*/
public class HttpClientNewUtil {private static final Logger logger = Logger.getLogger("XXX");public static JSONObject doHttp(Context ctx, InterfaceConfigEntity info, String type) {String url = info.getInterfaceUrl();String token = "";try {if (isUrlEmpty(url)) {logger.error("接口地址为空");return null;}logger.error("start call interface: " + info.getInterfaceLabel());logger.error("The paramJson is: " + info.getParamJson());CloseableHttpClient httpClient = createClient(url);if (CommonConstant.HttpType.POST.equals(type)) {return doPost(ctx, httpClient, url, info, token);} else if (CommonConstant.HttpType.GET.equals(type)) {return doGet(ctx, httpClient, url, info, token);}} catch (Exception e) {logger.error("访问接口失败,接口地址为:" + url, e);}return null;}private static JSONObject doPost(Context ctx, CloseableHttpClient httpClient, String url,InterfaceConfigEntity info, String token) throws IOException {HttpPost httpPost = new HttpPost(url);httpPost.setHeader("source", "99");httpPost.setHeader("site", "1");// 设置Token头部httpPost.setHeader("token", getToken(ctx));if(info.getParamJson() != null) {StringEntity entity = new StringEntity(info.getParamJson(), "UTF-8");entity.setContentType("application/json");httpPost.setEntity(entity);}return parseResult(httpClient.execute(httpPost), info);}private static JSONObject doGet(Context ctx, CloseableHttpClient httpClient, String url,InterfaceConfigEntity info, String token) throws IOException {Map<String, String> params = JSONObject.parseObject(info.getParamJson(), Map.class);List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());for (Map.Entry<String, String> entry : params.entrySet()) {String value = entry.getValue();if (value != null) {pairs.add(new BasicNameValuePair(entry.getKey(), value));}}url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, "UTF-8"));HttpGet httpGet = new HttpGet(url);httpGet.setHeader("source", "99");httpGet.setHeader("site", "1");// 设置Token头部httpGet.setHeader("token", getToken(ctx));return parseResult(httpClient.execute(httpGet), info);}private static JSONObject parseResult(CloseableHttpResponse response, InterfaceConfigEntity info) throws IOException {logger.error("response:" + response);if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {String resultJson = EntityUtils.toString(response.getEntity(), "utf-8");logger.error(info.getInterfaceLabel() + " response: " + resultJson);response.close();return JSONObject.parseObject(resultJson);}return null;}/*** 创建HttpClient客户端*/@SuppressWarnings("deprecation")private static CloseableHttpClient createClient(String url) {HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();if (url.startsWith("https")) {try {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有@Overridepublic boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);httpClientBuilder.setSSLSocketFactory(sslsf);} catch (Exception e) {logger.error("创建HTTPS客户端异常", e);}}return httpClientBuilder.build();}/*** 判断url是否为空:为空返回true*/private static boolean isUrlEmpty(String url) {return StringUtils.isBlank(url);}/*** 获取token*/private static String getToken(Context ctx) {String token = null;try {String sql = "select interfaceUrl from T_RH_InterfaceConfig where interfaceType = 14;";IRowSet rs = DbUtil.executeQuery(ctx, sql);rs.next();// 构造获取Token的请求HttpPost tokenRequest = new HttpPost(rs.getString("interfaceUrl"));tokenRequest.setHeader("Content-Type", "application/json");// 设置请求参数,如用户名和密码JSONObject requestBody = new JSONObject();requestBody.put("account", "eas");requestBody.put("password", "o6H95Utzv9GKzvx9+P45Zw==");StringEntity entity = new StringEntity(requestBody.toJSONString());entity.setContentType("application/json");tokenRequest.setEntity(entity);// 发送请求并解析响应CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = httpClient.execute(tokenRequest);if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {String responseBody = EntityUtils.toString(response.getEntity());JSONObject responseJson = JSONObject.parseObject(responseBody);// 提取Token字段int code = responseJson.getIntValue("code");if (code == 1000) {JSONObject data = responseJson.getJSONObject("data");token = data.getString("token");}}// 关闭资源response.close();httpClient.close();} catch (Exception e) {logger.error("获取Token失败", e);}return token;}
}
文章到这里就结束了,如果有什么疑问的地方,可以在评论区指出~
希望能和大佬们一起努力,诸君顶峰相见
再次感谢各位小伙伴儿们的支持!!!