简单公民身份信息API开发

本文介绍了公民身份信息API的开发过程,包括总体设计、数据库设计、项目结构和代码实现。详细展示了Controller、Service、DAO层的代码示例,如CitizenIdentityApiContriller、MemberServiceImpl、CitizenIdentityServiceImpl等,以及验证工具类VerifyUtil的使用。通过这个API,可以进行身份逻辑验证并返回查询结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总体设计

数据库设计

公民身份信息数据表
此表主要签名

项目结构

一个服务器,一个客户端

服务器项目结构

服务器项目结构

客户端项目结构

客户端项目结构

项目代码

controller代码
CitizenIdentityApiContriller.java
  1. **** 身份逻辑验证之后,会返回相应的查询结构
  2. /此为本人自己查阅资料的劳动成果,转载请注明链接/
    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
  1. ****;
  2. 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
  1. 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
  1. 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
  1. 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
  1. 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
  1. 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;
}

}

运行结果

启动时需先启动服务端,再运行客户端的代码,结果如下
运行结果图
完毕,如有侵权,请联系本人删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值