回撥機制引發的呼叫思考
介面被呼叫的時候會自動呼叫他的實現類(回撥機制)
至於父類子類,子類複寫了父類的方法,可以單獨呼叫父類的方法,也單獨呼叫子類的這個方法
父類的方法父類有一份(super),子類有一份(this),通過子類呼叫父類方法這個this就是子類本身,
單獨呼叫父類用super,那麼封裝在父類的方法直接用this.呼叫即可之後哪個子類呼叫就是誰
父:
package com.esteel.settlement.pa.packet;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* 平安對接介面的基類 用於對資料格式的轉換
*
* @author zhangxiuzhi
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class PaPacket implements Serializable {
public static String RMB = "RMB";
public static String SUCCESS = "000000";
public static SimpleDateFormat SFDate = new SimpleDateFormat("yyyyMMdd");
DecimalFormat df = new DecimalFormat("######0.00");
Charset charset = Charset.forName("GBK");
// 報文請求型別 請求
public static String REQUEST = "01";
// 報文請求型別 請求
public static String RESPONSE = "02";
// 保留域
@XmlElement(name = "Reserve")
private String reserve;
@XmlTransient
protected PacketHeader packetHeader = new PacketHeader();
@XmlTransient
protected BusinessHeader buisinessHeader = new BusinessHeader();
// 交易網程式碼
@XmlTransient
@NotEmpty
private String qydm;
// 交易網流水號
@XmlElement(name = "ThirdLogNo")
@Length(max = 20)
@NotEmpty
private String thirdLogNo;
// 服務型別
@XmlTransient
@NotEmpty
@Pattern(regexp = "01|02")
private String servType;
// 交易時間
@XmlTransient
@NotNull
@DateTimeFormat(pattern = "yyyyMMdd")
private Date transDate;
// 操作員號
@XmlTransient
private String counterId;
// 交易碼
@XmlTransient
@NotNull
@Length(min = 1, max = 4)
private String tranFunc;
public PaPacket(){
this.setTranFunc(tranFunc());
}
protected abstract String tranFunc();
public String getReserve() {
return reserve;
}
public void setReserve(String reserve) {
this.reserve = reserve;
}
public String getQydm() {
return qydm;
}
public void setQydm(String qydm) {
this.qydm = qydm;
// 交易網程式碼
this.packetHeader.setQydm(this.getQydm());
this.buisinessHeader.setQydm(this.qydm);
}
public String getThirdLogNo() {
return thirdLogNo;
}
public void setThirdLogNo(String thirdLogNo) {
this.thirdLogNo = thirdLogNo;
// 請求系統流水號
this.packetHeader.setThirdLogNo(this.getThirdLogNo());
this.buisinessHeader.setThirdLogNo(this.getThirdLogNo());
}
public String getServType() {
return servType;
}
public void setServType(String servType) {
this.servType = servType;
// 服務型別 01 請求 02 應答
this.packetHeader.setServType(this.getServType());
this.buisinessHeader.setServType(this.getServType());
}
public Date getTransDate() {
return transDate;
}
public void setTransDate(Date transDate) {
this.transDate = transDate;
// 交易時間
this.packetHeader.setTranDate(this.getTransDate());
this.buisinessHeader.setTranDate(this.getTransDate());
}
public String getCounterId() {
return counterId;
}
public void setCounterId(String counterId) {
this.counterId = counterId;
// 操作員號
this.packetHeader.setCounterId(counterId);
this.buisinessHeader.setCounterId(counterId);
}
public String getTranFunc() {
return tranFunc;
}
public void setTranFunc(String tranFunc) {
this.tranFunc = tranFunc;
this.buisinessHeader.setTranFunc(tranFunc);
}
public void setRspCode(String rspCode) {
this.buisinessHeader.setRspCode(rspCode);
this.packetHeader.setRspCode(rspCode);
}
public String getRspCode() {
return this.buisinessHeader.getRspCode();
}
public void setRspMsg(String rspMsg) {
this.buisinessHeader.setRspMsg(rspMsg);
this.packetHeader.setRspMsg(rspMsg);
}
public String getRspMsg() {
return this.buisinessHeader.getRspMsg();
}
/**
* 解析報文頭
*
* @param packetHeader
*/
private void analyzePacketHeader(byte[] packetHeader) {
this.packetHeader.analyze(packetHeader);
}
/**
* 解析業務報文頭
*
* @param businesserHeader
*/
private void analyzeBusinsserHeader(byte[] businesserHeader) {
this.buisinessHeader.analyze(businesserHeader);
}
/**
* 將報文編組成可以傳送的字串報文
*
* @return
*/
public String marshal() {
Assert.notNull(this.packetHeader);
Assert.notNull(this.buisinessHeader);
// 業務報問題
String data = this.getString();
// 設定報文中的公共的值
// 交易網程式碼
this.packetHeader.setQydm(this.getQydm());
this.buisinessHeader.setQydm(this.qydm);
// 請求系統流水號
this.packetHeader.setThirdLogNo(this.getThirdLogNo());
this.buisinessHeader.setThirdLogNo(this.getThirdLogNo());
// 服務型別 01 請求 02 應答
this.packetHeader.setServType(this.getServType());
this.buisinessHeader.setServType(this.getServType());
// 交易時間
this.packetHeader.setTranDate(this.getTransDate());
this.buisinessHeader.setTranDate(this.getTransDate());
// 設定報文長度
this.packetHeader.setPacketLength(BusinessHeader.HEADERLEN + data.getBytes(charset).length);
this.buisinessHeader.setLength(data.getBytes(charset).length);
// 操作員號
this.packetHeader.setCounterId(this.getCounterId());
this.buisinessHeader.setCounterId(this.getCounterId());
// 設定操作程式碼
// this.buisinessHeader.setTranFunc(this.getTranFunc());
byte[] cs = this.packetHeader.getPacketHeader();
StringBuilder sb = new StringBuilder();
sb.append(new String(cs, charset));
sb.append(new String(this.buisinessHeader.getBusinessHeader(), charset));
sb.append(data);
return sb.toString();
}
/**
* 生成需要的報文字串
*
* @return
*/
public String getString() {
StringBuilder sb = new StringBuilder();
try {
for (String fName : this.order()) {
Object obj = getValue(fName);
if (obj == null) {
sb.append("");
}
if (obj instanceof String) {
sb.append((String) obj);
}
if (obj instanceof Integer) {
sb.append(((Integer) obj).intValue());
}
if (obj instanceof Long) {
sb.append(((Long) obj).intValue());
}
if (obj instanceof Double) {
sb.append(df.format((Double) obj));
}
if (obj instanceof Date) {
sb.append(SFDate.format(obj));
}
sb.append("&");
}
} catch (NoSuchFieldException | SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
// sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
/**
* 取得屬性名字時 用於獲得屬性值
*
* @param fName
* @return
* @throws NoSuchFieldException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private Object getValue(String fName) throws NoSuchFieldException, SecurityException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
fName = fName.substring(0, 1).toUpperCase() + fName.substring(1);
Method method = this.getClass().getMethod("get" + fName);
Assert.notNull(method);
return method.invoke(this);
}
/**
* 設定物件的值
*
* @param fName
* @param value
* @throws NoSuchMethodException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws ParseException
*/
private void setValue(Object obj,String fieldName, List<String> values)
throws NoSuchMethodException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ParseException {
if (values == null||values.isEmpty()) {
return;
}
//用於判斷是否去掉values中的第一個元素,預設情況刪除,但在處理遞迴呼叫的時候 不刪除
boolean isMove=true;
String value = values.get(0);
String fName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Method get = obj.getClass().getMethod("get" + fName);
Method method = obj.getClass().getMethod("set" + fName, get.getReturnType());
Assert.notNull(method);
switch (get.getReturnType().getSimpleName()) {
case "String": {
method.invoke(obj, value);
break;
}
case "int":
case "Integer": {
if (value.indexOf(".") > -1) {
value = value.substring(0, value.indexOf("."));
}
method.invoke(obj, new Integer(value));
break;
}
case "double":
case "Double": {
method.invoke(obj, df.parse(value));
break;
}
case "long":
case "Long": {
if (value.indexOf(".") > -1) {
value = value.substring(0, value.indexOf("."));
}
method.invoke(obj, new Long(value));
break;
}
case "Date": {
try{
Date date = SFDate.parse(value);
method.invoke(obj, date);
}catch(Exception ex){
}
break;
}
case "List":{
Field field = obj.getClass().getDeclaredField(fieldName);
ArraySizeMethod arraySizeMethod = field.getAnnotation(ArraySizeMethod.class);
//迴圈記錄的條數 預設1
int numSize = 1;
if (arraySizeMethod!=null){
String sizeMethodName = arraySizeMethod.value();
if (!StringUtils.isEmpty(sizeMethodName)){
Method sizeMethod = obj.getClass().getMethod(sizeMethodName);
numSize = ((int) sizeMethod.invoke(obj));
}
}
List<ResultArray> list = new ArrayList<ResultArray>();
Type fc = field.getGenericType();
if (fc instanceof ParameterizedType){
ParameterizedType pt = (ParameterizedType) fc;
Class<?> genericClazz = (Class<?>)pt.getActualTypeArguments()[0];
try {
ResultArray result = (ResultArray) genericClazz.newInstance();
String[] orders = result.order();
for (int i=0;i<numSize;i++){
for (String str : orders){
setValue(result,str,values);
}
list.add(result);
result = (ResultArray) genericClazz.newInstance();
}
} catch (InstantiationException e) {
e.printStackTrace();
}
}
method.invoke(obj, list);
isMove = false;
break;
}
default:{
System.out.println(get.getReturnType().getSimpleName());
}
}
//去掉佇列中的第一個元素
if (isMove){
values.remove(0);
}
}
/**
* 根據各處的
*
* @param str
*/
public void analyze(String packetStr) {
byte[] src = packetStr.getBytes(charset);
Assert.isTrue(src.length > 344);
byte[] ph = new byte[222];
byte[] bh = new byte[122];
System.arraycopy(src, 0, ph, 0, ph.length);
System.arraycopy(src, 222, bh, 0, bh.length);
this.analyzePacketHeader(ph);
this.analyzeBusinsserHeader(bh);
byte[] data = new byte[src.length - 344];
System.arraycopy(src, 344, data, 0, data.length);
String str = new String(data, charset);
// 將標頭檔案中的屬性值設定到公共報文中
this.setCounterId(this.buisinessHeader.getCounterId());
this.setQydm(this.buisinessHeader.getQydm());
this.setTransDate(this.buisinessHeader.getTranDate());
this.setServType(this.buisinessHeader.getServType());
this.setThirdLogNo(this.buisinessHeader.getThirdLogNo());
this.setTranFunc(this.buisinessHeader.getTranFunc());
String[] strs = str.split("&");
List<String> list = new LinkedList<String>();
list.addAll(Arrays.asList(strs));
String[] fNames = this.order();//////////////////////////////////////誰呼叫就指誰
String[] values = new String[fNames.length];
System.arraycopy(strs, 0, values, 0, values.length > strs.length ? strs.length : values.length);
// Assert.isTrue(fNames.length >= strs.length);
//int index = 0;
try {
for (String fname : fNames) {
//setValue(fname, values[index]);
setValue(this,fname, list);
//index++;
}
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException | InvocationTargetException | ParseException e) {
e.printStackTrace();
}
}
/**
* 返回報文的生成順序
*
* @return
*/
protected abstract String[] order();
}
子類:
@Test
public void testAnsyze(){
String str = "1&2&3&4&5&6&7&8&9&10&11&12&13&14&15&";
BP1303 bp = new BP1303();
bp.analyze(str);
System.out.println(bp.getString());
}
子類覆寫父類:
@Override
protected String[] order() {
String[] objs = {"funcFlag","supAcctId","custAcctId","custName","thirdCustId","idType","idCode","relatedAcctId","acctFlag","tranType","acctName","bankCode","bankName","oldRelatedAcctId","reserve"};
return objs;
}
==================
回撥機制在系統配置的時候體現:
public class CustomUserDetailsService
implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
@Override
public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
System.out.println("當前的使用者名稱是:"+token.getName());
/*這裡我為了方便,就直接返回一個使用者資訊,實際當中這裡修改為查詢資料庫或者呼叫服務什麼的來獲取使用者資訊*/
UserInfo userInfo = new UserInfo();
userInfo.setUsername(token.getName());
userInfo.setName(token.getName());
Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();
AuthorityInfo authorityInfo = new AuthorityInfo("TEST");
authorities.add(authorityInfo);
userInfo.setAuthorities(authorities);
return userInfo;
}
@Bean
public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService() {
return new CustomUserDetailsService();
}