总体设计
数据库设计
项目结构
服务器项目结构
客户端项目结构
项目代码
controller代码
CitizenIdentityApiContriller.java
- **** 身份逻辑验证之后,会返回相应的查询结构
- /此为本人自己查阅资料的劳动成果,转载请注明链接/
package com.mp.api.controller;
import com.mp.api.constant.InvokerEnum;
import com.mp.api.constant.OperationEnum;
import com.mp.api.dto.ResponseDTO;
import com.mp.api.entity.CitizenIdentity;
import com.mp.api.entity.Member;
import com.mp.api.service.CitizenIdentityService;
import com.mp.api.service.MemberService;
import com.mp.api.util.VerifyUtil;
import com.mp.api.vo.CitizenIdentityVO;
import com.mp.api.vo.ResponseVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Objects;
/**
-
@ Author :MP…
-
@ Date :Created in 18:08 2019/6/28
-
@ Description:公民身份信息控制器
-
@ Modified By:
-
@Version: $
*/
@RestController
@RequestMapping("/citizen-identity")
@Api(value = “CitizenIdentityApiContriller”, tags = {“公民身份信息查询接口”})
public class CitizenIdentityApiContriller {@Autowired
private MemberService memberService;
@Autowired
private CitizenIdentityService citizenIdentityService;/**
- @Description: 根据公民姓名和身份证号查询身份信息
- @Param: [citizenIdentityVO]
- @return: ResponseDTO<ResponseVO>
- @Author: MP.
- @Date: 2019/6/28
*/
@RequestMapping(value = “”, method = {RequestMethod.GET, RequestMethod.POST})
@ApiOperation(value = “查询公民身份信息”, notes = “根据公民姓名和身份证号查询公民身份信息”)
public ResponseDTO<ResponseVO> getCitizenIdentity(@ApiParam(name = “citizenIdentityVO”, value = “公民身份查询参数对象”, required = true) @Valid CitizenIdentityVO citizenIdentityVO) {
//查询会员编号是否正确
Member member = memberService.getMemberByMemberNo(citizenIdentityVO.getMemberNo());
if (Objects.isNull(member)) {
return ResponseDTO.fail(InvokerEnum.AUTH_FAIL);
}
//检查签名
if (!VerifyUtil.checkSign(citizenIdentityVO, member.getSecretKey())) {
return ResponseDTO.fail(InvokerEnum.SIGN_FAIL);
}
//查询公民身份信息
CitizenIdentity citizenIdentity = citizenIdentityService.getCitizenIdentityByIdNo(citizenIdentityVO.getIdNo());
if (Objects.isNull(citizenIdentity)) {
return ResponseDTO.success(ResponseVO.fail(OperationEnum.NOT_EXISTS));
}
if (!Objects.equals(citizenIdentityVO.getName(), citizenIdentity.getName())) {
return ResponseDTO.success(ResponseVO.fail(OperationEnum.NOT_MATCH));
}
return ResponseDTO.success(ResponseVO.success(citizenIdentity));
}
}
service层代码
MemberServiceImpl.java
- ****;
- package com.mp.api.service.impl;
import com.mp.api.entity.Member;
import com.mp.api.mapper.MemberMapper;
import com.mp.api.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
-
@ Author :MP…
-
@ Date :Created in 15:03 2019/6/29
-
@ Description:身份信息服务接口
-
@ Modified By:
-
@Version: $
*/
@Service
public class MemberServiceImpl implements MemberService {@Autowired
private MemberMapper memberMapper;@Override
public Member getMemberByMemberNo(String memberNo) {
return memberMapper.getMemberByMemberNo(memberNo);
}
}
CitizenIdentityServiceImpl .java
/此为本人自己查阅资料的劳动成果,转载请注明链接/
package com.mp.api.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mp.api.entity.CitizenIdentity;
import com.mp.api.mapper.CitizenIdentityMapper;
import com.mp.api.service.CitizenIdentityService;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
-
@ Author :MP…
-
@ Date :Created in 18:55 2019/6/28
-
@ Description:公民身份信息服务实现类
-
@ Modified By:
-
@Version: $
*/
@Service
public class CitizenIdentityServiceImpl extends ServiceImpl<CitizenIdentityMapper, CitizenIdentity> implements CitizenIdentityService {
@Override
public CitizenIdentity getCitizenIdentityByIdNo(String idNo) {return baseMapper.getCitizenIdentityByIdNo(idNo);
}
}
dao层
CitizenIdentityMapper.java
- package com.mp.api.mapper;
import com.mp.api.entity.CitizenIdentity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
/**
-
@ Author :MP…
-
@ Date :Created in 18:31 2019/6/28
-
@ Description:公民身份信息 Mapper 接口
-
@ Modified By:
-
@Version: $
*/
public interface CitizenIdentityMapper extends BaseMapper {/**
- 根据身份证号查询身份信息
- @param idNo
- @return com.lx.api.entity.CitizenIdentity
- @author zhuwenbin
- @since 2019/3/1 14:52
*/
@Select(“select * from citizen_identity where id_no = #{idNo}”)
CitizenIdentity getCitizenIdentityByIdNo(String idNo);
}
MemberMapper.java
package com.mp.api.mapper;
import com.mp.api.entity.Member;
import com.mp.api.entity.Member;
import org.apache.ibatis.annotations.Select;
/**
-
会员信息访问接口
*/
public interface MemberMapper {/**
- 根据会员编号查询会员信息
- @param memberNo
- @return
*/
@Select(“select * from member where member_no = #{memberNo}”)
Member getMemberByMemberNo(String memberNo);
}
其他一些业务处理的工具类
OperationEnum.java
- package com.mp.api.constant;
public enum OperationEnum {
SUCCESS("0", ""), NOT_EXISTS("1", "身份信息不存在"),
NOT_MATCH("2", "姓名和身份证号不匹配");
//业务处理状态码:0-成功;其他失败
private String code;
//业务处理错误信息
private String msg;
private OperationEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
InvokerEnum.java
package com.mp.api.constant;
public enum InvokerEnum {
SUCCESS("0", ""), SYSTEM_ERROR("1", "系统异常"),
ILLEGAL_ARGUMENT("10", "非法参数"), AUTH_FAIL("11", "会员身份认证失败"),
SIGN_FAIL("12", "签名验证失败");
//接口调用状态码:0-成功,其他失败
private String retCode;
//接口调用错误信息
private String retMsg;
private InvokerEnum(String retCode,String retMsg ){
this.retCode = retCode;
this.retMsg = retMsg;
}
public String getRetCode() {
return retCode;
}
public void setRetCode(String retCode) {
this.retCode = retCode;
}
public String getRetMsg() {
return retMsg;
}
public void setRetMsg(String retMsg) {
this.retMsg = retMsg;
}
}
CitizenIdentityVO.java
package com.mp.api.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@ApiModel
@Data
public class CitizenIdentityVO extends SystemVO{
@ApiModelProperty(name = "name", value = "姓名", required = true)
@NotEmpty(message = "姓名不能为空")
@Pattern(regexp = "^[\\u4E00-\\u9FA5\\uf900-\\ufa2d·s]{2,20}$", message = "姓名格式不正确")
private String name;
@NotEmpty(message = "身份证号码不能为空")
@Pattern(regexp = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)", message = "身份证号码格式不正确")
@ApiModelProperty(name = "idNo", value = "身份证号码", required = true)
private String idNo;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdNo() {
return idNo;
}
public void setIdNo(String idNo) {
this.idNo = idNo;
}
}
ResponseVO.java
package com.mp.api.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mp.api.constant.OperationEnum;
import lombok.Data;
import java.io.Serializable;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseVO implements Serializable {
private static final long serialVersionUID = 1L;
//业务处理成功与否,0为成功,其他值为失败
private String code;
//业务处理失败信息
private String msg;
private T content;
public ResponseVO() {
}
public ResponseVO(String code, String msg) {
this.code = code;
this.msg = msg;
}
public ResponseVO(String code, String msg, T content) {
this.code = code;
this.msg = msg;
this.content = content;
}
public ResponseVO(OperationEnum operationEnum) {
this.code = operationEnum.getCode();
this.msg = operationEnum.getMsg();
}
/**
* 业务处理成功
*
* @param content
* @return com.lx.api.vo.ResponseVO
*/
public static <T extends Serializable> ResponseVO success(T content) {
return new ResponseVO(OperationEnum.SUCCESS.getCode(), OperationEnum.SUCCESS.getMsg(), content);
}
/**
* 业务处理失败
*
* @param operationEnum
* @return com.lx.api.vo.ResponseVO
*/
public static <T extends Serializable> ResponseVO fail(OperationEnum operationEnum) {
return new ResponseVO(operationEnum.getCode(), operationEnum.getMsg());
}
}
SystemVO.java
/此为本人自己查阅资料的劳动成果,转载请注明链接/
package com.mp.api.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
/**
-
@ Author :MP…
-
@ Date :Created in 19:16 2019/6/28
-
@ Description:系统参数类
-
@ Modified By:
-
@Version: $
*/
@ApiModel
@Data
public class SystemVO {@ApiModelProperty(name = “memberNo”, value = “会员编号”, required = true)
@NotEmpty(message = “会员编号不能为空”)
@Pattern(regexp = “\w{9}”, message = “会员格式不正确”)
private String memberNo;@NotEmpty(message = “签名不能为空”)
@Pattern(regexp = “[a-z0-9]{32}”, message = “签名格式不正确”)
@ApiModelProperty(name = “sign”, value = “签名”, required = true)
private String sign;public String getMemberNo() {
return memberNo;
}public void setMemberNo(String memberNo) {
this.memberNo = memberNo;
}public String getSign() {
return sign;
}public void setSign(String sign) {
this.sign = sign;
}
}
ResponseDTO.java
- package com.mp.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mp.api.constant.InvokerEnum;
import lombok.Data;
import java.io.Serializable;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseDTO {
//调用接口成功与否,0为成功,其他值为失败
private String retCode;
//调用接口失败信息
private String retMsg;
//调用接口成功后返回内容
private T body;
public ResponseDTO() {
}
public ResponseDTO(String retCode, String retMsg) {
this.retCode = retCode;
this.retMsg = retMsg;
}
public ResponseDTO(String retCode, String retMsg, T body) {
this.retCode = retCode;
this.retMsg = retMsg;
this.body = body;
}
public ResponseDTO(InvokerEnum invokerEnum) {
this.retCode = invokerEnum.getRetCode();
this.retMsg = invokerEnum.getRetMsg();
}
/**
* 调用接口成功
*
* @param body
* @return com.lx.api.dto.ResponseDTO
*/
public static <T extends Serializable> ResponseDTO success(T body) {
return new ResponseDTO(InvokerEnum.SUCCESS.getRetCode(), InvokerEnum.SUCCESS.getRetMsg(), body);
}
/**
* 调用接口失败
*
* @param invokerEnum
* @return com.lx.api.dto.ResponseDTO
*/
public static <T extends Serializable> ResponseDTO fail(InvokerEnum invokerEnum) {
return new ResponseDTO(invokerEnum.getRetCode(), invokerEnum.getRetMsg());
}
}
CitizenIdentity.java
- package com.mp.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(“citizen_identity”)
public class CitizenIdentity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
@JsonIgnore
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 身份证号码
*/
private String idNo;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private Integer sex;
/**
* 住址
*/
private String address;
/**
* 电话号码
*/
private String phoneNo;
/**
* 邮箱
*/
private String email;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdNo() {
return idNo;
}
public void setIdNo(String idNo) {
this.idNo = idNo;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Member.java
package com.mp.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(“member”)
public class Member implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private int id;
private String memberName;
@JsonIgnore
private String password;
@JsonIgnore
private String memberNo;
@JsonIgnore
private String secretKey;
private Date createDate;
private Date updateDate;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMemberName() {
return memberName;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMemberNo() {
return memberNo;
}
public void setMemberNo(String memberNo) {
this.memberNo = memberNo;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
}
VerifyUtil.java
- package com.mp.api.util;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.SecureUtil;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
- 验证工具
*/
public class VerifyUtil {
/**
* 检查签名
*
* @param paramVO
* @param secretKey
* @return boolean
*/
public static boolean checkSign(Object paramVO, String secretKey) {
//获取需要签名的参数集合
Map<String, Object> paramMap = getParamMap(paramVO);
//获取签名
String sign = getSign(paramMap, secretKey);
//比较
return sign.equals(paramMap.get("sign"));
}
/**
* 获取参数集合
*
* @param paramVO
* @return java.util.Map<java.lang.String, java.lang.Object>
*/
public static Map<String, Object> getParamMap(Object paramVO) {
//bean转map
Map<String, Object> paramMap = convertObjToMap(paramVO);
return paramMap;
}
/**
* 过滤并排序
*
* @param paramMap
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
public static Map<String, Object> filterAndSortMap(Map<String, Object> paramMap){
//过滤值为null的字段
paramMap = MapUtil.filter(paramMap, (Filter<Map.Entry<String, Object>>) stringObjectEntry -> !stringObjectEntry.getKey().equals("sign"));
//对上述参数key进行排序按照字典序(a-z),请注意byte[]类型的参数不参与排序和计算签名,
// 比如上传的文件;空值的参数也不参与排序和计算签名
paramMap = MapUtil.sort(paramMap, (str, str2) -> {
char[] chars = str.toCharArray();
char[] chars2 = str2.toCharArray();
int i = 0;
while (i < chars.length && i < chars2.length) {
if (chars[i] > chars2[i]) {
return 1;
} else if (chars[i] < chars2[i]) {
return -1;
} else {
i++;
}
}
if (i == chars.length) { //str到头
return -1;
}
if (i == chars2.length) { //str2到头
return 1;
}
return 0;
});
return paramMap;
}
/**
* 获取签名
*
*
*/
public static String getSign(Map<String, Object> paramMap, String secretKey) {
//过滤并排序
paramMap = filterAndSortMap(paramMap);
//以key+value方式拼装字符串
String paramStr = MapUtil.joinIgnoreNull(paramMap, "", "");
//加密
String sign = SecureUtil.md5(paramStr + secretKey);
return sign;
}
public static String getSign(Object paramVO, String secretKey) {
//获取参数集合
Map<String, Object> paramMap = getParamMap(paramVO);
return getSign(paramMap, secretKey);
}
/**
* JavaBean对象转换为Map(包括父类属性)
*
* @param obj
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
public static Map<String, Object> convertObjToMap(Object obj){
Map<String,Object> reMap = new HashMap<String,Object>();
if (obj == null)
return null;
try {
Class<?> objClass = obj.getClass();
while(objClass != null){
Field[] fields = objClass.getDeclaredFields();
for(int i=0;i<fields.length;i++){
try {
Field f = objClass.getDeclaredField(fields[i].getName());
f.setAccessible(true);
Object o = f.get(obj);
reMap.put(fields[i].getName(), o);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
objClass = objClass.getSuperclass();
}
} catch (SecurityException e) {
e.printStackTrace();
}
return reMap;
}
}
mapper配置文件
CitizenIdentityMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.mp.api.entity.CitizenIdentity">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="id_no" property="idNo" />
<result column="age" property="age" />
<result column="sex" property="sex" />
<result column="address" property="address" />
<result column="phone_no" property="phoneNo" />
<result column="email" property="email" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, id_no, age, sex, address, phone_no, email
</sql>
MemberMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.mp.api.entity.Member">
<id column="id" property="id" />
<result column="member_name" property="memberName" />
<result column="password" property="password" />
<result column="member_no" property="memberNo" />
<result column="secret_key" property="secretKey" />
<result column="create_date" property="createDate" />
<result column="update_date" property="updateDate" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, member_name, password, member_no, secret_key, create_date, update_date
</sql>
application.properties
#\u6FC0\u6D3B\u5F00\u53D1\u73AF\u5883
spring.profiles.active=dev
#\u6570\u636E\u6E90
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/study?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.mp.api.entity
mybatis.configuration.map-underscore-to-camel-case=true
#json
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?><!-- 文件输出格式 -->
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level
[%thread] %c [%L] -| %msg%n" />
<!-- test文件路径 -->
<property name="TEST_FILE_PATH" value="d:/logs" />
<!-- pro文件路径 -->
<property name="PROD_FILE_PATH" value="/opt/logs" />
<!-- 开发环境 -->
<springProfile name="dev">
<!--控制台输出-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${PATTERN}</pattern>
</encoder>
</appender>
<logger name="com.lx.api" level="debug" />
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<!-- 测试环境 -->
<springProfile name="test">
<!--控制台输出-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${PATTERN}</pattern>
</encoder>
</appender>
<!-- 每天产生一个文件 -->
<appender name="TEST-FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${TEST_FILE_PATH}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="TEST-FILE" />
</root>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<appender name="PROD_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${PROD_FILE_PATH}/warn.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<root level="warn">
<appender-ref ref="PROD_FILE" />
</root>
</springProfile>
客户端
APIRequest.java
package com.mp.apiclient.client;
import cn.hutool.http.HttpRequest;
import com.mp.apiclient.util.VerifyUtil;
import java.util.HashMap;
import java.util.Map;
/**
-
api请求
-
@author zhuwenbin
-
@since 2019/3/2 12:20
*/
public class APIRequest {public static void main(String[] args) {
//请求参数
Map<String, Object> paramMap = new HashMap<>();
paramMap.put(“name”, “张三”);
paramMap.put(“idNo”, “238207237436119856”);
paramMap.put(“memberNo”, “sb_000002”);//签名 String sign = VerifyUtil.getSign(paramMap, "b0e65b8ca8d815d510487063ff76362d"); paramMap.put("sign", sign); //请求 String body = HttpRequest.post("http://localhost:8080/citizen-identity").form(paramMap).execute().body(); System.out.println(body);
}
}
VerifyUtil.java
package com.mp.apiclient.util;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.SecureUtil;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
- 验证工具
*/
public class VerifyUtil {
/**
* 检查签名
*
* @param paramVO
* @param secretKey
* @return boolean
*/
public static boolean checkSign(Object paramVO, String secretKey) {
//获取需要签名的参数集合
Map<String, Object> paramMap = getParamMap(paramVO);
//获取签名
String sign = getSign(paramMap, secretKey);
//比较
return sign.equals(paramMap.get("sign"));
}
/**
* 获取参数集合
*
* @param paramVO
* @return java.util.Map<java.lang.String, java.lang.Object>
*/
public static Map<String, Object> getParamMap(Object paramVO) {
//bean转map
Map<String, Object> paramMap = convertObjToMap(paramVO);
return paramMap;
}
/**
* 过滤并排序
*
* @param paramMap
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
public static Map<String, Object> filterAndSortMap(Map<String, Object> paramMap){
//过滤值为null的字段
paramMap = MapUtil.filter(paramMap, (Filter<Map.Entry<String, Object>>) stringObjectEntry -> !stringObjectEntry.getKey().equals("sign"));
//对上述参数key进行排序按照字典序(a-z),请注意byte[]类型的参数不参与排序和计算签名,
// 比如上传的文件;空值的参数也不参与排序和计算签名
paramMap = MapUtil.sort(paramMap, (str, str2) -> {
char[] chars = str.toCharArray();
char[] chars2 = str2.toCharArray();
int i = 0;
while (i < chars.length && i < chars2.length) {
if (chars[i] > chars2[i]) {
return 1;
} else if (chars[i] < chars2[i]) {
return -1;
} else {
i++;
}
}
if (i == chars.length) { //str到头
return -1;
}
if (i == chars2.length) { //str2到头
return 1;
}
return 0;
});
return paramMap;
}
/**
* 获取签名
*
* @param paramMap
* @param secretKey
* @return java.lang.String
*/
public static String getSign(Map<String, Object> paramMap, String secretKey) {
//过滤并排序
paramMap = filterAndSortMap(paramMap);
//以key+value方式拼装字符串
String paramStr = MapUtil.joinIgnoreNull(paramMap, "", "");
//加密
String sign = SecureUtil.md5(paramStr + secretKey);
return sign;
}
/**
* 获取签名
*
* @param paramVO
* @param secretKey
* @return java.lang.String
*/
public static String getSign(Object paramVO, String secretKey) {
//获取参数集合
Map<String, Object> paramMap = getParamMap(paramVO);
return getSign(paramMap, secretKey);
}
/**
* JavaBean对象转换为Map
*
* @param obj
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
public static Map<String, Object> convertObjToMap(Object obj){
Map<String,Object> reMap = new HashMap<String,Object>();
if (obj == null)
return null;
try {
Class<?> objClass = obj.getClass();
while(objClass != null){
Field[] fields = objClass.getDeclaredFields();
for(int i=0;i<fields.length;i++){
try {
Field f = objClass.getDeclaredField(fields[i].getName());
f.setAccessible(true);
Object o = f.get(obj);
reMap.put(fields[i].getName(), o);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
objClass = objClass.getSuperclass();
}
} catch (SecurityException e) {
e.printStackTrace();
}
return reMap;
}
}
运行结果
启动时需先启动服务端,再运行客户端的代码,结果如下
完毕,如有侵权,请联系本人删除