S7 更新了一个大版本,待测试
This commit is contained in:
부모
5b2c38770d
커밋
829c9ce9ca
14
pom.xml
14
pom.xml
@ -80,11 +80,19 @@
|
||||
</dependency>
|
||||
<!-- websocket 结束 -->
|
||||
|
||||
<!-- retry 结束 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
<version>1.2.2.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- retry 结束 -->
|
||||
|
||||
<!-- fastjson 开始 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.78</version>
|
||||
<version>2.0.21</version>
|
||||
</dependency>
|
||||
<!-- fastjson 结束 -->
|
||||
<!-- hutool 开始 -->
|
||||
@ -201,6 +209,10 @@
|
||||
<artifactId>influxdb-client-java</artifactId>
|
||||
<version>6.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- influx end -->
|
||||
|
||||
|
@ -30,7 +30,7 @@ public interface S7Connector extends Closeable {
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
public byte[] read(DaveArea area, int areaNumber, int bytes, int offset) throws Exception;
|
||||
public byte[] read(DaveArea area, int areaNumber, int bytes, int offset);
|
||||
|
||||
/**
|
||||
* Reads an area 读需要bit 位置的 变量(其实就是 read bool变量的时候调用这个方法。)
|
||||
@ -41,7 +41,7 @@ public interface S7Connector extends Closeable {
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
public byte[] read(DaveArea area, int areaNumber, int bytes, int offset, int bitOffset, TransportSize transportSize) throws Exception;
|
||||
public byte[] read(DaveArea area, int areaNumber, int bytes, int offset, int bitOffset, TransportSize transportSize);
|
||||
/**
|
||||
* Writes an area
|
||||
* desc : 只要未抛出异常,都是 操作成功的
|
||||
@ -50,9 +50,9 @@ public interface S7Connector extends Closeable {
|
||||
* @param offset
|
||||
* @param buffer
|
||||
*/
|
||||
public void write(DaveArea area, int areaNumber, int offset, byte[] buffer) throws Exception;
|
||||
public void write(DaveArea area, int areaNumber, int offset, byte[] buffer);
|
||||
|
||||
//如果 bitOffset 没有 那么就填0
|
||||
public void write(DaveArea area, int areaNumber, int byteOffset, int bitOffset, byte[] buffer, PlcVar var) throws Exception;
|
||||
public void write(DaveArea area, int areaNumber, int byteOffset, int bitOffset, byte[] buffer, PlcVar var);
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package com.qgs.dc.s7.my.s7connector.api.utils;
|
||||
* @DATE: 2021/12/16 9:08
|
||||
*/
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7ParseDataException;
|
||||
import com.qgs.dc.s7.my.s7connector.utils.CommonFunctions;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
@ -47,9 +48,14 @@ public class ByteUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String addDate(String timeParam, Long day) throws ParseException {
|
||||
public static String addDate(String timeParam, Long day) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式
|
||||
Date date = dateFormat.parse(timeParam); // 指定日期
|
||||
Date date = null;
|
||||
try {
|
||||
date = dateFormat.parse(timeParam); // 指定日期
|
||||
}catch (Exception e){
|
||||
throw new S7ParseDataException("ByteUtils.addDate error:", e);
|
||||
}
|
||||
|
||||
long time = date.getTime(); // 得到指定日期的毫秒数
|
||||
day = day * 24 * 60 * 60 * 1000; // 要加上的天数转换成毫秒数
|
||||
@ -175,13 +181,13 @@ public class ByteUtils {
|
||||
// String ascii = new String(b, Charset.forName("UTF-8"));
|
||||
// return ascii;
|
||||
// }
|
||||
public static Character toChar(byte[] b) throws UnsupportedEncodingException {
|
||||
public static Character toChar(byte[] b) {
|
||||
if(b.length==1){
|
||||
return toChar(b[0]);
|
||||
}
|
||||
return byteToChar(b);
|
||||
}
|
||||
public static Character toChar(byte b) throws UnsupportedEncodingException {
|
||||
public static Character toChar(byte b){
|
||||
return byteToChar(b);
|
||||
}
|
||||
// public static String toChar(byte b) throws UnsupportedEncodingException {
|
||||
@ -194,7 +200,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* return null 代表返回传入参数不正确str 取的length太小
|
||||
* */
|
||||
public static String toStr(byte[] b) throws UnsupportedEncodingException {
|
||||
public static String toStr(byte[] b) {
|
||||
Integer length = Byte.toUnsignedInt(b[1]);
|
||||
if(length>(b.length-2)){
|
||||
return null;
|
||||
@ -207,7 +213,7 @@ public class ByteUtils {
|
||||
// String s = new String(content);
|
||||
return ascii;
|
||||
}
|
||||
public static String[] toStrArray(byte[] b,Integer length,Integer strSize) throws UnsupportedEncodingException {
|
||||
public static String[] toStrArray(byte[] b,Integer length,Integer strSize) {
|
||||
String[] res = new String[length];
|
||||
strSize+=2;
|
||||
for(int i=0;i<length;i++){
|
||||
@ -275,7 +281,7 @@ public class ByteUtils {
|
||||
return b;
|
||||
}
|
||||
|
||||
public static List<Boolean> toBoolArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Boolean> toBoolArray(byte[] b) {
|
||||
List<Boolean> res = new ArrayList<>();
|
||||
for(int i=0;i<b.length;i++){
|
||||
boolean[] booleanArray = getBooleanArray(b[i], true);
|
||||
@ -301,7 +307,7 @@ public class ByteUtils {
|
||||
|
||||
|
||||
//bool array to byte array
|
||||
public static byte[] toByteArray(boolean[] b) throws UnsupportedEncodingException {
|
||||
public static byte[] toByteArray(boolean[] b){
|
||||
Integer byteLength = CommonFunctions.exactDivision(b.length, 8);
|
||||
byte[] res = new byte[byteLength];
|
||||
Queue<Boolean> queue = new LinkedList<Boolean>();
|
||||
@ -347,7 +353,7 @@ public class ByteUtils {
|
||||
// return res;
|
||||
// }
|
||||
|
||||
public static List<Byte> toByteArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Byte> toByteArray(byte[] b) {
|
||||
List<Byte> res = new ArrayList<>();
|
||||
for(int i=0;i<b.length;i++){
|
||||
res.add((b[i]));
|
||||
@ -355,7 +361,7 @@ public class ByteUtils {
|
||||
return res;
|
||||
}
|
||||
|
||||
public static List<Character> toCharArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Character> toCharArray(byte[] b) {
|
||||
List<Character> res = new ArrayList<>();
|
||||
for(int i=0;i<b.length;i++){
|
||||
res.add(toChar(b[i]));
|
||||
@ -367,7 +373,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* 默认:word => 有符号的整形
|
||||
* */
|
||||
public static List<Integer> toWordArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toWordArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+2)<=b.length){
|
||||
@ -383,7 +389,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* 默认:dword => 有符号的整形
|
||||
* */
|
||||
public static List<Integer> toDWordArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toDWordArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+4)<=b.length){
|
||||
@ -444,7 +450,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* USInt 无符号整形 1个字节 =》 Integer
|
||||
* */
|
||||
public static List<Integer> toUSIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toUSIntArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
for(int i=0;i<b.length;i++){
|
||||
res.add(toUInt(b[i]));
|
||||
@ -454,7 +460,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* UInt 无符号整形 2个字节 =》 Integer
|
||||
* */
|
||||
public static List<Integer> toUIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toUIntArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+2)<=b.length){
|
||||
@ -468,7 +474,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* UDInt 无符号整形 4个字节 =》 Long
|
||||
* */
|
||||
public static List<Long> toUDIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Long> toUDIntArray(byte[] b) {
|
||||
List<Long> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+4)<=b.length){
|
||||
@ -483,7 +489,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* SInt 无符号整形 1个字节 =》 Integer
|
||||
* */
|
||||
public static List<Integer> toSIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toSIntArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
for(int i=0;i<b.length;i++){
|
||||
res.add(toInt(b[i]));
|
||||
@ -493,7 +499,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* Int 无符号整形 2个字节 =》 Integer
|
||||
* */
|
||||
public static List<Integer> toIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toIntArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+2)<=b.length){
|
||||
@ -507,7 +513,7 @@ public class ByteUtils {
|
||||
/**
|
||||
* DInt 无符号整形 4个字节 =》 Integer
|
||||
* */
|
||||
public static List<Integer> toDIntArray(byte[] b) throws UnsupportedEncodingException {
|
||||
public static List<Integer> toDIntArray(byte[] b) {
|
||||
List<Integer> res = new ArrayList<>();
|
||||
int i=0;
|
||||
while ((i+4)<=b.length){
|
||||
|
@ -0,0 +1,355 @@
|
||||
package com.qgs.dc.s7.my.s7connector.enmuc;
|
||||
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.api.DaveArea;
|
||||
import com.qgs.dc.s7.my.s7connector.api.S7Connector;
|
||||
import com.qgs.dc.s7.my.s7connector.api.factory.S7ConnectorFactory;
|
||||
import com.qgs.dc.s7.my.s7connector.api.utils.ByteUtils;
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7Exception;
|
||||
import com.qgs.dc.s7.my.s7connector.type.PlcVar;
|
||||
import com.qgs.dc.s7.my.s7connector.utils.CommonFunctions;
|
||||
import com.qgs.dc.s7.retry.S7RetryTemplate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2022/1/15 13:01
|
||||
*/
|
||||
public enum S7ClientNew {
|
||||
//TODO 步骤1 这里是配置多PLC 的,,,有多个plc 就在这里配置一个枚举类
|
||||
//1500 西门子200smart、1200、1500默认的 机架号=0 槽位号=1; 300/400 默认的 机架-0 插槽-2
|
||||
S7_1200("192.168.0.52",0,1,1,PlcVarActual.HeartBeatFor1200),
|
||||
|
||||
S7_1500("192.168.0.51",0,1,1,PlcVarActual.HeartBeat),
|
||||
//1500 机架-0 插槽-1
|
||||
//后续 在这里扩展 多PLC应用。
|
||||
;
|
||||
private String host;
|
||||
//默认 0 机架号
|
||||
private Integer rack;
|
||||
//默认 0
|
||||
private Integer slot;
|
||||
|
||||
//心跳变量,如果plc没有让电控的人加一个,这个是必填的
|
||||
private PlcVarActual heartBeat;
|
||||
|
||||
private List<S7Connector> connections;
|
||||
//coreSize 是线程池的大小
|
||||
private Integer coreSize;
|
||||
//pickOne 就是一个初始化 的轮询取余值
|
||||
private int pickOne;
|
||||
private static final Logger logger = LoggerFactory.getLogger(S7ClientNew.class);
|
||||
|
||||
|
||||
|
||||
|
||||
//coreSize 是线程池的数量
|
||||
S7ClientNew(String host, Integer rack, Integer slot, Integer coreSize, PlcVarActual heartBeat){
|
||||
this.host = host;
|
||||
this.rack = rack;
|
||||
this.slot = slot;
|
||||
this.pickOne = 0;
|
||||
|
||||
this.coreSize = coreSize;
|
||||
|
||||
connections = new ArrayList<>();
|
||||
connectionPool();
|
||||
|
||||
}
|
||||
|
||||
public String getHost(){
|
||||
return this.host;
|
||||
}
|
||||
|
||||
/**
|
||||
* PlcVar(byte[]) 转 java对象 对照表
|
||||
* 单体变量
|
||||
* Bool ===> Boolean
|
||||
* LREAL ===> Double
|
||||
* REAL ===> Float
|
||||
* DATE ===> String(yyyy-MM-dd 这种形式的类型)
|
||||
* DTL ===> String("年-月-日-工作日-时-分-秒" 这种格式)
|
||||
* TIME ===> Integer(单位 ms)
|
||||
* USINT ===> Integer
|
||||
* SINT ===> Integer
|
||||
* UINT ===> Integer
|
||||
* INT ===> Integer
|
||||
* DINT ===> Integer
|
||||
* UINT ===> Long
|
||||
* Byte ===> Integer(有符号)(默认)
|
||||
* Integer(无符号)(后续扩展)
|
||||
* Char ===> Character
|
||||
* WChar ===> Character
|
||||
* String ===> String (特殊)
|
||||
|
||||
|
||||
* 数组变量
|
||||
* BoolArray ===> List<Boolean>
|
||||
* ByteArray ===> List<Byte>
|
||||
* WordArray ===> List<Integer>
|
||||
* DWordArray ===> List<Integer>
|
||||
* CharArray ===> List<Character>
|
||||
* SIntArray ===> List<Integer>
|
||||
* IntArray ===> List<Integer>
|
||||
* DIntArray ===> List<Integer>
|
||||
* UIntArray ===> List<Integer>
|
||||
* USIntArray ===> List<Integer>
|
||||
* UDIntArray ===> List<Long>
|
||||
* StringArray ===> String[] (特殊)
|
||||
*
|
||||
* 如果返回null,就代表出现了异常,并且尝试了 retryMax 次数,并且尝试重置连接
|
||||
* */
|
||||
public Object read(DaveArea area, Integer areaNumber, Integer byteOffset, Integer bitOffset, Integer length, Integer strSizes, PlcVar type) {
|
||||
S7Connector connector = getConnector();
|
||||
return S7RetryTemplate.getInstance().execute(
|
||||
context -> {
|
||||
//String 类型比较特殊。 String[] 也是同理,Sring数组里面的子项 也是有两个字节的 readBytes。
|
||||
if(type.equals(PlcVar.STRING)){
|
||||
Integer readBytes = 2;
|
||||
byte[] read = connector.read(
|
||||
area,
|
||||
areaNumber,
|
||||
readBytes,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
type.getTransportSize()
|
||||
);
|
||||
|
||||
Integer allLength = Integer.valueOf(read[1])+2;
|
||||
byte[] readF = connector.read(
|
||||
area,
|
||||
areaNumber,
|
||||
allLength,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
type.getTransportSize()
|
||||
);
|
||||
return type.toObject(readF);
|
||||
}else if(type.equals(PlcVar.BOOL_Array)){
|
||||
|
||||
byte[] read = connector.read(
|
||||
area,
|
||||
areaNumber,
|
||||
CommonFunctions.exactDivision(length,8),
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
type.getTransportSize()
|
||||
);
|
||||
List<Boolean> booleans = ByteUtils.toBoolArray(read);
|
||||
List<Boolean> res = new ArrayList<Boolean>();
|
||||
for(int i=0;i<length;i++){
|
||||
res.add(i,booleans.get(i));
|
||||
}
|
||||
return res;
|
||||
}else if(type.equals(PlcVar.STRING_Array)){
|
||||
Integer arrayLength = length;
|
||||
Integer strSize = strSizes;
|
||||
|
||||
byte[] read = connector.read(
|
||||
area,
|
||||
areaNumber,
|
||||
arrayLength*(strSize+2),
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
type.getTransportSize()
|
||||
);
|
||||
return ByteUtils.toStrArray(read, arrayLength, strSize);
|
||||
}else {
|
||||
Integer readBytes = type.getTransportSize().getSizeInBytes() * length;
|
||||
byte[] read = connector.read(
|
||||
area,
|
||||
areaNumber,
|
||||
readBytes,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
type.getTransportSize()
|
||||
);
|
||||
return type.toObject(read);
|
||||
}
|
||||
},
|
||||
context -> {
|
||||
logger.info("S7-Retry : 已达到最大重试次数: "+S7RetryTemplate.getMaxRetryTimes()+", 现在尝试重新连接");
|
||||
if(replaceConnector(connector)==1){
|
||||
logger.info("S7-Retry-Read 现在恢复成功,创建新connection成功");
|
||||
return null;
|
||||
}else {
|
||||
logger.info("S7-Retry-Read 现在恢复失败,创建新connection失败");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* eg :
|
||||
* Object newValue = Boolean.FALSE
|
||||
* s7Service.write(PlcVarActual.HeartBeat, newValue, S7Client.S7_1200);
|
||||
*
|
||||
* PlcVar(byte[]) 转 java对象 对照表
|
||||
* 单体变量
|
||||
* Bool ===> Object newValue = Boolean.FALSE
|
||||
* LREAL ===> Object newValue = Boolean.FALSE
|
||||
* REAL ===> Object newValue = Boolean.FALSE
|
||||
* DATE ===> 暂时没需求(有问题找我)
|
||||
* DTL ===> 暂时没需求(有问题找我)
|
||||
* TIME ===> 暂时没需求(有问题找我)
|
||||
* USINT ===> Object newValue = new Integer(1)
|
||||
* SINT ===> Object newValue = new Integer(1)
|
||||
* UINT ===> Object newValue = new Integer(1)
|
||||
* INT ===> Object newValue = new Integer(1)
|
||||
* DINT ===> Object newValue = new Integer(1)
|
||||
* UINT ===> Object newValue = new Integer(1)
|
||||
* Byte ===> Object newValue = 0x11
|
||||
*
|
||||
* Char ===> Object newValue = 'a'
|
||||
* WChar ===> Object newValue = '菜'
|
||||
* String ===> Object newValue = '你好啊' (特殊)
|
||||
|
||||
|
||||
* 数组变量
|
||||
* 注意:在write的时候,你write的数量 一定要和 plc中存在的数量一一对应
|
||||
* BoolArray ===> boolean[] booleanArray = new boolean[2]; .... 赋予值
|
||||
* ByteArray ===> byte[] write_byteArrays = new byte[2];
|
||||
* WordArray ===> short[] shortArrays_content = new short[2];
|
||||
* DWordArray ===> int[] intArrays_content = new int[2];
|
||||
* CharArray ===> char[] charArrays_content = new char[2];
|
||||
* SIntArray ===> int[] sintArrays_content = new int[2];
|
||||
* IntArray ===> int[] iintArrays_content = new int[2];
|
||||
* DIntArray ===> int[] dintArrays_content = new int[2];
|
||||
* UIntArray ===> int[] uintArrays_content = new int[3];
|
||||
* USIntArray ===> int[] usintArrays_content = new int[3];
|
||||
* UDIntArray ===> int[] udintArrays_content = new int[3];
|
||||
* StringArray ===> String[] stringArrays_content = new String[3];
|
||||
* //如果有其他数据类型 这里没有找我扩展
|
||||
*
|
||||
*
|
||||
* */
|
||||
public void write(DaveArea area, Integer areaNumber, Integer byteOffset, Integer bitOffset,Integer strSize, PlcVar type, Object newValue) throws Exception {
|
||||
S7Connector connector = getConnector();
|
||||
|
||||
S7RetryTemplate.getInstance().execute(
|
||||
context -> {
|
||||
//String 类型比较特殊。 String[] 也是同理,Sring数组里面的子项 也是有两个字节的 readBytes。
|
||||
if(type.equals(PlcVar.STRING)){
|
||||
connector.write(
|
||||
area,
|
||||
areaNumber,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
ByteUtils.strToBytes(newValue.toString(), strSize),
|
||||
type
|
||||
);
|
||||
}else if(type.equals(PlcVar.BOOL_Array)){
|
||||
connector.write(
|
||||
area,
|
||||
areaNumber,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
ByteUtils.toByteArray((boolean[])newValue),
|
||||
type
|
||||
);
|
||||
}else if(type.equals(PlcVar.STRING_Array)){
|
||||
//todo here 检查 read write service
|
||||
connector.write(
|
||||
area,
|
||||
areaNumber,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
ByteUtils.strArrayToBytes((String[])newValue, strSize),
|
||||
type
|
||||
);
|
||||
}else {
|
||||
byte[] bytes = type.toBytes(newValue);
|
||||
connector.write(
|
||||
area,
|
||||
areaNumber,
|
||||
byteOffset,
|
||||
bitOffset,
|
||||
bytes,
|
||||
type
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
context -> {
|
||||
logger.info("S7-Retry-Write : 已达到最大重试次数: "+S7RetryTemplate.getMaxRetryTimes()+", 现在尝试重新连接");
|
||||
if( replaceConnector(connector) == 1 ){
|
||||
logger.info("S7-Retry-Write 现在恢复成功,创建新connection成功");
|
||||
return null;
|
||||
}else {
|
||||
logger.info("S7-Retry-Write 现在恢复失败,创建新connection失败");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc: 传入的connection 是需要被替换的
|
||||
* return:
|
||||
* 1 代表替换成功
|
||||
* -1 代表替换失败(创建connection失败,原因:出现异常.原来的connection也被舍弃掉了)
|
||||
* */
|
||||
private Integer replaceConnector(S7Connector oldOne){
|
||||
connections.remove(oldOne);
|
||||
S7Connector connect = connect(host, rack, slot);
|
||||
if(connect == null){
|
||||
return -1;
|
||||
}else {
|
||||
connections.add(connect);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public S7Connector getConnector() {
|
||||
int size = connections.size();
|
||||
S7Connector s7Connector = connections.get((pickOne + size) % size);
|
||||
pickOne+=1;
|
||||
pickOne = (pickOne)%size;
|
||||
return s7Connector;
|
||||
}
|
||||
|
||||
private S7Connector connect(String host,Integer rack,Integer slot ){
|
||||
try {
|
||||
S7Connector connector = S7ConnectorFactory
|
||||
.buildTCPConnector()
|
||||
.withHost(host)
|
||||
.withRack(rack) //optional rack 是机架号
|
||||
.withSlot(slot) //optional slot 是插槽号
|
||||
.build();
|
||||
return connector;
|
||||
}catch (S7Exception e){
|
||||
// logger.info("创建S7Connector 连接失败,原因:"+e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void resetConnetctions(){
|
||||
this.connections = new ArrayList<S7Connector>();
|
||||
connectionPool();
|
||||
}
|
||||
|
||||
private void connectionPool(){
|
||||
for(int i=0;i<coreSize;i++){
|
||||
S7Connector connect = connect(host, rack, slot);
|
||||
if(connect!=null){
|
||||
connections.add(connect);
|
||||
}
|
||||
}
|
||||
//todo 在plc上新增一个 变量来解决 心跳问题 okok
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2016 S7connector members (github.com/s7connector)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package com.qgs.dc.s7.my.s7connector.exception;
|
||||
|
||||
/**
|
||||
* The Class S7Exception is an exception related to S7 Communication
|
||||
*/
|
||||
public final class S7CheckResultException extends RuntimeException {
|
||||
|
||||
/** The Constant serialVersionUID. */
|
||||
private static final long serialVersionUID = -4761415733559374116L;
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*/
|
||||
public S7CheckResultException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public S7CheckResultException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7CheckResultException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7CheckResultException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2016 S7connector members (github.com/s7connector)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package com.qgs.dc.s7.my.s7connector.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The Class S7IOException is an exception related to S7 Communication
|
||||
*/
|
||||
public final class S7IOException extends RuntimeException {
|
||||
|
||||
/** The Constant serialVersionUID. */
|
||||
private static final long serialVersionUID = -4761415733559374116L;
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*/
|
||||
public S7IOException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public S7IOException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7IOException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7IOException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2016 S7connector members (github.com/s7connector)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package com.qgs.dc.s7.my.s7connector.exception;
|
||||
|
||||
/**
|
||||
* The Class S7Exception is an exception related to S7 Communication
|
||||
*/
|
||||
public final class S7ParseDataException extends RuntimeException {
|
||||
|
||||
/** The Constant serialVersionUID. */
|
||||
private static final long serialVersionUID = -4761415733559374116L;
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*/
|
||||
public S7ParseDataException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public S7ParseDataException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7ParseDataException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new s7 exception.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public S7ParseDataException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,8 @@ package com.qgs.dc.s7.my.s7connector.impl;
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.api.DaveArea;
|
||||
import com.qgs.dc.s7.my.s7connector.api.S7Connector;
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7CheckResultException;
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7Exception;
|
||||
import com.qgs.dc.s7.my.s7connector.impl.nodave.Nodave;
|
||||
import com.qgs.dc.s7.my.s7connector.impl.nodave.S7Connection;
|
||||
import com.qgs.dc.s7.my.s7connector.type.PlcVar;
|
||||
@ -32,7 +34,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
|
||||
/** The Constant MAX_SIZE. */
|
||||
//private static final int MAX_SIZE = 96; //原版96 ;; ioserver 127 ;;
|
||||
private static final int MAX_SIZE = 212; //S7-1200-maxReadBytes = 212 ;; S7-1200-maxReadBytes = 452
|
||||
private static final int MAX_SIZE = 212; //S7-1200-maxReadBytes = 212 ;; S7-1500-maxReadBytes = 452
|
||||
|
||||
/** The Constant PROPERTY_AREA. */
|
||||
public static final String PROPERTY_AREA = "area";
|
||||
@ -52,11 +54,11 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
* @param libnodaveResult
|
||||
* the libnodave result
|
||||
*/
|
||||
public static void checkResult(final int libnodaveResult) throws Exception {
|
||||
public static void checkResult(final int libnodaveResult) {
|
||||
if (libnodaveResult != Nodave.RESULT_OK) {
|
||||
final String msg = Nodave.strerror(libnodaveResult);
|
||||
// throw new IllegalArgumentException("Result: " + msg);
|
||||
throw new Exception(msg);
|
||||
throw new S7CheckResultException("errMsg : "+msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public synchronized byte[] read(final DaveArea area, final int areaNumber, final int bytes, final int offset) throws Exception {
|
||||
public synchronized byte[] read(final DaveArea area, final int areaNumber, final int bytes, final int offset) {
|
||||
if (bytes > MAX_SIZE) {
|
||||
final byte[] ret = new byte[bytes];
|
||||
//注意这里 嵌套了 递归,让无限递归去解决 MAX_SIZE的问题。
|
||||
@ -108,7 +110,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public synchronized byte[] read(final DaveArea area, final int areaNumber, final int bytes, final int offset, int bitOffset, TransportSize transportSize) throws Exception {
|
||||
public synchronized byte[] read(final DaveArea area, final int areaNumber, final int bytes, final int offset, int bitOffset, TransportSize transportSize) {
|
||||
if(bitOffset==0){
|
||||
return read(area,areaNumber,bytes,offset);
|
||||
}
|
||||
@ -128,6 +130,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
final byte[] buffer = new byte[bytes];
|
||||
final int ret = this.dc.readBytes(area, areaNumber, offset,bitOffset, bytes, buffer,transportSize);
|
||||
|
||||
//thr resultException
|
||||
checkResult(ret);
|
||||
return buffer;
|
||||
}
|
||||
@ -135,7 +138,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public synchronized void write(final DaveArea area, final int areaNumber, final int offset, final byte[] buffer) throws Exception {
|
||||
public synchronized void write(final DaveArea area, final int areaNumber, final int offset, final byte[] buffer) {
|
||||
if (buffer.length > MAX_SIZE) {
|
||||
// Split buffer
|
||||
final byte[] subBuffer = new byte[MAX_SIZE];
|
||||
@ -155,7 +158,7 @@ public abstract class S7BaseConnection implements S7Connector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(final DaveArea area, final int areaNumber, final int byteOffset, final int bitOffset, final byte[] buffer, PlcVar var) throws Exception {
|
||||
public synchronized void write(final DaveArea area, final int areaNumber, final int byteOffset, final int bitOffset, final byte[] buffer, PlcVar var) {
|
||||
if(bitOffset==0){
|
||||
write(area,areaNumber,byteOffset,buffer);
|
||||
return;
|
||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
package com.qgs.dc.s7.my.s7connector.impl.nodave;
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -45,7 +46,7 @@ public final class PLCinterface {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public int read(final byte[] b, int start, int len) {
|
||||
public int read(final byte[] b, int start, int len){
|
||||
int res;
|
||||
try {
|
||||
int retry = 0;
|
||||
@ -67,18 +68,20 @@ public final class PLCinterface {
|
||||
}
|
||||
return res;
|
||||
} catch (final IOException e) {
|
||||
logger.info("Socket read字节流失败: "+e);
|
||||
return 0;
|
||||
String errMsg = "Socket read字节流失败: "+e.getMessage();
|
||||
logger.info(errMsg);
|
||||
throw new S7IOException(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
public int write(final byte[] b, final int start, final int len) {
|
||||
public int write(final byte[] b, final int start, final int len){
|
||||
try {
|
||||
this.out.write(b, start, len);
|
||||
return 1;
|
||||
} catch (final IOException e) {
|
||||
logger.info("Socket write字节流失败: "+e);
|
||||
return 0;
|
||||
String errMsg = "Socket write字节流失败: "+e.getMessage();
|
||||
logger.info(errMsg);
|
||||
throw new S7IOException(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ public abstract class S7Connection {
|
||||
* it's NULL you can get your data from the resultPointer in daveConnection
|
||||
* long as you do not send further requests.
|
||||
*/
|
||||
public ResultSet execReadRequest(final PDU p) {
|
||||
public ResultSet execReadRequest(final PDU p) throws Exception {
|
||||
PDU p2;
|
||||
int errorState;
|
||||
errorState = this.exchange(p);
|
||||
@ -269,7 +269,7 @@ public abstract class S7Connection {
|
||||
* build the PDU for a PDU length negotiation
|
||||
* 构建第二次握手
|
||||
*/
|
||||
public int negPDUlengthRequest() {
|
||||
public int negPDUlengthRequest() throws Exception {
|
||||
int res;
|
||||
final PDU p = new PDU(this.msgOut, this.PDUstartOut);
|
||||
//S7-Param 构造
|
||||
@ -320,7 +320,7 @@ public abstract class S7Connection {
|
||||
final PDU p1 = new PDU(this.msgOut, this.PDUstartOut);
|
||||
p1.initReadRequest();
|
||||
p1.addVarToReadRequest(area, DBnum, start, len);
|
||||
//发送read var request
|
||||
//通过tcp链接 发送read var request,thr S7IOException
|
||||
res = this.exchange(p1);
|
||||
if (res != Nodave.RESULT_OK) {
|
||||
this.semaphore.release();
|
||||
|
@ -17,6 +17,7 @@ package com.qgs.dc.s7.my.s7connector.impl.nodave;
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.api.utils.ByteUtils;
|
||||
import com.qgs.dc.s7.my.s7connector.enmuc.S7Client;
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -59,7 +60,7 @@ public final class TCPConnection extends S7Connection {
|
||||
*
|
||||
* @return the int
|
||||
*/
|
||||
public int connectPLC() {
|
||||
public int connectPLC() throws Exception {
|
||||
//COTP包 字节流(是上位机 和plc进行的第一次握手)
|
||||
final byte[] b4 = { //b4.length = 18
|
||||
(byte) 0x11, //(16进制)当前字节以后的字节数
|
||||
@ -113,7 +114,7 @@ public final class TCPConnection extends S7Connection {
|
||||
* 0 代表成功
|
||||
* */
|
||||
@Override
|
||||
public int exchange(final PDU p1) {
|
||||
public int exchange(final PDU p1){
|
||||
this.msgOut[4] = (byte) 0x02; //当前字节以后的字节数(也就是下面两个字节)
|
||||
this.msgOut[5] = (byte) 0xf0; //PDU Type
|
||||
this.msgOut[6] = (byte) 0x80; //TPDU number (如果这个字节首位为1 代表就是最后一个传输单元了 如1000 0000 ;; 如果首字母不为1 就代表这个Request是比较长的要分多个unit传输,后7位就代表传输单元序号)
|
||||
@ -123,9 +124,9 @@ public final class TCPConnection extends S7Connection {
|
||||
if(writeRes!=0 && readRes!=0){
|
||||
return 0;
|
||||
}else {
|
||||
|
||||
logger.info("exchange 出现了问题:① writeRes:"+(writeRes==0?"writeISOPacket成功":"writeISOPacket失败")+"② readRes:"+(readRes==0?"readISOPacket成功":"readISOPacket失败"));
|
||||
return 1 ;
|
||||
String errMsg = "exchange 出现了问题:① writeRes:"+(writeRes==0?"writeISOPacket成功":"writeISOPacket失败")+"② readRes:"+(readRes==0?"readISOPacket成功":"readISOPacket失败");
|
||||
logger.info(errMsg);
|
||||
throw new S7IOException(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,15 +134,14 @@ public final class TCPConnection extends S7Connection {
|
||||
* Read iso packet.
|
||||
*
|
||||
* @return the int
|
||||
* 0 ==> 不成功
|
||||
* 0 ==> 不成功(异常)
|
||||
* -1 ==> 读到一个空的字节流 (这种情况很少)
|
||||
* 其他 ==> 成功
|
||||
*/
|
||||
protected int readISOPacket() {
|
||||
protected int readISOPacket(){
|
||||
//read return 为0 就是异常
|
||||
int res = this.iface.read(this.msgIn, 0, 4);
|
||||
if (res == 4) {
|
||||
// final int len = (0x100 * this.msgIn[2]) + this.msgIn[3]; //读取字节数 这串是bug代码
|
||||
final int len = (0x100 * ByteUtils.toUInt(this.msgIn[2])) + ByteUtils.toUInt(this.msgIn[3]);
|
||||
res += this.iface.read(this.msgIn, 4, len);
|
||||
} else {
|
||||
@ -159,7 +159,7 @@ public final class TCPConnection extends S7Connection {
|
||||
* 1 ==> 成功
|
||||
* 0 ==> 不成功(出现异常了)
|
||||
*/
|
||||
protected int sendISOPacket(int size) {
|
||||
protected int sendISOPacket(int size){
|
||||
size += 4;
|
||||
//下面包装的 是TPKT 字节包(第一次握手)
|
||||
this.msgOut[0] = (byte) 0x03; //Version ,默认版本3
|
||||
|
@ -330,7 +330,7 @@ public enum PlcVar {
|
||||
*
|
||||
*
|
||||
* */
|
||||
public Object toObject(byte[] value) throws ParseException, UnsupportedEncodingException {
|
||||
public Object toObject(byte[] value) {
|
||||
if(!isArray){
|
||||
Object res = null;
|
||||
switch (dataType) {
|
||||
|
60
src/main/java/com/qgs/dc/s7/retry/S7RetryTemplate.java
Normal file
60
src/main/java/com/qgs/dc/s7/retry/S7RetryTemplate.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.qgs.dc.s7.retry;
|
||||
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7CheckResultException;
|
||||
import com.qgs.dc.s7.my.s7connector.exception.S7IOException;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.retry.backoff.FixedBackOffPolicy;
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author caixiang
|
||||
* @description 重试模板和重试策略
|
||||
*/
|
||||
public class S7RetryTemplate extends RetryTemplate {
|
||||
|
||||
private volatile static S7RetryTemplate instance = null;
|
||||
/**
|
||||
* 重试间隔时间ms,默认1000ms
|
||||
* */
|
||||
private static long fixedPeriodTime = 500L;
|
||||
/**
|
||||
* 最大重试次数,默认为3
|
||||
*/
|
||||
private static int maxRetryTimes = 3;
|
||||
/**
|
||||
* 表示哪些异常需要重试,key表示异常的字节码,value为true表示需要重试
|
||||
*/
|
||||
private static Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
|
||||
private S7RetryTemplate() {
|
||||
// 代表S7IOException 这个异常是需要重试的(true), 如果你想设置这个异常不去重试,那么可以把它设置为false。
|
||||
exceptionMap.put(S7IOException.class,true);
|
||||
exceptionMap.put(S7CheckResultException.class,true);
|
||||
|
||||
}
|
||||
public static int getMaxRetryTimes() {
|
||||
return maxRetryTimes;
|
||||
}
|
||||
|
||||
public static S7RetryTemplate getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (S7RetryTemplate.class) {
|
||||
if (instance == null) {
|
||||
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
|
||||
// 定义重试间隔-间隔 fixedPeriodTime ms再重试,总共重试3次
|
||||
backOffPolicy.setBackOffPeriod(fixedPeriodTime);
|
||||
instance = new S7RetryTemplate();
|
||||
// 定义重试次数- maxRetryTimes
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxRetryTimes, exceptionMap);
|
||||
instance.setRetryPolicy(retryPolicy);
|
||||
|
||||
instance.setBackOffPolicy(backOffPolicy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
39
src/main/java/com/qgs/dc/s7/retrydemo/RetryDemoTask.java
Normal file
39
src/main/java/com/qgs/dc/s7/retrydemo/RetryDemoTask.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.qgs.dc.s7.retrydemo;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
|
||||
/**
|
||||
* @Author: cx
|
||||
* @Description:
|
||||
*/
|
||||
public class RetryDemoTask {
|
||||
/**
|
||||
* 重试方法
|
||||
* @return
|
||||
*/
|
||||
public static boolean retryTask(String param) {
|
||||
System.out.println("retry-task : 收到请求参数:"+param);
|
||||
|
||||
int i = RandomUtils.nextInt(0,11);
|
||||
System.out.println("retry-task : 随机生成的数:"+i);
|
||||
if (i == 0) {
|
||||
System.out.println("retry-task : 为0,抛出参数异常.");
|
||||
//因为Illeague这个异常我们没有在exceptionMap里面配置,所以 抛出这个异常后
|
||||
//spring-retry不会进行重试,而是会直接进入recovery函数
|
||||
throw new IllegalArgumentException("retry-task : 参数异常");
|
||||
}else if (i == 1){
|
||||
System.out.println("retry-task : 为1,返回true.");
|
||||
return true;
|
||||
}else if (i == 2){
|
||||
System.out.println("retry-task : 为2,返回false.");
|
||||
return false;
|
||||
}else{
|
||||
//因为RemoteAccessExcep这个异常我们在exceptionMap里面配置了,所以 抛出这个异常后
|
||||
//spring-retry会进行重试
|
||||
System.out.println("retry-task : 大于2,抛出自定义异常.");
|
||||
throw new RemoteAccessException("retry-task : 大于2,抛出远程访问异常");
|
||||
}
|
||||
}
|
||||
}
|
58
src/main/java/com/qgs/dc/s7/retrydemo/RetryMain.java
Normal file
58
src/main/java/com/qgs/dc/s7/retrydemo/RetryMain.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.qgs.dc.s7.retrydemo;
|
||||
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.retry.backoff.FixedBackOffPolicy;
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RetryMain {
|
||||
public static void main(String[] args) {
|
||||
|
||||
/**
|
||||
* 重试间隔时间ms,默认1000ms
|
||||
* */
|
||||
long fixedPeriodTime = 1000L;
|
||||
/**
|
||||
* 最大重试次数,默认为3
|
||||
*/
|
||||
int maxRetryTimes = 3;
|
||||
/**
|
||||
* 表示哪些异常需要重试,key表示异常的字节码,value为true表示需要重试
|
||||
*/
|
||||
Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
|
||||
|
||||
|
||||
exceptionMap.put(RemoteAccessException.class,true);
|
||||
|
||||
// 构建重试模板实例
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
|
||||
// 设置重试回退操作策略,主要设置重试间隔时间
|
||||
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
|
||||
backOffPolicy.setBackOffPeriod(fixedPeriodTime);
|
||||
|
||||
// 设置重试策略,主要设置重试次数
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxRetryTimes, exceptionMap);
|
||||
|
||||
retryTemplate.setRetryPolicy(retryPolicy);
|
||||
retryTemplate.setBackOffPolicy(backOffPolicy);
|
||||
|
||||
Boolean execute = retryTemplate.execute(
|
||||
//RetryCallback
|
||||
retryContext -> {
|
||||
boolean b = RetryDemoTask.retryTask("abc");
|
||||
System.err.println("retry-main : 调用的结果:"+b+",times:"+retryContext.getRetryCount());
|
||||
return b;
|
||||
},
|
||||
retryContext -> {
|
||||
//RecoveryCallback
|
||||
System.err.println("retry-main : 已达到最大重试次数或抛出了不重试的异常~~~");
|
||||
return false;
|
||||
}
|
||||
);
|
||||
System.err.println("retry-main : 执行结果:"+execute);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.qgs.dc.s7.retrydemo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.retry.backoff.FixedBackOffPolicy;
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: zgd
|
||||
* @Description: spring-retry 重试框架
|
||||
*/
|
||||
public class SpringS7RetryTemplateTest {
|
||||
|
||||
/**
|
||||
* 重试间隔时间ms,默认1000ms
|
||||
* */
|
||||
private long fixedPeriodTime = 1000L;
|
||||
/**
|
||||
* 最大重试次数,默认为3
|
||||
*/
|
||||
private int maxRetryTimes = 3;
|
||||
/**
|
||||
* 表示哪些异常需要重试,key表示异常的字节码,value为true表示需要重试
|
||||
*/
|
||||
private Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
//文档:https://blog.csdn.net/minghao0508/article/details/123972703
|
||||
exceptionMap.put(RemoteAccessException.class,true);
|
||||
|
||||
// 构建重试模板实例
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
|
||||
// 设置重试回退操作策略,主要设置重试间隔时间
|
||||
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
|
||||
backOffPolicy.setBackOffPeriod(fixedPeriodTime);
|
||||
|
||||
// 设置重试策略,主要设置重试次数
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxRetryTimes, exceptionMap);
|
||||
|
||||
retryTemplate.setRetryPolicy(retryPolicy);
|
||||
retryTemplate.setBackOffPolicy(backOffPolicy);
|
||||
|
||||
Boolean execute = retryTemplate.execute(
|
||||
//RetryCallback
|
||||
retryContext -> {
|
||||
boolean b = RetryDemoTask.retryTask("abc");
|
||||
System.out.println("调用的结果:"+b);
|
||||
return b;
|
||||
},
|
||||
retryContext -> {
|
||||
//RecoveryCallback
|
||||
System.out.println("已达到最大重试次数或抛出了不重试的异常~~~");
|
||||
return false;
|
||||
}
|
||||
);
|
||||
System.out.println("执行结果:"+execute);
|
||||
}
|
||||
|
||||
}
|
20
src/main/java/com/qgs/dc/s7/retrydemo/TestMain.java
Normal file
20
src/main/java/com/qgs/dc/s7/retrydemo/TestMain.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.qgs.dc.s7.retrydemo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TestMain {
|
||||
public static void main(String[] args) {
|
||||
Integer a = 1;
|
||||
Integer a1 = 2;
|
||||
Integer a2 = 3;
|
||||
List<Integer> list = new ArrayList<Integer>();
|
||||
list.add(a);
|
||||
list.add(a1);
|
||||
list.add(a2);
|
||||
Integer integer = list.get(0);
|
||||
list.remove(integer);
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
}
|
불러오는 중...
Reference in New Issue
Block a user