发布时间:2025-12-09 13:50:48 浏览次数:4
先看看项目的整体结构
依赖的jar包
<dependencies><!--json相关--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.32</version></dependency><!-- 添加slf4j日志api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.20</version></dependency><!-- 添加logback-classic依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- 添加logback-core依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency><!--lombok支持--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version></dependency><!--工具类--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version></dependency></dependencies>用户查询的客户端,继承ClientAbstract 类
package com.lh.hope.client;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.TypeReference;import com.lh.hope.common.ReturnCodeEnum;import com.lh.hope.domain.SysUser;import com.lh.hope.domain.SysUserDTO;import com.lh.hope.domain.common.ApiRequest;import com.lh.hope.domain.common.BaseResponse;import com.lh.hope.domain.common.PageModel;import lombok.extern.slf4j.Slf4j;@Slf4jpublic class SysUserClient extends ClientAbstract { public static BaseResponse<PageModel<SysUser>> queryUserList(ApiRequest<SysUserDTO> request) { try { String str = post(request);return JSON.parseObject(str, new TypeReference<BaseResponse<PageModel<SysUser>>>() { });} catch (Exception e) { log.error("SysUserClient queryUserList is exception! request={}", request);return BaseResponse.error(ReturnCodeEnum.SYSTEM_ERROR);}}}提供了入参加密,返回解密的功能,http请求。这里也可以添加参数校验的功能,这里省略。
package com.lh.hope.client;import com.alibaba.fastjson.JSON;import com.lh.hope.common.HopeException;import com.lh.hope.common.ReturnCodeEnum;import com.lh.hope.domain.common.ApiRequest;import com.lh.hope.domain.common.HopeRequest;import com.lh.hope.domain.common.HopeResponse;import com.lh.hope.utils.HttpUtil;import com.lh.hope.utils.RsaUtil;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;@Slf4jclass ClientAbstract { static String post(ApiRequest request) { HopeRequest hopeRequest = HopeRequest.builder().appId(request.getAppId()).data(RsaUtil.encrypt(request.getPublicKey(), JSON.toJSONString(request.getData()))).build();String s = HttpUtil.doPost(request.getUrl(), JSON.toJSONString(hopeRequest));if (StringUtils.isBlank(s)) { log.error("client post api result is null!");throw new HopeException(ReturnCodeEnum.API_ERROR);}HopeResponse hopeResponse = JSON.parseObject(s, HopeResponse.class);if (!hopeResponse.isSuccess()) { log.error("client post api error! hopeResponse={}", hopeResponse);throw new HopeException(ReturnCodeEnum.API_ERROR.getCode(), hopeResponse.getMessage());}return RsaUtil.decrypt(request.getPublicKey(), hopeResponse.getData());}}Http请求的工具类,这里简单写一个psot请求的方法。参数传递方法为application/json。
package com.lh.hope.utils;import lombok.extern.slf4j.Slf4j;import java.io.*;import java.net.HttpURLConnection;import java.net.URL;@Slf4jpublic class HttpUtil { /** * Http post请求 * * @param httpUrl 连接 * @param param 参数 * @return */public static String doPost(String httpUrl, String param) { log.info(" HttpUtil doPost begin! httpUrl={} param={}", httpUrl, param);StringBuilder result = new StringBuilder();//连接HttpURLConnection connection = null;OutputStream os = null;InputStream is = null;BufferedReader br = null;try { //创建连接对象URL url = new URL(httpUrl);//创建连接connection = (HttpURLConnection) url.openConnection();//设置请求方法connection.setRequestMethod("POST");//设置连接超时时间connection.setConnectTimeout(15000);//设置读取超时时间connection.setReadTimeout(15000);//DoOutput设置是否向httpUrlConnection输出,DoInput设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个//设置是否可读取connection.setDoOutput(true);connection.setDoInput(true);//设置通用的请求属性connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");connection.setRequestProperty("connection", "Keep-Alive");//拼装参数if (null != param && !param.equals("")) { //设置参数os = connection.getOutputStream();//拼装参数os.write(param.getBytes("UTF-8"));}//开启连接connection.connect();//读取响应if (connection.getResponseCode() == 200) { is = connection.getInputStream();if (null != is) { br = new BufferedReader(new InputStreamReader(is, "UTF-8"));String temp = null;while (null != (temp = br.readLine())) { result.append(temp);result.append("\r\n");}}}} catch (Exception e) { e.printStackTrace();log.error("HttpUtil doPost exception! httpUrl={} param={}", httpUrl, param, e);} finally { //关闭连接if (br != null) { try { br.close();} catch (IOException e) { e.printStackTrace();}}if (os != null) { try { os.close();} catch (IOException e) { e.printStackTrace();}}if (is != null) { try { is.close();} catch (IOException e) { e.printStackTrace();}}//关闭连接if (connection != null) { connection.disconnect();}}log.info(" HttpUtil doPost end! result={}", result);return result.toString();}}RSA加解密的工具类
package com.lh.hope.utils;import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;import lombok.extern.slf4j.Slf4j;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import java.security.Key;import java.security.KeyFactory;import java.security.PrivateKey;import java.security.PublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Arrays;@Slf4jpublic class RsaUtil { /** * 算法加解密算法 */private static final String ALGORITHM = "RSA";/** * 最大加密字节数,超出最大字节数需要分组加密 */private static final Integer MAX_ENCRYPT_BLOCK = 117;private static final Integer MAX_DECRYPT_BLOCK = 128;/** * 请求报文公钥解密 * * @param publicKeyString 公钥 * @param text 报文 * @return 加密报文 */public static String encrypt(String publicKeyString, String text) { try { PublicKey publicKey = getPublicKey(publicKeyString);return encryptRSA(publicKey, text);} catch (Exception e) { e.printStackTrace();log.error("RsaUtil encrypt exception! publicKeyString={} text={}", publicKeyString, text);return null;}}/** * 应答报文公钥解密 * * @param publicKeyString 公钥 * @param text 应答密文 * @return 解密报文 */public static String decrypt(String publicKeyString, String text) { try { PublicKey publicKey = getPublicKey(publicKeyString);return decryptRSA(publicKey, text);} catch (Exception e) { e.printStackTrace();log.error("RsaUtil decrypt exception! publicKeyString={} text={}", publicKeyString, text);return null;}}/** * RSA 加密 * * @param key 密钥 * @param text 原文 * @return 密文 * @throws Exception 异常 */private static String encryptRSA(Key key, String text) throws Exception { // 创建加密对象Cipher cipher = Cipher.getInstance(ALGORITHM);// 对加密进行初始化 第一个参数是加密模式,第二个参数是你想用的公钥加密还是私钥加密cipher.init(Cipher.ENCRYPT_MODE, key);// 分段加密byte[] make = doCrypt(text.getBytes(), cipher, MAX_ENCRYPT_BLOCK);return Base64.encode(make);}/** * RSA 解密 * * @param key 密钥 * @param text 密文 * @return 明文 * @throws Exception 异常 */private static String decryptRSA(Key key, String text) throws Exception { // 创建加解密对象Cipher cipher = Cipher.getInstance(ALGORITHM);// 对解密进行初始化 第一个参数是加密模式,第二个参数是你想用的公钥解密还是私钥解密cipher.init(Cipher.DECRYPT_MODE, key);//分段解密byte[] make = doCrypt(Base64.decode(text), cipher, MAX_DECRYPT_BLOCK);return new String(make);}/** * 分段加解密 * * @param data 要加解密的内容数组 * @param cipher 加解密对象 * @param maxBlock 分段大小 * @return 结果 * @throws IllegalBlockSizeException 异常 * @throws BadPaddingException 异常 */private static byte[] doCrypt(byte[] data, Cipher cipher, Integer maxBlock) throws IllegalBlockSizeException, BadPaddingException { int inputLength = data.length;// 标识int offSet = 0;byte[] resultBytes = { };byte[] cache;while (inputLength - offSet > 0) { if (inputLength - offSet > maxBlock) { cache = cipher.doFinal(data, offSet, maxBlock);offSet += maxBlock;} else { cache = cipher.doFinal(data, offSet, inputLength - offSet);offSet = inputLength;}resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);}return resultBytes;}/** * 获取私钥 * * @param privateKeyString 私钥路径 * @return 私钥 */private static PrivateKey getPrivateKey(String privateKeyString) throws Exception { // 创建key的工厂KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);// 创建私钥key的规则PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString));// 返回私钥对象return keyFactory.generatePrivate(keySpec);}/** * 获取公钥 * * @param publicKeyString 公钥 * @return 公钥 * @throws Exception 异常 */private static PublicKey getPublicKey(String publicKeyString) throws Exception { // 创建key的工厂KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);// 创建公钥key的规则X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKeyString));// 返回公钥对象return keyFactory.generatePublic(keySpec);}}测试类
package com.lh.hope;import com.alibaba.fastjson.JSON;import com.lh.hope.client.SysUserClient;import com.lh.hope.domain.SysUser;import com.lh.hope.domain.SysUserDTO;import com.lh.hope.domain.common.ApiRequest;import com.lh.hope.domain.common.BaseResponse;import com.lh.hope.domain.common.PageModel;public class App { /** * 公钥 */private static final String PUBLIC_KEY_STRING = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCllRJyNyA5/kOKpF+VV322IN7fownz5GMltjnWLHJPE+xdusVYHz/3C0ck27sv7mHP0TrJ7PLxUHyeUJ9PGOZ2fyrBRikKNE4ce1ihNgQxorIJ68G+70eHyOr65mQxRYa4lUOHMMPHgicN/2vGCjwL/ET8eQU0yIRAoOnO8avAuQIDAQAB";public static void main(String[] args) { SysUserDTO dto = new SysUserDTO();dto.setStatus(0);ApiRequest<SysUserDTO> request = ApiRequest.<SysUserDTO>builder().appId("000001").url("http://localhost:8081/api/user/queryUserList").publicKey(PUBLIC_KEY_STRING).data(dto).build();BaseResponse<PageModel<SysUser>> pageModelBaseResponse = SysUserClient.queryUserList(request);System.out.println(JSON.toJSONString(pageModelBaseResponse));}}这个是接口的入参,这里简单演示,一个客户端唯一编号(用来获取对应的私钥),一个是加密的入参。
package com.lh.entity.api;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class HopeRequest { /** * 客户端唯一编号 */private String appId;/** * 加密后业务相关的入参 */private String data;}package com.lh.entity.api;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class HopeResponse { /** * 是否成功 */private boolean success;/** * 返回信息 */private String message;/** * 业务相关的返回信息,私钥加密之后的 */private String data;}这个类是创建入参是用的,有客户端唯一Id(appId),请求的接口地址,公钥还有业务相关的入参。
package com.lh.hope.domain.common;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class ApiRequest<T> { private String url;private String publicKey;private String appId;private T data;}File ——》 Project Structure ——》 Project Settings ——》 Artifacts ——》 右栏左上角+ ——》JAR ——》 From Modules with dependencies——》OK
直接确定无需指定主类
不用更改 点击apply
Build ——》 Build Artifacts
现在一个简单的SDK已经开发打包好了,服务端之前也已经开发并启动了,现在就剩下最后一步客户端引用SDK测试了。