Redkale 2.4.0 结束

This commit is contained in:
redkale
2021-10-18 13:19:30 +08:00
parent 2464c360c0
commit 7ffb65cc38
523 changed files with 90963 additions and 81040 deletions

View File

@@ -0,0 +1,39 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.asm;
import java.io.*;
import org.redkale.util.Utility;
/**
*
* @author zhangjx
*/
public class AsmCreator {
public static void main(String[] args) throws Throwable {
boolean realasm = false; //从http://forge.ow2.org/projects/asm/ 下载最新asm的src放在 srcasmroot 目录下
File srcasmroot = new File("D:/JAVA/JDK源码/JDK11源码/java.base/jdk/internal/org/objectweb/asm");
if (realasm) srcasmroot = new File("D:/JAVA/JDK源码/org/objectweb/asm");
File destasmroot = new File("D:/Java-Projects/RedkaleProject/src/org/redkale/asm");
String line = null;
LineNumberReader txtin = new LineNumberReader(new FileReader(new File(destasmroot, "asm.txt")));
while ((line = txtin.readLine()) != null) {
line = line.trim();
if (!line.endsWith(".java")) continue;
File srcfile = new File(srcasmroot, line);
if (!srcfile.isFile()) continue;
File destfile = new File(destasmroot, line);
String content = Utility.readThenClose(new FileInputStream(srcfile));
FileOutputStream out = new FileOutputStream(destfile);
out.write(content.replace("jdk.internal.org.objectweb", "org.redkale").replace("org.objectweb", "org.redkale")
.replace("<tt>", "&#60;tt&#62;").replace("</tt>", "&#60;/tt&#62;")
.replace("{@link org.redkale.asm.tree.MethodNode#getLabelNode} method.", "").getBytes());
out.close();
}
//需要屏蔽ClassReader中判断checks the class version的部分
}
}

View File

@@ -0,0 +1,72 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.redkale.convert.ConvertField;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.Attribute;
/**
* @author zhangjx
*/
public class BiFunctionConvertTest {
public static class GamePlayer {
public int userid;
public String username;
public int[] cards;
}
public static class GameTable {
public int tableid;
public GamePlayer[] players;
}
@Test
public void run() throws Throwable {
GamePlayer player1 = new GamePlayer();
player1.userid = 1;
player1.username = "玩家1";
player1.cards = new int[]{11, 12, 13, 14, 15};
GamePlayer player2 = new GamePlayer();
player2.userid = 2;
player2.username = "玩家2";
player2.cards = new int[]{21, 22, 23, 24, 25};
GamePlayer player3 = new GamePlayer();
player3.userid = 3;
player3.username = "玩家3";
player3.cards = new int[]{31, 32, 33, 34, 35};
GameTable table = new GameTable();
table.tableid = 100;
table.players = new GamePlayer[]{player1, player2, player3};
JsonConvert convert1 = JsonConvert.root();
System.out.println(convert1.convertTo(table));
JsonConvert convert2 = convert1.newConvert((Attribute t, Object u) -> {
if (t.field().equals("cards") && u instanceof GamePlayer) {
int userid = ((GamePlayer) u).userid;
if (userid == 3) return null; //玩家3的cards不输出
return t.get(u);
}
return t.get(u);
}, (Object u) -> {
if (table != u) return null;
//return new ConvertField[]{new ConvertField("extcol1", 30), new ConvertField("extcol2", "扩展字段值")};
return ConvertField.ofArray("extcol1", 30, "extcol2", "扩展字段值");
});
System.out.println(convert2.convertTo(table));
Assertions.assertEquals("{\"players\":[{\"cards\":[11,12,13,14,15],\"userid\":1,\"username\":\"玩家1\"},{\"cards\":[21,22,23,24,25],\"userid\":2,\"username\":\"玩家2\"},{\"userid\":3,\"username\":\"玩家3\"}],\"tableid\":100,\"extcol1\":30,\"extcol2\":\"扩展字段值\"}",
convert2.convertTo(table));
//{"players":[{"cards":[11,12,13,14,15],"userid":1,"username":"玩家1"},{"cards":[21,22,23,24,25],"userid":2,"username":"玩家2"},{"cards":[31,32,33,34,35],"userid":3,"username":"玩家3"}],"tableid":100}
//{"players":[{"cards":[11,12,13,14,15],"userid":1,"username":"玩家1"},{"cards":[21,22,23,24,25],"userid":2,"username":"玩家2"},{"userid":3,"username":"玩家3"}],"tableid":100,"extcol1":30,"extcol2":"扩展字段值"}
}
}

View File

@@ -0,0 +1,276 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.io.*;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.redkale.convert.bson.BsonByteBufferWriter;
import org.redkale.convert.bson.BsonFactory;
import org.redkale.util.Utility;
import org.redkale.convert.bson.BsonConvert;
import java.nio.*;
import java.util.*;
import javax.persistence.*;
import org.redkale.convert.json.*;
import org.redkale.util.*;
/**
* @author zhangjx
*/
public class BsonMainTest {
@Test
public void run1() throws Throwable {
Serializable[] sers = new Serializable[]{"aaa", 4};
final BsonConvert convert = BsonFactory.root().getConvert();
byte[] bytes = convert.convertTo(sers);
Utility.println("---", bytes);
byte[] checks = new byte[]{0x00, 0x00, 0x00, 0x02, 0x7f, 0x01, 0x41, 0x00, 0x00, 0x00, 0x03, 0x61, 0x61, 0x61, 0x01, 0x69, 0x00, 0x00, 0x00, 0x04};
Assertions.assertArrayEquals(checks, bytes);
Serializable[] a = convert.convertFrom(Serializable[].class, bytes);
Assertions.assertEquals("[aaa, 4]", Arrays.toString(a));
}
@Test
public void run2() throws Exception {
final BsonConvert convert = BsonFactory.root().getConvert();
SimpleChildEntity entry = SimpleChildEntity.create();
byte[] bytes = convert.convertTo(SimpleEntity.class, entry);
System.out.println("长度: " + bytes.length);
Assertions.assertEquals(260, bytes.length);
BsonByteBufferWriter writer = convert.pollBsonWriter(() -> ByteBuffer.allocate(1));
convert.convertTo(writer, SimpleEntity.class, entry);
ByteBuffer[] buffers = writer.toBuffers();
int len = 0;
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (ByteBuffer b : buffers) {
len += b.remaining();
byte[] ts = new byte[b.remaining()];
b.get(ts);
out.write(ts);
b.flip();
}
System.out.println("长度: " + len);
Assertions.assertEquals(260, len);
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, buffers);
System.out.println(entry);
Assertions.assertEquals(entry.toString(), entry2.toString());
}
@Test
public void run3() throws Exception {
final BsonConvert convert = BsonFactory.root().getConvert();
SimpleChildEntity entry = SimpleChildEntity.create();
byte[] bytes = convert.convertTo(SimpleEntity.class, entry);
Utility.println(null, bytes);
System.out.println(JsonConvert.root().convertTo(entry));
SimpleEntity rs = convert.convertFrom(SimpleEntity.class, bytes);
Assertions.assertEquals(JsonConvert.root().convertTo(entry), rs.toString());
ComplextEntity bean = new ComplextEntity();
byte[] bytes2 = convert.convertTo(Object.class, bean);
final int len = bytes2.length;
BsonByteBufferWriter writer = convert.pollBsonWriter(() -> ByteBuffer.allocate(len / 2));
convert.convertTo(writer, bean);
bytes2 = writer.toArray();
System.out.println(convert.convertFrom(ComplextEntity.class, bytes2).toString());
Assertions.assertEquals("{\"flag\":true,\"userid\":0}", convert.convertFrom(ComplextEntity.class, bytes2).toString());
}
@Test
public void run4() throws Exception {
final BsonConvert convert = BsonFactory.root().getConvert();
SimpleChildEntity entry = SimpleChildEntity.create();
ByteArrayOutputStream out = new ByteArrayOutputStream();
convert.convertTo(out, SimpleEntity.class, entry);
byte[] bytes = out.toByteArray();
Utility.println(null, bytes);
SimpleEntity rs = convert.convertFrom(SimpleEntity.class, new ByteArrayInputStream(bytes));
System.out.println(rs.toString());
Assertions.assertEquals(JsonConvert.root().convertTo(entry), rs.toString());
}
@Test
public void run5() throws Exception {
final BsonConvert convert = BsonFactory.root().getConvert();
LinkedHashMap map = new LinkedHashMap();
map.put("1", 1);
map.put("2", "a2");
byte[] bs = convert.convertTo(Object.class, map);
Object mapobj = convert.convertFrom(Object.class, bs);
System.out.println(mapobj);
Assertions.assertEquals("{1=1, 2=a2}", mapobj.toString());
}
@Test
public void run6() throws Exception {
final BsonConvert convert = BsonFactory.root().getConvert();
Optional<String> val = Optional.ofNullable("haha");
byte[] bs = convert.convertTo(val);
Object obj = convert.convertFrom(Optional.class, bs);
System.out.println(obj);
Assertions.assertEquals("Optional[haha]", obj.toString());
bs = convert.convertTo(Object.class, val);
obj = convert.convertFrom(Object.class, bs);
Assertions.assertEquals("Optional[haha]", obj.toString());
bs = convert.convertTo(new TypeToken<Optional<String>>() {
}.getType(), val);
obj = convert.convertFrom(new TypeToken<Optional<String>>() {
}.getType(), bs);
Assertions.assertEquals("Optional[haha]", obj.toString());
System.out.println(JsonConvert.root().convertTo(val));
Assertions.assertEquals("\"haha\"", JsonConvert.root().convertTo(val));
}
@Test
public void run7() throws Throwable {
Two two = new Two();
two.setKey("key111");
two.setCode(12345);
List<String> list = new ArrayList<>();
list.add("haha");
two.setList(list);
Map<String, String> map = new HashMap<>();
map.put("222", "333");
two.setStringMap(map);
List<ConvertRecord> records = new ArrayList<>();
records.add(ConvertRecord.createDefault());
two.setRecords(records);
Map<String, ConvertRecord> rmap = new HashMap<>();
rmap.put("222", ConvertRecord.createDefault());
two.setRecordMap(rmap);
byte[] bs = BsonFactory.root().getConvert().convertTo(two);
One one = BsonFactory.root().getConvert().convertFrom(One.class, bs);
System.out.println(one);
Assertions.assertEquals("{\"bytes\":[3,4,5],\"code\":12345,\"ints\":[3000,4000,5000],\"key\":\"key111\"}", one.toString());
}
@Test
public void run8() throws Exception {
final JsonConvert jsonConvert = JsonConvert.root();
final BsonConvert bsonConvert = BsonFactory.root().getConvert();
ConstructorArgsEntity bean = new ConstructorArgsEntity(12345678, "哈哈");
bean.setCreatetime(12345678901L);
String json = jsonConvert.convertTo(bean);
System.out.println(json);
Assertions.assertEquals("{\"createtime\":12345678901,\"name\":\"哈哈\",\"userid\":12345678}", json);
Assertions.assertEquals(jsonConvert.convertFrom(ConstructorArgsEntity.class, json).toString(), json);
byte[] bytes = bsonConvert.convertTo(bean);
Assertions.assertEquals(bsonConvert.convertFrom(ConstructorArgsEntity.class, bytes).toString(), json);
}
public static class ComplextEntity {
@Id
private int userid;
private String chname = "";
@Transient
private boolean flag = true;
@Transient
private List<SimpleChildEntity> children;
@Transient
private SimpleEntity user;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getChname() {
return chname;
}
public void setChname(String chname) {
this.chname = chname;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public List<SimpleChildEntity> getChildren() {
return children;
}
public void setChildren(List<SimpleChildEntity> children) {
this.children = children;
}
public SimpleEntity getUser() {
return user;
}
public void setUser(SimpleEntity user) {
this.user = user;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
public static class ConstructorArgsEntity {
private final int userid;
private String name;
private long createtime;
@ConstructorParameters({"userid", "name"})
public ConstructorArgsEntity(int userid, String name) {
this.userid = userid;
this.name = name;
}
public int getUserid() {
return userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import org.junit.jupiter.api.*;
import org.redkale.convert.ConvertImpl;
import org.redkale.convert.json.JsonConvert;
/**
*
* @author zhangjx
*/
public class ConvertImplTest {
@Test
public void run1() throws Throwable {
String json = "{'name':'hellow'}";
OneEntity one = JsonConvert.root().convertFrom(OneEntity.class, json);
Assertions.assertTrue(one instanceof OneImpl);
}
@ConvertImpl(OneImpl.class)
public static interface OneEntity {
public String getName();
}
public static class OneImpl implements OneEntity {
private String name;
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@@ -0,0 +1,192 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.util.*;
/**
*
* @author redkale
*/
public class ConvertRecord {
private String aname;
private String desc = "";
private int id = (int) System.currentTimeMillis();
private int[] integers;
private long[] longs;
private List<String> strings;
private Map<String, Integer> map;
public static ConvertRecord createDefault() {
ConvertRecord v = new ConvertRecord();
v.setAname("this is name\n \"test");
v.setId(1000000001);
v.setIntegers(new int[]{12, 34, 56, 78, 90, 123, 456, 789});
v.setLongs(new long[]{10000012L, 10000034L, 10000056L, 10000078L, -10000090L, -100000123L, -100000456L, -100000789L});
List<String> list = new ArrayList<>();
list.add("str_a");
list.add("str_b");
list.add("str_c");
v.setStrings(list);
Map<String, Integer> map = new HashMap<>();
map.put("key_a", 111);
map.put("key_b", 222);
map.put("key_c", 333);
v.setMap(map);
return v;
}
public static void main(String[] args) throws Exception {
final ConvertRecord entry = ConvertRecord.createDefault();
run(ConvertRecord.class, entry);
}
public static <T> void run(final Class<T> type, final T entry) throws Exception {
/**
final org.redkale.convert.json.JsonConvert convert = org.redkale.convert.json.JsonFactory.root().getConvert();
final String entryString = convert.convertTo(entry);
convert.convertFrom(type, entryString);
System.out.println("redkale-convert: " + convert.convertTo(entry));
com.alibaba.fastjson.JSON.parseObject(entryString, type);
System.out.println("fastjson 1.2.7: " + com.alibaba.fastjson.JSON.toJSONString(entry));
final com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
mapper.readValue(entryString, type);
System.out.println("jackson 2.7.2: " + mapper.writeValueAsString(entry));
final com.google.gson.Gson gson = new com.google.gson.Gson();
gson.fromJson(entryString, type);
System.out.println("google-gson 2.4: " + gson.toJson(entry));
System.out.println("------------------------------------------------");
System.out.println("组件 序列化耗时(ms) 反序列化耗时(ms)");
final int count = 10_0000;
long s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
convert.convertTo(entry);
}
long e = System.currentTimeMillis() - s;
System.out.print("redkale-convert " + e);
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
convert.convertFrom(type, entryString);
}
e = System.currentTimeMillis() - s;
System.out.println("\t " + e);
//----------------------------------------------------------------------------
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
com.alibaba.fastjson.JSON.toJSONString(entry);
}
e = System.currentTimeMillis() - s;
System.out.print("fastjson 1.2.7 " + e);
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
com.alibaba.fastjson.JSON.parseObject(entryString, type);
}
e = System.currentTimeMillis() - s;
System.out.println("\t " + e);
//----------------------------------------------------------------------------
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
mapper.writeValueAsString(entry);
}
e = System.currentTimeMillis() - s;
System.out.print("jackson 2.7.2 " + e);
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
mapper.readValue(entryString, type);
}
e = System.currentTimeMillis() - s;
System.out.println("\t " + e);
//----------------------------------------------------------------------------
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
gson.toJson(entry);
}
e = System.currentTimeMillis() - s;
System.out.print("google-gson 2.4 " + e);
s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
gson.fromJson(entryString, type);
}
e = System.currentTimeMillis() - s;
System.out.println("\t " + e);
//----------------------------------------------------------------------------
*/
}
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int[] getIntegers() {
return integers;
}
public void setIntegers(int[] integers) {
this.integers = integers;
}
public long[] getLongs() {
return longs;
}
public void setLongs(long[] longs) {
this.longs = longs;
}
public List<String> getStrings() {
return strings;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
public Map<String, Integer> getMap() {
return map;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
}

View File

@@ -0,0 +1,56 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import javax.persistence.Id;
import org.redkale.convert.json.JsonConvert;
/**
*
* @author zhangjx
*/
public class Fortune implements Comparable<Fortune> {
@Id
private int id;
private String message = "";
public Fortune() {
}
public Fortune(int id, String message) {
this.id = id;
this.message = message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public int compareTo(Fortune o) {
return message.compareTo(o.message);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -0,0 +1,110 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import org.redkale.util.TypeToken;
import org.redkale.convert.json.JsonFactory;
import java.lang.reflect.*;
import java.util.*;
import org.redkale.convert.json.*;
/**
* 支持泛型的
*
* @author zhangjx
* @param <T>
* @param <K>
* @param <V>
*/
public class GenericEntity<T, K, V> {
private K name;
private List<? extends T> list;
private Entry<K, V> entry;
public static void main(String[] args) throws Throwable {
GenericEntity<Long, String, SimpleEntity> bean = new GenericEntity<>();
bean.setName("你好");
List<Long> list = new ArrayList<>();
list.add(1234567890L);
bean.setList(list);
bean.setEntry(new Entry<>("aaaa", SimpleEntity.create()));
final Type type = new TypeToken<GenericEntity<Long, String, SimpleEntity>>() {
}.getType();
JsonFactory.root().tiny(true);
String json = JsonConvert.root().convertTo(bean);
System.out.println(json);
System.out.println(JsonConvert.root().convertFrom(type, json).toString());
}
@Override
public String toString() {
return "{\"entry\":" + entry + ",\"list\":" + list + ",\"name\":\"" + name + "\"}";
}
public K getName() {
return name;
}
public void setName(K name) {
this.name = name;
}
public List<? extends T> getList() {
return list;
}
public void setList(List<? extends T> list) {
this.list = list;
}
public Entry<K, V> getEntry() {
return entry;
}
public void setEntry(Entry<K, V> entry) {
this.entry = entry;
}
public static class Entry<K, V> {
private K key;
private V value;
public Entry() {
}
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
}

View File

@@ -0,0 +1,119 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import org.redkale.convert.*;
import org.redkale.convert.bson.*;
import org.redkale.convert.json.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class InnerCoderEntity {
private final String val;
private final int id;
private InnerCoderEntity(int id, String value) {
this.id = id;
this.val = value;
}
public static InnerCoderEntity create(int id, String value) {
return new InnerCoderEntity(id, value);
}
/**
* 该方法提供给Convert组件自动加载。
* 1) 方法名可以随意。
2) 方法必须是static
3方法的参数有且只能有一个 且必须是org.redkale.convert.ConvertFactory或子类。
—3.1) 参数类型为org.redkale.convert.ConvertFactory 表示适合JSON和BSON。
—3.2) 参数类型为org.redkale.convert.json.JsonFactory 表示仅适合JSON。
—3.3) 参数类型为org.redkale.convert.bson.BsonFactory 表示仅适合BSON。
4方法的返回类型必须是org.redkale.convert.Decodeable/org.redkale.convert.Encodeable/org.redkale.convert.SimpledCoder
若返回类型不是org.redkale.convert.SimpledCoder, 就必须提供两个方法: 一个返回Decodeable 一个返回 Encodeable。
*
* @param factory
* @return
*/
private static SimpledCoder<Reader, Writer, InnerCoderEntity> createConvertCoder(final org.redkale.convert.ConvertFactory factory) {
return new SimpledCoder<Reader, Writer, InnerCoderEntity>() {
//必须与EnMember[] 顺序一致
private final DeMember[] deMembers = new DeMember[]{
DeMember.create(factory, InnerCoderEntity.class, "id"),
DeMember.create(factory, InnerCoderEntity.class, "val")};
//必须与DeMember[] 顺序一致
private final EnMember[] enMembers = new EnMember[]{
EnMember.create(factory, InnerCoderEntity.class, "id"),
EnMember.create(factory, InnerCoderEntity.class, "val")};
@Override
public void convertTo(Writer out, InnerCoderEntity value) {
if (value == null) {
out.writeObjectNull(InnerCoderEntity.class);
return;
}
out.writeObjectB(value);
for (EnMember member : enMembers) {
out.writeObjectField(member, value);
}
out.writeObjectE(value);
}
@Override
public InnerCoderEntity convertFrom(Reader in) {
if (in.readObjectB(InnerCoderEntity.class) == null) return null;
int index = 0;
final Object[] params = new Object[deMembers.length];
while (in.hasNext()) {
DeMember member = in.readFieldName(deMembers); //读取字段名
in.readBlank(); //读取字段名与字段值之间的间隔符JSON则是跳过冒号:
if (member == null) {
in.skipValue(); //跳过不存在的字段的值, 一般不会发生
} else {
params[index++] = member.read(in);
}
}
in.readObjectE(InnerCoderEntity.class);
return InnerCoderEntity.create(params[0] == null ? 0 : (Integer) params[0], (String) params[1]);
}
};
}
public int getId() {
return id;
}
public String getVal() {
return val;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static void main(String[] args) throws Exception {
InnerCoderEntity record = InnerCoderEntity.create(200, "haha");
final JsonConvert convert = JsonConvert.root();
String json = convert.convertTo(record);
System.out.println(json);
System.out.println(convert.convertFrom(InnerCoderEntity.class, json).toString());
final BsonConvert convert2 = BsonFactory.root().getConvert();
byte[] bs = convert2.convertTo(InnerCoderEntity.class, null);
Utility.println("--", bs);
InnerCoderEntity r = convert2.convertFrom(InnerCoderEntity.class, bs);
System.out.println(r);
}
}

View File

@@ -0,0 +1,91 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.io.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.convert.json.JsonFactory;
import java.nio.*;
import java.util.*;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class JsonTestMain {
@Test
public void run1() throws Throwable {
JsonFactory factory = JsonFactory.root().tiny(true);
final JsonConvert convert = JsonConvert.root();
String json = "{\"access_token\":\"null\",\"priv\":null, vvv:nulla,\"priv2\":\"nulla\",\"expires_in\":7200, \"aa\":\"\"}";
Map<String, String> map = convert.convertFrom(JsonConvert.TYPE_MAP_STRING_STRING, json);
System.out.println(map);
String rs = convert.convertTo(map);
System.out.println(rs);
ByteBuffer[] buffers = convert.convertTo(() -> ByteBuffer.allocate(1024), map);
byte[] bs = new byte[buffers[0].remaining()];
buffers[0].get(bs);
System.out.println(new String(bs));
Assertions.assertEquals(rs, new String(bs));
}
@Test
public void run2() throws Throwable {
final JsonConvert convert = JsonConvert.root();
SimpleChildEntity entry = SimpleChildEntity.create();
String json = convert.convertTo(SimpleEntity.class, entry);
System.out.println("长度: " + json.length());
JsonByteBufferWriter writer = new JsonByteBufferWriter(false, () -> ByteBuffer.allocate(1)) {
};
convert.convertTo(writer, SimpleEntity.class, entry);
ByteBuffer[] buffers = writer.toBuffers();
int len = 0;
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (ByteBuffer b : buffers) {
len += b.remaining();
byte[] ts = new byte[b.remaining()];
b.get(ts);
out.write(ts);
b.flip();
}
System.out.println("长度: " + len);
System.out.println(json);
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, buffers);
System.out.println(entry);
System.out.println(entry2);
}
@Test
public void run3() throws Throwable {
final JsonConvert convert = JsonConvert.root();
SimpleChildEntity entry = SimpleChildEntity.create();
ByteArrayOutputStream out = new ByteArrayOutputStream();
convert.convertTo(out, SimpleEntity.class, entry);
String json = out.toString("UTF-8");
System.out.println("长度: " + json.length());
System.out.println(json);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, in);
System.out.println(entry);
System.out.println(entry2);
Map rs = (Map) convert.convertFrom(entry2.toString());
System.out.println(convert.convertTo(rs));
}
@Test
public void run4() throws Throwable {
final JsonConvert convert = JsonConvert.root();
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
String json = convert.convertTo(date);
System.out.println("java.sql.Date 值: " + json);
java.sql.Date rs = convert.convertFrom(java.sql.Date.class, json);
System.out.println(convert.convertTo(rs));
}
}

View File

@@ -0,0 +1,91 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.redkale.convert.*;
import org.redkale.convert.json.*;
import org.redkale.util.ByteArray;
/**
*
* @author zhangjx
*/
public final class Message {
protected boolean flag;
private int[] ints;
private List<Long> longs;
@ConvertSmallString
private String message;
public Message() {
}
public List<Long> getLongs() {
return longs;
}
public void setLongs(List<Long> longs) {
this.longs = longs;
}
public int[] getInts() {
return ints;
}
public void setInts(int[] ints) {
this.ints = ints;
}
public Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static void main(String[] args) throws Throwable {
Message msg = new Message();
msg.message = "dddd";
List<Long> longs = new ArrayList<>();
longs.add(2222L);
longs.add(3333L);
msg.longs = longs;
msg.ints = new int[]{2, 3, 4};
JsonConvert convert = JsonFactory.root().getConvert();
Encodeable encoder = JsonFactory.root().loadEncoder(Message.class);
System.out.println(encoder);
ByteArray array = new ByteArray();
array.put("数据: ".getBytes(StandardCharsets.UTF_8));
JsonConvert.root().convertToBytes(array, msg);
System.out.println(array);
Message[] mss = new Message[]{msg};
System.out.println(JsonConvert.root().convertTo(mss));
}
}

View File

@@ -0,0 +1,89 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.util.Arrays;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.Utility;
/**
*
* @author zhangjx
*/
public class One {
protected String key;
protected int code;
protected byte[] bytes = new byte[]{3, 4, 5};
protected int[] ints = new int[]{3000, 4000, 5000};
public One(int code) {
this.code = code;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public byte[] getBytes() {
return bytes;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
public int[] getInts() {
return ints;
}
public void setInts(int[] ints) {
this.ints = ints;
}
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static void main(String[] args) throws Throwable {
int count = 100_0000;
One one = new One(234);
one.bytes = new byte[]{1, 2, 3};
one.key = "哈哈";
System.out.println(Arrays.toString(Utility.encodeUTF8(JsonConvert.root().convertTo(one))));
System.out.println(Arrays.toString(JsonConvert.root().convertToBytes(one)));
long s = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
JsonConvert.root().convertTo(one).getBytes();
}
long e = System.currentTimeMillis() - s;
long s2 = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
JsonConvert.root().convertToBytes(one);
}
long e2 = System.currentTimeMillis() - s2;
System.out.println(e);
System.out.println(e2);
}
}

View File

@@ -0,0 +1,60 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.net.*;
import org.redkale.convert.ConvertEntity;
import java.util.*;
/**
*
* @author zhangjx
*/
@ConvertEntity("myname")
public class SimpleChildEntity extends SimpleEntity {
private short st = -1234;
private String extend;
public static SimpleChildEntity create() {
SimpleChildEntity v = new SimpleChildEntity();
v.setName("this is name\n \"test");
v.setId(1000000001);
v.setAddrs(new int[]{22222, 33333, 44444, 55555, 66666, 77777, 88888, 99999});
v.setStrings(new String[]{"zzz", "yyy", "xxx"});
List<String> list = new ArrayList<>();
list.add("aaaa");
list.add("bbbb");
list.add("cccc");
v.setLists(list);
Map<String, Integer> map = new HashMap<>();
map.put("AAA", 111);
map.put("BBB", 222);
map.put("CCC", 333);
v.setMap(map);
v.setExtend("hahaha");
v.setAddr(new InetSocketAddress("127.0.0.1", 6666));
return v;
}
public short getSt() {
return st;
}
public void setSt(short st) {
this.st = st;
}
public String getExtend() {
return extend;
}
public void setExtend(String extend) {
this.extend = extend;
}
}

View File

@@ -0,0 +1,137 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.net.*;
import org.redkale.util.Creator;
import java.util.*;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class SimpleEntity {
private String name;
private String desc = "";
private int id = (int) System.currentTimeMillis();
private int[] addrs;
private List<String> lists;
private String[] strings;
private Map<String, Integer> map;
private InetSocketAddress addr;
public static SimpleEntity create() {
SimpleEntity v = new SimpleEntity();
v.setName("this is name\n \"test");
v.setId(1000000001);
v.setAddrs(new int[]{22222, 33333, 44444, 55555, 66666, 77777, 88888, 99999});
v.setStrings(new String[]{"zzz", "yyy", "xxx"});
List<String> list = new ArrayList<>();
list.add("aaaa");
list.add("bbbb");
list.add("cccc");
v.setLists(list);
Map<String, Integer> map = new HashMap<>();
map.put("AAA", 111);
map.put("BBB", 222);
map.put("CCC", 333);
v.setMap(map);
v.setAddr(new InetSocketAddress("127.0.0.1", 6666));
return v;
}
public static void main(String[] args) throws Exception {
System.out.println(JsonConvert.root().convertTo(create()));
Creator<SimpleEntity> creator = Creator.create(SimpleEntity.class); //Creator.create(10, SimpleEntity.class);
SimpleEntity entry = creator.create();
System.out.println(entry);
for (int i = 0; i < 10000000; i++) {
creator.create();
}
System.gc();
Thread.sleep(2000);
System.out.println(creator.create());
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public InetSocketAddress getAddr() {
return addr;
}
public void setAddr(InetSocketAddress addr) {
this.addr = addr;
}
public int[] getAddrs() {
return addrs;
}
public void setAddrs(int[] addrs) {
this.addrs = addrs;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Map<String, Integer> getMap() {
return map;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String[] getStrings() {
return strings;
}
public void setStrings(String[] strings) {
this.strings = strings;
}
}

View File

@@ -0,0 +1,72 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.util.*;
import org.redkale.convert.bson.BsonFactory;
/**
*
* @author zhangjx
*/
public class Two extends One {
public Two() {
super(90100119);
}
protected List<String> list;
protected Map<String, String> stringMap;
protected List<ConvertRecord> records;
protected Map<String, ConvertRecord> recordMap;
public Map<String, String> getStringMap() {
return stringMap;
}
public void setStringMap(Map<String, String> stringMap) {
this.stringMap = stringMap;
}
String ip;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public List<ConvertRecord> getRecords() {
return records;
}
public void setRecords(List<ConvertRecord> records) {
this.records = records;
}
public Map<String, ConvertRecord> getRecordMap() {
return recordMap;
}
public void setRecordMap(Map<String, ConvertRecord> recordMap) {
this.recordMap = recordMap;
}
}

View File

@@ -0,0 +1,57 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import javax.persistence.Id;
import org.redkale.convert.json.JsonConvert;
/**
*
* @author zhangjx
*/
public class World implements Comparable<World> {
@Id
private int id;
private int randomNumber;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getRandomNumber() {
return randomNumber;
}
public void setRandomNumber(int randomNumber) {
this.randomNumber = randomNumber;
}
@Override
public int compareTo(World o) {
return Integer.compare(id, o.id);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static void main(String[] args) throws Throwable {
World[] worlds = new World[20];
int index = 8866;
for(int i =0;i<worlds.length;i++){
worlds[i] = new World();
worlds[i].setId(8866+i);
worlds[i].setRandomNumber(9966+i);
}
System.out.println(JsonConvert.root().convertTo(worlds));
}
}

View File

@@ -0,0 +1,49 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class _DyncFortuneJsonEncoder extends JsonDynEncoder<Fortune> {
protected final byte[] idFieldBytes = "\"id\":".getBytes();
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
public _DyncFortuneJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
}
@Override
public void convertTo(JsonWriter out, Fortune value) {
if (value == null) {
out.writeObjectNull(null);
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
return;
}
out.writeTo('{');
out.writeTo(idFieldBytes);
out.writeInt(value.getId());
String message = value.getMessage();
if (message != null) {
out.writeTo(messageCommaFieldBytes);
out.writeString(message);
}
out.writeTo('}');
}
}

View File

@@ -0,0 +1,51 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class _DyncMessageJsonEncoder extends JsonDynEncoder<Message> {
protected final byte[] messageFieldBytes = "\"message\":".getBytes();
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
public _DyncMessageJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
}
@Override
public void convertTo(JsonWriter out, Message value) {
if (value == null) {
out.writeObjectNull(null);
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
return;
}
out.writeTo('{');
boolean comma = false;
String message = value.getMessage();
if (message != null) {
if (comma) {
out.writeTo(messageCommaFieldBytes);
} else {
out.writeTo(messageFieldBytes);
comma = true;
}
out.writeLatin1To(true, message); //out.writeString(message);
}
out.writeTo('}');
}
}

View File

@@ -0,0 +1,47 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert;
import java.lang.reflect.Type;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class _DyncWorldJsonEncoder extends JsonDynEncoder<World> {
protected final byte[] idFieldBytes = "\"id\":".getBytes();
protected final byte[] randomNumberFieldBytes = ",\"randomNumber\":".getBytes();
public _DyncWorldJsonEncoder(JsonFactory factory, Type type) {
super(factory, type);
}
@Override
public void convertTo(JsonWriter out, World value) {
if (value == null) {
out.writeObjectNull(null);
return;
}
if (!out.isExtFuncEmpty()) {
objectEncoder.convertTo(out, value);
return;
}
out.writeTo('{');
boolean comma = false;
out.writeTo(idFieldBytes);
out.writeInt(value.getId());
out.writeTo(randomNumberFieldBytes);
out.writeInt(value.getRandomNumber());
out.writeTo('}');
}
}

View File

@@ -0,0 +1,117 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert.media;
/**
*
* @author redkale
*/
public class Image implements java.io.Serializable {
private static final long serialVersionUID = 1L;
public enum Size {
SMALL, LARGE
}
private String uri;
private String title; // Can be null
private int width;
private int height;
private Size size;
public Image() {
}
public Image(String uri, String title, int width, int height, Size size) {
this.height = height;
this.title = title;
this.uri = uri;
this.width = width;
this.size = size;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Image image = (Image) o;
if (height != image.height) return false;
if (width != image.width) return false;
if (size != image.size) return false;
if (title != null ? !title.equals(image.title) : image.title != null) return false;
return !(uri != null ? !uri.equals(image.uri) : image.uri != null);
}
@Override
public int hashCode() {
int result = uri != null ? uri.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + width;
result = 31 * result + height;
result = 31 * result + (size != null ? size.hashCode() : 0);
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[Image ");
sb.append("uri=").append((uri));
sb.append(", title=").append((title));
sb.append(", width=").append(width);
sb.append(", height=").append(height);
sb.append(", size=").append(size);
sb.append("]");
return sb.toString();
}
public void setUri(String uri) {
this.uri = uri;
}
public void setTitle(String title) {
this.title = title;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setSize(Size size) {
this.size = size;
}
public String getUri() {
return uri;
}
public String getTitle() {
return title;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Size getSize() {
return size;
}
}

View File

@@ -0,0 +1,203 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert.media;
import java.util.*;
/**
*
* @author redkale
*/
public class Media implements java.io.Serializable {
public enum Player {
JAVA, FLASH;
}
private String uri;
private String title; // Can be unset.
private int width;
private int height;
private String format;
private long duration;
private long size;
private int bitrate; // Can be unset.
private List<String> persons;
private Player player;
private String copyright; // Can be unset.
public Media() {
}
public Media(String uri, String title, int width, int height, String format, long duration, long size,
int bitrate, boolean hasBitrate, List<String> persons, Player player, String copyright) {
this.uri = uri;
this.title = title;
this.width = width;
this.height = height;
this.format = format;
this.duration = duration;
this.size = size;
this.bitrate = bitrate;
this.persons = persons;
this.player = player;
this.copyright = copyright;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Media media = (Media) o;
if (bitrate != media.bitrate) return false;
if (duration != media.duration) return false;
if (height != media.height) return false;
if (size != media.size) return false;
if (width != media.width) return false;
if (copyright != null ? !copyright.equals(media.copyright) : media.copyright != null) return false;
if (format != null ? !format.equals(media.format) : media.format != null) return false;
if (persons != null ? !persons.equals(media.persons) : media.persons != null) return false;
if (player != media.player) return false;
if (title != null ? !title.equals(media.title) : media.title != null) return false;
if (uri != null ? !uri.equals(media.uri) : media.uri != null) return false;
return true;
}
@Override
public int hashCode() {
int result = uri != null ? uri.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + width;
result = 31 * result + height;
result = 31 * result + (format != null ? format.hashCode() : 0);
result = 31 * result + (int) (duration ^ (duration >>> 32));
result = 31 * result + (int) (size ^ (size >>> 32));
result = 31 * result + bitrate;
result = 31 * result + (persons != null ? persons.hashCode() : 0);
result = 31 * result + (player != null ? player.hashCode() : 0);
result = 31 * result + (copyright != null ? copyright.hashCode() : 0);
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[Media ");
sb.append("uri=").append((uri));
sb.append(", title=").append((title));
sb.append(", width=").append(width);
sb.append(", height=").append(height);
sb.append(", format=").append((format));
sb.append(", duration=").append(duration);
sb.append(", size=").append(size);
sb.append(", bitrate=").append(String.valueOf(bitrate));
sb.append(", persons=").append((persons));
sb.append(", player=").append(player);
sb.append(", copyright=").append((copyright));
sb.append("]");
return sb.toString();
}
public void setUri(String uri) {
this.uri = uri;
}
public void setTitle(String title) {
this.title = title;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setFormat(String format) {
this.format = format;
}
public void setDuration(long duration) {
this.duration = duration;
}
public void setSize(long size) {
this.size = size;
}
public void setBitrate(int bitrate) {
this.bitrate = bitrate;
}
public void setPersons(List<String> persons) {
this.persons = persons;
}
public void setPlayer(Player player) {
this.player = player;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getUri() {
return uri;
}
public String getTitle() {
return title;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public String getFormat() {
return format;
}
public long getDuration() {
return duration;
}
public long getSize() {
return size;
}
public int getBitrate() {
return bitrate;
}
public List<String> getPersons() {
return persons;
}
public Player getPlayer() {
return player;
}
public String getCopyright() {
return copyright;
}
}

View File

@@ -0,0 +1,109 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.convert.media;
import java.util.*;
import org.redkale.convert.json.*;
import org.redkale.test.convert.*;
/**
*
* @author redkale
*/
public class MediaContent implements java.io.Serializable {
private Media media;
private List<Image> images;
public MediaContent() {
}
public MediaContent(Media media, List<Image> images) {
this.media = media;
this.images = images;
}
public static void main(String[] args) throws Exception {
final MediaContent entry = MediaContent.createDefault();
ConvertRecord.run(MediaContent.class, entry);
}
public static MediaContent createDefault() {
String str = "{"
+ " media : {"
+ " uri : \"http://javaone.com/keynote.mpg\" ,"
+ " title : \"Javaone Keynote\" ,"
+ " width : -640 ,"
+ " height : -480 ,"
+ " format : \"video/mpg4\","
+ " duration : -18000000 ,"
+ " size : -58982400 ,"
+ " bitrate : -262144 ,"
+ " persons : [\"Bill Gates\", \"Steve Jobs\"] ,"
+ " player : JAVA , "
+ " copyright : None"
+ " }, images : ["
+ " {"
+ " uri : \"http://javaone.com/keynote_large.jpg\","
+ " title : \"Javaone Keynote\","
+ " width : -1024,"
+ " height : -768,"
+ " size : LARGE"
+ " }, {"
+ " uri : \"http://javaone.com/keynote_small.jpg\", "
+ " title : \"Javaone Keynote\" , "
+ " width : -320 , "
+ " height : -240 , "
+ " size : SMALL"
+ " }"
+ " ]"
+ "}";
return JsonFactory.root().getConvert().convertFrom(MediaContent.class, str);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MediaContent that = (MediaContent) o;
if (images != null ? !images.equals(that.images) : that.images != null) return false;
return !(media != null ? !media.equals(that.media) : that.media != null);
}
@Override
public int hashCode() {
int result = media != null ? media.hashCode() : 0;
result = 31 * result + (images != null ? images.hashCode() : 0);
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[MediaContent: ");
sb.append("media=").append(media);
sb.append(", images=").append(images);
sb.append("]");
return sb.toString();
}
public void setMedia(Media media) {
this.media = media;
}
public void setImages(List<Image> images) {
this.images = images;
}
public Media getMedia() {
return media;
}
public List<Image> getImages() {
return images;
}
}

View File

@@ -0,0 +1,348 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.http;
import java.io.*;
import java.lang.reflect.Type;
import java.net.*;
import java.nio.charset.*;
import java.util.*;
import org.redkale.convert.json.*;
import org.redkale.net.http.*;
import org.redkale.util.AnyValue;
/**
*
* @author zhangjx
*/
public interface HttpRequestDesc {
//获取客户端地址IP
public SocketAddress getRemoteAddress();
//获取客户端地址IP, 与getRemoteAddres() 的区别在于:
//本方法优先取header中指定为RemoteAddress名的值没有则返回getRemoteAddres()的getHostAddress()。
//本方法适用于服务前端有如nginx的代理服务器进行中转通过getRemoteAddres()是获取不到客户端的真实IP。
public String getRemoteAddr();
//获取请求内容指定的编码字符串
public String getBody(Charset charset);
//获取请求内容的UTF-8编码字符串
public String getBodyUTF8();
//获取请求内容的byte[]
public byte[] getBody();
//获取请求内容的JavaBean对象
public <T> T getBodyJson(java.lang.reflect.Type type);
//获取请求内容的JavaBean对象
public <T> T getBodyJson(JsonConvert convert, java.lang.reflect.Type type);
//获取文件上传对象
public MultiContext getMultiContext();
//获取文件上传信息列表 等价于 getMultiContext().parts();
public Iterable<MultiPart> multiParts() throws IOException;
//设置当前用户信息, 通常在HttpServlet.preExecute方法里设置currentUser
//数据类型由@HttpUserType指定
public <T> HttpRequest setCurrentUser(T user);
//获取当前用户信息 数据类型由@HttpUserType指定
public <T> T currentUser();
//获取模块ID来自@HttpServlet.moduleid()
public int getModuleid();
//获取操作ID来自@HttpMapping.actionid()
public int getActionid();
//获取sessionid
public String getSessionid(boolean autoCreate);
//更新sessionid
public String changeSessionid();
//指定值更新sessionid
public String changeSessionid(String newsessionid);
//使sessionid失效
public void invalidateSession();
//获取所有Cookie对象
public java.net.HttpCookie[] getCookies();
//获取Cookie值
public String getCookie(String name);
//获取Cookie值 没有返回默认值
public String getCookie(String name, String defaultValue);
//获取协议名 http、https、ws、wss等
public String getProtocol();
//获取请求方法 GET、POST等
public String getMethod();
//获取Content-Type的header值
public String getContentType();
//获取请求内容的长度, 为-1表示内容长度不确定
public long getContentLength();
//获取Connection的Header值
public String getConnection();
//获取Host的Header值
public String getHost();
//获取请求的URL
public String getRequestURI();
//截取getRequestURI最后的一个/后面的部分
public String getRequstURILastPath();
// 获取请求URL最后的一个/后面的部分的short值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: short type = request.getRequstURILastPath((short)0); //type = 2
public short getRequstURILastPath(short defvalue);
// 获取请求URL最后的一个/后面的部分的short值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: short type = request.getRequstURILastPath((short)0); //type = 2
public short getRequstURILastPath(int radix, short defvalue);
// 获取请求URL最后的一个/后面的部分的int值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: int type = request.getRequstURILastPath(0); //type = 2
public int getRequstURILastPath(int defvalue);
// 获取请求URL最后的一个/后面的部分的int值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: int type = request.getRequstURILastPath(0); //type = 2
public int getRequstURILastPath(int radix, int defvalue);
// 获取请求URL最后的一个/后面的部分的float值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: float type = request.getRequstURILastPath(0.f); //type = 2.f
public float getRequstURILastPath(float defvalue);
// 获取请求URL最后的一个/后面的部分的long值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: long type = request.getRequstURILastPath(0L); //type = 2
public long getRequstURILastPath(long defvalue);
// 获取请求URL最后的一个/后面的部分的long值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: long type = request.getRequstURILastPath(0L); //type = 2
public long getRequstURILastPath(int radix, long defvalue);
// 获取请求URL最后的一个/后面的部分的double值 <br>
// 例如请求URL /pipes/record/query/2 <br>
// 获取type参数: double type = request.getRequstURILastPath(0.0); //type = 2.0
public double getRequstURILastPath(double defvalue);
//从prefix之后截取getRequestURI再对"/"进行分隔
public String[] getRequstURIPaths(String prefix);
// 获取请求URL分段中含prefix段的值
// 例如请求URL /pipes/record/query/name:hello
// 获取name参数: String name = request.getRequstURIPath("name:", "none");
public String getRequstURIPath(String prefix, String defaultValue);
// 获取请求URL分段中含prefix段的short值
// 例如请求URL /pipes/record/query/type:10
// 获取type参数: short type = request.getRequstURIPath("type:", (short)0);
public short getRequstURIPath(String prefix, short defaultValue);
// 获取请求URL分段中含prefix段的short值
// 例如请求URL /pipes/record/query/type:a
// 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); type = 10
public short getRequstURIPath(int radix, String prefix, short defvalue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:50
// 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
// 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
public int getRequstURIPath(String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:10
// 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
// 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
public int getRequstURIPath(int radix, String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的float值
// 例如请求URL /pipes/record/query/point:40.0
// 获取time参数: float point = request.getRequstURIPath("point:", 0.0f);
public float getRequstURIPath(String prefix, float defvalue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
// 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(String prefix, long defaultValue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
// 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(int radix, String prefix, long defvalue);
// 获取请求URL分段中含prefix段的double值 <br>
// 例如请求URL /pipes/record/query/point:40.0 <br>
// 获取time参数: double point = request.getRequstURIPath("point:", 0.0);
public double getRequstURIPath(String prefix, double defvalue);
//获取所有的header名
public AnyValue getHeaders();
//将请求Header转换成Map
public Map<String, String> getHeadersToMap(Map<String, String> map);
//获取所有的header名
public String[] getHeaderNames();
// 获取指定的header值
public String getHeader(String name);
//获取指定的header值, 没有返回默认值
public String getHeader(String name, String defaultValue);
//获取指定的header的json值
public <T> T getJsonHeader(Type type, String name);
//获取指定的header的json值
public <T> T getJsonHeader(JsonConvert convert, Type type, String name);
//获取指定的header的boolean值, 没有返回默认boolean值
public boolean getBooleanHeader(String name, boolean defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(String name, short defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(int radix, String name, short defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(String name, int defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(int radix, String name, int defaultValue);
//获取指定的header的int值, 没有返回默认int值
public int getIntHeader(String name, int defaultValue);
//获取指定的header的int值, 没有返回默认int值
public int getIntHeader(int radix, String name, int defaultValue);
// 获取指定的header的long值, 没有返回默认long值
public long getLongHeader(String name, long defaultValue);
// 获取指定的header的long值, 没有返回默认long值
public long getLongHeader(int radix, String name, long defaultValue);
// 获取指定的header的float值, 没有返回默认float值
public float getFloatHeader(String name, float defaultValue);
//获取指定的header的double值, 没有返回默认double值
public double getDoubleHeader(String name, double defaultValue);
//获取请求参数总对象
public AnyValue getParameters();
//将请求参数转换成Map
public Map<String, String> getParametersToMap(Map<String, String> map);
//将请求参数转换成String, 字符串格式为: bean1={}&amp;id=13&amp;name=xxx
//不会返回null没有参数返回空字符串
public String getParametersToString();
//将请求参数转换成String, 字符串格式为: prefix + bean1={}&amp;id=13&amp;name=xxx
//拼接前缀, 如果无参数,返回的字符串不会含有拼接前缀
//不会返回null没有参数返回空字符串
public String getParametersToString(String prefix);
//获取所有参数名
public String[] getParameterNames();
//获取指定的参数值
public String getParameter(String name);
//获取指定的参数值, 没有返回默认值
public String getParameter(String name, String defaultValue);
//获取指定的参数json值
public <T> T getJsonParameter(Type type, String name);
//获取指定的参数json值
public <T> T getJsonParameter(JsonConvert convert, Type type, String name);
//获取指定的参数boolean值, 没有返回默认boolean值
public boolean getBooleanParameter(String name, boolean defaultValue);
//获取指定的参数short值, 没有返回默认short值
public short getShortParameter(String name, short defaultValue);
//获取指定的参数short值, 没有返回默认short值
public short getShortParameter(int radix, String name, short defaultValue);
//获取指定的参数short值, 没有返回默认short值
public short getShortParameter(int radix, String name, int defaultValue);
//获取指定的参数int值, 没有返回默认int值
public int getIntParameter(String name, int defaultValue);
//获取指定的参数int值, 没有返回默认int值
public int getIntParameter(int radix, String name, int defaultValue);
//获取指定的参数long值, 没有返回默认long值
public long getLongParameter(String name, long defaultValue);
//获取指定的参数long值, 没有返回默认long值
public long getLongParameter(int radix, String name, long defaultValue);
//获取指定的参数float值, 没有返回默认float值
public float getFloatParameter(String name, float defaultValue);
//获取指定的参数double值, 没有返回默认double值
public double getDoubleParameter(String name, double defaultValue);
//获取翻页对象 同 getFlipper("flipper", false, 0);
public org.redkale.source.Flipper getFlipper();
//获取翻页对象 同 getFlipper("flipper", needcreate, 0);
public org.redkale.source.Flipper getFlipper(boolean needcreate);
//获取翻页对象 同 getFlipper("flipper", false, maxLimit);
public org.redkale.source.Flipper getFlipper(int maxLimit);
//获取翻页对象 同 getFlipper("flipper", needcreate, maxLimit)
public org.redkale.source.Flipper getFlipper(boolean needcreate, int maxLimit);
//获取翻页对象 http://redkale.org/pipes/records/list/offset:0/limit:20/sort:createtime%20ASC
//http://redkale.org/pipes/records/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
//以上两种接口都可以获取到翻页对象
public org.redkale.source.Flipper getFlipper(String name, boolean needcreate, int maxLimit);
//获取HTTP上下文对象
public HttpContext getContext();
//获取所有属性值, servlet执行完后会被清空
public Map<String, Object> getAttributes();
//获取指定属性值, servlet执行完后会被清空
public <T> T getAttribute(String name);
//删除指定属性
public void removeAttribute(String name);
//设置属性值, servlet执行完后会被清空
public void setAttribute(String name, Object value);
//获取request创建时间
public long getCreatetime();
}

View File

@@ -0,0 +1,175 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.http;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.CompletionHandler;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.*;
import org.redkale.convert.Convert;
import org.redkale.convert.json.*;
import org.redkale.net.http.*;
/**
*
* @author zhangjx
*/
public interface HttpResponseDesc {
//增加Cookie值
public HttpResponse addCookie(HttpCookie... cookies);
//增加Cookie值
public HttpResponse addCookie(Collection<HttpCookie> cookies);
//创建CompletionHandler实例将非字符串对象以JSON格式输出字符串以文本输出
public CompletionHandler createAsyncHandler();
//传入的CompletionHandler子类必须是public且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数
public <H extends CompletionHandler> H createAsyncHandler(Class<H> handlerClass);
//获取ByteBuffer生成器
public Supplier<ByteBuffer> getBufferSupplier();
//设置状态码
public void setStatus(int status);
//获取状态码
public int getStatus();
//获取 ContentType
public String getContentType();
//设置 ContentType
public HttpResponse setContentType(String contentType);
//获取内容长度
public long getContentLength();
//设置内容长度
public HttpResponse setContentLength(long contentLength);
//设置Header值
public HttpResponse setHeader(String name, Object value);
//添加Header值
public HttpResponse addHeader(String name, Object value);
//添加Header值
public HttpResponse addHeader(Map<String, ?> map);
//跳过header的输出
//通常应用场景是调用者的输出内容里已经包含了HTTP的响应头信息因此需要调用此方法避免重复输出HTTP响应头信息。
public HttpResponse skipHeader();
//异步输出指定内容
public <A> void sendBody(ByteBuffer buffer, A attachment, CompletionHandler<Integer, A> handler);
//异步输出指定内容
public <A> void sendBody(ByteBuffer[] buffers, A attachment, CompletionHandler<Integer, A> handler);
//关闭HTTP连接如果是keep-alive则不强制关闭
public void finish();
//强制关闭HTTP连接
public void finish(boolean kill);
//将对象以JSON格式输出
public void finishJson(Object obj);
//将对象数组用Map的形式以JSON格式输出
//例如: finishMap("a",2,"b",3) 输出结果为 {"a":2,"b":3}
public void finishMapJson(final Object... objs);
//将对象以JSON格式输出
public void finishJson(JsonConvert convert, Object obj);
//将对象数组用Map的形式以JSON格式输出
//例如: finishMap("a",2,"b",3) 输出结果为 {"a":2,"b":3}
public void finishMapJson(final JsonConvert convert, final Object... objs);
//将对象以JSON格式输出
public void finishJson(Type type, Object obj);
//将对象以JSON格式输出
public void finishJson(final JsonConvert convert, final Type type, final Object obj);
//将对象以JSON格式输出
public void finishJson(final Object... objs);
//将RetResult对象以JSON格式输出
public void finishJson(final org.redkale.service.RetResult ret);
//将RetResult对象以JSON格式输出
public void finishJson(final JsonConvert convert, final org.redkale.service.RetResult ret);
//将CompletableFuture的结果对象以JSON格式输出
public void finishJson(final CompletableFuture future);
//将CompletableFuture的结果对象以JSON格式输出
public void finishJson(final JsonConvert convert, final CompletableFuture future);
//将CompletableFuture的结果对象以JSON格式输出
public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future);
//将HttpResult的结果对象以JSON格式输出
public void finishJson(final HttpResult result);
//将HttpResult的结果对象以JSON格式输出
public void finishJson(final JsonConvert convert, final HttpResult result);
//将指定字符串以响应结果输出
public void finish(String obj);
//以指定响应码附带内容输出, message 可以为null
public void finish(int status, String message);
//将结果对象输出
public void finish(final Object obj);
//将结果对象输出
public void finish(final Convert convert, final Object obj);
//将结果对象输出
public void finish(final Convert convert, final Type type, final Object obj);
//以304状态码输出
public void finish304();
//以404状态码输出
public void finish404();
//将指定byte[]按响应结果输出
public void finish(final byte[] bs);
//将指定ByteBuffer按响应结果输出
public void finish(ByteBuffer buffer);
//将指定ByteBuffer按响应结果输出
//kill 输出后是否强制关闭连接
public void finish(boolean kill, ByteBuffer buffer);
//将指定ByteBuffer数组按响应结果输出
public void finish(ByteBuffer... buffers);
//将指定ByteBuffer数组按响应结果输出
//kill 输出后是否强制关闭连接
public void finish(boolean kill, ByteBuffer... buffers);
//将指定文件按响应结果输出
public void finish(File file) throws IOException;
//将文件按指定文件名输出
public void finish(final String filename, File file) throws IOException;
//HttpResponse回收时回调的监听方法
public void recycleListener(BiConsumer<HttpRequest, HttpResponse> recycleListener);
}

View File

@@ -0,0 +1,36 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.http;
import java.net.Socket;
/**
*
* @author zhangjx
*/
public class SocketMain {
public static void main(String[] args) throws Throwable {
Socket socket = new Socket("127.0.0.1", 6060);
socket.getOutputStream().write("GET /json1 HTTP/1.1\r\nAccpet: aaa\r\nConnection: keep-alive\r\n\r\nGET /json2 HTTP/1.1\r\nAccpet: a".getBytes());
socket.getOutputStream().flush();
Thread.sleep(1000);
socket.getOutputStream().write("aa\r\nConnection: keep-alive\r\n\r".getBytes());
socket.getOutputStream().flush();
Thread.sleep(1000);
socket.getOutputStream().write("\nGET /json3 HTTP/1.1\r\nAccpet: aaa\r\nConnection: keep-alive\r\n\r".getBytes());
socket.getOutputStream().flush();
Thread.sleep(1000);
socket.getOutputStream().write("\n".getBytes());
socket.getOutputStream().flush();
byte[] bs = new byte[10240];
int rs = socket.getInputStream().read(bs);
System.out.println(new String(bs, 0, rs));
rs = socket.getInputStream().read(bs);
System.out.println(new String(bs, 0, rs));
}
}

View File

@@ -0,0 +1,50 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.http;
import org.redkale.net.http.HttpServlet;
import org.redkale.net.http.MultiPart;
import org.redkale.net.http.HttpRequest;
import org.redkale.net.http.HttpResponse;
import java.io.*;
/**
*
* @author zhangjx
*/
//@WebServlet({"/uploadtest/form", "/uploadtest/send"})
public class UploadTestServlet extends HttpServlet {
@Override
public void execute(HttpRequest request, HttpResponse response) throws IOException {
if (request.getRequestURI().contains("/uploadtest/send")) {
send(request, response);
} else {
form(request, response);
}
}
public void form(HttpRequest req, HttpResponse resp) throws IOException {
resp.setContentType("text/html");
resp.finish(
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/></head>"
+ "<div style='margin-top:150px;margin-left:400px;'><form action=\"/pipes/uploadtest/send\" method=\"post\" enctype=\"multipart/form-data\">"
+ "描述: <input name=\"desc1\"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;文件1: <input type=\"file\" name=\"filepath1\"/><br/><br/>"
+ "描述: <input name=\"desc2\"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;文件2: <input type=\"file\" name=\"filepath2\"/><br/><br/>"
+ "描述: <input name=\"desc3\"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;文件3: <input type=\"file\" name=\"filepath3\"/><br/><br/>"
+ "描述: <input name=\"desc4\"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>"
+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" value=\"Submit\"/></form></div>"
+ "</html>");
}
public void send(HttpRequest req, HttpResponse resp) throws IOException {
for (MultiPart entry : req.multiParts()) {
entry.skip();
System.out.println(entry);
}
System.exit(0);
}
}

View File

@@ -0,0 +1,204 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.http;
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.redkale.convert.Convert;
import org.redkale.net.http.*;
/**
*
* @author zhangjx
*/
public interface WebSocketDesc<G, T> {
//给自身发送消息, 消息类型是String或byte[]或可JavaBean对象 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> send(Object message);
//给自身发送消息, 消息类型是key-value键值对 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMap(Object... messages);
//给自身发送消息, 消息类型是String或byte[]或可JavaBean对象 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> send(Object message, boolean last);
//给自身发送消息, 消息类型是key-value键值对 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMap(boolean last, Object... messages);
//给自身发送消息, 消息类型是JavaBean对象 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> send(Convert convert, Object message);
//给自身发送消息, 消息类型是JavaBean对象 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> send(Convert convert, Object message, boolean last);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Object message, G... userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Object message, Stream<G> userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Convert convert, Object message, G... userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Convert convert, Object message, Stream<G> userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Object message, boolean last, G... userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Object message, boolean last, Stream<G> userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Convert convert, Object message, boolean last, G... userids);
//给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendMessage(Convert convert, Object message, boolean last, Stream<G> userids);
//给所有人广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final Object message);
//给所有人广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final Convert convert, final Object message);
//给符合条件的人群广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final WebSocketRange wsrange, final Object message);
//给符合条件的人群广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final WebSocketRange wsrange, final Convert convert, final Object message);
//给所有人广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final Object message, boolean last);
//给所有人广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final Convert convert, final Object message, boolean last);
//给符合条件的人群广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(final WebSocketRange wsrange, final Object message, boolean last);
//给符合条件的人群广播消息, 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> broadcastMessage(WebSocketRange wsrange, Convert convert, final Object message, boolean last);
//给指定userid的WebSocket节点发送操作
public CompletableFuture<Integer> sendAction(final WebSocketAction action, Serializable... userids);
//广播操作, 给所有人发操作指令
public CompletableFuture<Integer> broadcastAction(final WebSocketAction action);
//获取用户在线的SNCP节点地址列表不是分布式则返回元素数量为1且元素值为null的列表
public CompletableFuture<Collection<InetSocketAddress>> getRpcNodeAddresses(final Serializable userid);
//获取在线用户的详细连接信息
public CompletableFuture<Map<InetSocketAddress, List<String>>> getRpcNodeWebSocketAddresses(final Serializable userid);
//发送PING消息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendPing();
//发送PING消息附带其他信息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendPing(byte[] data);
//发送PONG消息附带其他信息 返回结果0表示成功非0表示错误码
public CompletableFuture<Integer> sendPong(byte[] data);
//强制关闭用户的所有WebSocket
public CompletableFuture<Integer> forceCloseWebSocket(Serializable userid);
//更改本WebSocket的userid
public CompletableFuture<Void> changeUserid(final G newuserid);
//获取指定userid的WebSocket数组, 没有返回null 此方法用于单用户多连接模式
/* protected */ Stream<WebSocket> getLocalWebSockets(G userid);
//获取指定userid的WebSocket数组, 没有返回null 此方法用于单用户单连接模式
/* protected */ WebSocket findLocalWebSocket(G userid);
//获取当前进程节点所有在线的WebSocket
/* protected */ Collection<WebSocket> getLocalWebSockets();
//获取ByteBuffer资源池
/* protected */ Supplier<ByteBuffer> getByteBufferSupplier();
//返回sessionid, null表示连接不合法或异常,默认实现是request.sessionid(true),通常需要重写该方法
/* protected */ CompletableFuture<String> onOpen(final HttpRequest request);
//创建userid null表示异常 必须实现该方法
/* protected abstract */ CompletableFuture<G> createUserid();
//WebSocket.broadcastMessage时的过滤条件
/* protected */ boolean predicate(WebSocketRange wsrange);
//WebSokcet连接成功后的回调方法
public void onConnected();
//ping后的回调方法
public void onPing(byte[] bytes);
//pong后的回调方法
public void onPong(byte[] bytes);
//接收到消息的回调方法
public void onMessage(T message, boolean last);
//接收到文本消息的回调方法
public void onMessage(String message, boolean last);
//接收到二进制消息的回调方法
public void onMessage(byte[] bytes, boolean last);
//关闭的回调方法调用此方法时WebSocket已经被关闭
public void onClose(int code, String reason);
//获取当前WebSocket下的属性
public T getAttribute(String name);
//移出当前WebSocket下的属性
public T removeAttribute(String name);
//给当前WebSocket下的增加属性
public void setAttribute(String name, Object value);
//获取当前WebSocket所属的userid
public G getUserid();
//获取当前WebSocket的会话ID 不会为null
public Serializable getSessionid();
//获取客户端直接地址, 当WebSocket连接是由代理服务器转发的则该值固定为代理服务器的IP地址
public SocketAddress getRemoteAddress();
//获取客户端真实地址 同 HttpRequest.getRemoteAddr()
public String getRemoteAddr();
//获取WebSocket创建时间
public long getCreatetime();
//获取最后一次发送消息的时间
public long getLastSendTime();
//获取最后一次读取消息的时间
public long getLastReadTime();
//获取最后一次ping的时间
public long getLastPingTime();
//显式地关闭WebSocket
public void close();
//WebSocket是否已关闭
public boolean isClosed();
}

View File

@@ -0,0 +1,74 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.net;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import org.redkale.net.*;
import org.redkale.net.http.HttpServer;
import org.redkale.net.sncp.Sncp;
import org.redkale.util.AnyValue.DefaultAnyValue;
/**
*
* @author zhangjx
*/
public class TransportTest {
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
public static void main(String[] args) throws Throwable {
System.setProperty("net.transport.checkinterval", "2");
List<InetSocketAddress> addrs = new ArrayList<>();
addrs.add(new InetSocketAddress("127.0.0.1", 22001));
addrs.add(new InetSocketAddress("127.0.0.1", 22002));
addrs.add(new InetSocketAddress("127.0.0.1", 22003));
addrs.add(new InetSocketAddress("127.0.0.1", 22004));
for (InetSocketAddress servaddr : addrs) {
//if (servaddr.getPort() % 100 == 4) continue;
HttpServer server = new HttpServer();
DefaultAnyValue servconf = DefaultAnyValue.create("port", servaddr.getPort());
server.init(servconf);
server.start();
}
addrs.add(new InetSocketAddress("127.0.0.1", 22005));
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
Thread.sleep(1000);
TransportFactory factory = TransportFactory.create(asyncGroup, 0, 0);
DefaultAnyValue conf = DefaultAnyValue.create(TransportFactory.NAME_PINGINTERVAL, 5);
factory.init(conf, Sncp.PING_BUFFER, Sncp.PONG_BUFFER.remaining());
Transport transport = factory.createTransportTCP("", null, addrs);
System.out.println(String.format(format, System.currentTimeMillis()));
try {
CountDownLatch cdl = new CountDownLatch(20);
for (int i = 0; i < 20; i++) {
transport.pollConnection(null).whenComplete((r, t) -> {
cdl.countDown();
System.out.println("连接: " + r.getRemoteAddress());
});
}
cdl.await();
HttpServer server = new HttpServer();
DefaultAnyValue servconf = DefaultAnyValue.create("port", 22005);
server.init(servconf);
server.start();
Thread.sleep(4000);
CountDownLatch cdl2 = new CountDownLatch(20);
for (int i = 0; i < 20; i++) {
transport.pollConnection(null).whenComplete((r, t) -> {
cdl2.countDown();
System.out.println("连接: " + r.getRemoteAddress());
});
}
cdl2.await();
} finally {
System.out.println(String.format(format, System.currentTimeMillis()));
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import java.text.SimpleDateFormat;
import org.redkale.convert.*;
/**
*
* @author zhangjx
* @param <R> R
* @param <W> W
*/
public class CreateTimeSimpleCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Long> {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void convertTo(W out, Long value) {
if (value == null) {
out.writeNull();
} else {
out.writeString(format.format(new java.util.Date(value)));
}
}
@Override
public Long convertFrom(R in) {
String val = in.readString();
if (val == null) return 0L;
try {
return format.parse(val).getTime();
} catch (Exception e) {
return 0L;
}
}
}

View File

@@ -0,0 +1,26 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import java.nio.channels.CompletionHandler;
/**
*
* @author zhangjx
*/
public class HelloAsyncHandler implements CompletionHandler {
@Override
public void completed(Object result, Object attachment) {
System.out.println("-----HelloAsyncHandler--------result : " + result + ", attachment: " + attachment);
}
@Override
public void failed(Throwable exc, Object attachment) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

View File

@@ -0,0 +1,69 @@
package org.redkale.test.rest;
import org.redkale.convert.json.JsonFactory;
import org.redkale.net.http.*;
import org.redkale.source.FilterBean;
public class HelloBean implements FilterBean {
private int helloid;
@RestHeader(name = "User-Agent")
private String useragent; //从Http Header中获取浏览器信息
@RestCookie(name = "hello-cookie")
private String rescookie; //从Cookie中获取名为hello-cookie的值
@RestAddress
private String clientaddr; //客户端请求IP
@RestSessionid
private String sessionid; //用户Sessionid, 未登录时为null
/** 以下省略getter setter方法 */
public int getHelloid() {
return helloid;
}
public void setHelloid(int helloid) {
this.helloid = helloid;
}
public String getUseragent() {
return useragent;
}
public void setUseragent(String useragent) {
this.useragent = useragent;
}
public String getRescookie() {
return rescookie;
}
public void setRescookie(String rescookie) {
this.rescookie = rescookie;
}
public String getClientaddr() {
return clientaddr;
}
public void setClientaddr(String clientaddr) {
this.clientaddr = clientaddr;
}
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,152 @@
package org.redkale.test.rest;
import java.util.Map;
import javax.persistence.Id;
import org.redkale.convert.json.JsonFactory;
import org.redkale.net.http.*;
import org.redkale.source.VirtualEntity;
@VirtualEntity
public class HelloEntity {
@Id
private int helloid;
private String helloname;
private int creator;
private long updatetime;
private long createtime;
@RestHeader(name = "hello-res")
private String resname;
@RestBody
private String bodystr;
@RestBody
private byte[] bodys;
@RestUploadFile
private byte[] uploads;
@RestBody
private Map<String, String> bodymap;
@RestAddress
private String clientaddr;
@RestURI
private String uri;
public HelloEntity() {
}
public HelloEntity(int id) {
this.helloid = id;
}
/** 以下省略getter setter方法 */
public int getHelloid() {
return helloid;
}
public void setHelloid(int helloid) {
this.helloid = helloid;
}
public String getHelloname() {
return helloname;
}
public void setHelloname(String helloname) {
this.helloname = helloname;
}
public long getUpdatetime() {
return updatetime;
}
public void setUpdatetime(long updatetime) {
this.updatetime = updatetime;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
public int getCreator() {
return creator;
}
public void setCreator(int creator) {
this.creator = creator;
}
public String getClientaddr() {
return clientaddr;
}
public void setClientaddr(String clientaddr) {
this.clientaddr = clientaddr;
}
public String getResname() {
return resname;
}
public void setResname(String resname) {
this.resname = resname;
}
public String getBodystr() {
return bodystr;
}
public void setBodystr(String bodystr) {
this.bodystr = bodystr;
}
public byte[] getBodys() {
return bodys;
}
public void setBodys(byte[] bodys) {
this.bodys = bodys;
}
public Map<String, String> getBodymap() {
return bodymap;
}
public void setBodymap(Map<String, String> bodymap) {
this.bodymap = bodymap;
}
public byte[] getUploads() {
return uploads;
}
public void setUploads(byte[] uploads) {
this.uploads = uploads;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,124 @@
package org.redkale.test.rest;
import java.nio.channels.CompletionHandler;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.DataSource;
import org.redkale.source.Flipper;
import org.redkale.util.*;
/**
* 类说明:
* Flipper : Source组件中的翻页对象
* UserInfo :当前用户类
* HelloEntity: Hello模块的实体类
* HelloBean: Hello模块实现FilterBean的过滤Bean类
*
*/
@RestService(automapping = true)
public class HelloService implements Service {
private int nodeid;
@Resource
private DataSource source;
public HelloService() {
}
public HelloService(int nodeid) {
this.nodeid = nodeid;
}
//增加记录
public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity, @RestBody Map<String, String> body) {
System.out.println("增加记录----------------" + nodeid + ": body =" + body + ", entity =" + entity);
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
if (source != null) source.insert(entity);
return new RetResult<>(entity);
}
//
public HttpResult showHello(int id) {
return new HttpResult("a");
}
//删除记录
public void deleteHello(int id) { //通过 /pipes/hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
public void updateHello(@RestAddress String clientAddr, HelloEntity entity) { //通过 /pipes/hello/update?bean={...} 修改对象
System.out.println("修改记录-" + nodeid + ": clientAddr = " + clientAddr + ", entity =" + entity);
if (entity != null) entity.setUpdatetime(System.currentTimeMillis());
if (source != null) source.update(entity);
}
//修改记录
public void update2Hello(@RestAddress String clientAddr, @RestUploadFile byte[] fs) { //通过 /pipes/hello/update2?bean={...} 修改对象
System.out.println("修改记录2-" + nodeid + ": clientAddr = " + clientAddr + ", fs =" + fs);
}
//修改记录
@RestMapping(name = "partupdate")
public void updateHello(HelloEntity entity, @RestParam(name = "cols") String[] columns) { //通过 /pipes/hello/partupdate?bean={...}&cols=... 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.updateColumn(entity, columns);
}
//查询Sheet列表
public Sheet<HelloEntity> queryHello(HelloBean bean, Flipper flipper) { //通过 /pipes/hello/query/offset:0/limit:20?bean={...} 查询Sheet列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询List列表
@RestMapping(name = "list")
@RestConvert(type = HelloEntity.class, ignoreColumns = {"createtime"})
public List<HelloEntity> queryHello(HelloBean bean) { //通过 /pipes/hello/list?bean={...} 查询List列表
return source.queryList(HelloEntity.class, bean);
}
//查询List列表
@RestMapping(name = "listmap")
public List<HelloEntity> queryHello(HelloBean bean, @RestParam(name = "map") Map<String, String> map) { //通过 /pipes/hello/list?bean={...} 查询List列表
System.out.println("map参数: " + map);
if (source != null) return source.queryList(HelloEntity.class, bean);
return new ArrayList<>();
}
//查询单个
@RestMapping(name = "find")
public HelloEntity findHello(@RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
return source.find(HelloEntity.class, id);
}
//异步查询单个
@RestMapping(name = "asyncfind")
public CompletableFuture<HelloEntity> asyncFindHello(@RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
if (source != null) source.findAsync(HelloEntity.class, id);
System.out.println("------------进入asyncfind1-------");
return CompletableFuture.completedFuture(new HelloEntity());
}
//异步查询单个
@RestMapping(name = "asyncfind2")
public void asyncFindHello(CompletionHandler hander, @RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
if (source != null) source.findAsync(HelloEntity.class, id);
System.out.println("-----------进入asyncfind2--------" + hander);
hander.completed(new HelloEntity(id), id);
}
//异步查询单个
@RestMapping(name = "asyncfind3")
public void asyncFindHello(HelloAsyncHandler hander, @RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
if (source != null) source.findAsync(HelloEntity.class, id);
System.out.println("-----------进入asyncfind3--------" + hander);
hander.completed(new HelloEntity(id), id);
}
}

View File

@@ -0,0 +1,62 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.*;
import org.redkale.util.Sheet;
/**
* 类说明:
* Flipper : Source组件中的翻页对象
* UserInfo :当前用户类
* HelloEntity: Hello模块的实体类
* HelloBean: Hello模块实现FilterBean的过滤Bean类
*
*/
@RestService(name = "hello", moduleid = 0, automapping = true, repair = true, ignore = false, comment = "Hello服务模块")
public class HelloService2 implements Service {
@Resource
private DataSource source;
//增加记录
@RestMapping(name = "create", auth = false, comment = "创建Hello对象")
public RetResult<HelloEntity> createHello(UserInfo info, @RestParam(name = "bean", comment = "Hello对象") HelloEntity entity) {
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
source.insert(entity);
return new RetResult<>(entity);
}
//删除记录
@RestMapping(name = "delete", auth = false, comment = "根据id删除Hello对象")
public void deleteHello(@RestParam(name = "#", comment = "Hello对象id") int id) { //通过 /hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
@RestMapping(name = "update", auth = false, comment = "修改Hello对象")
public void updateHello(@RestParam(name = "bean", comment = "Hello对象") HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.update(entity);
}
//查询列表
@RestConvertCoder(type = HelloEntity.class, field = "createtime", coder = CreateTimeSimpleCoder.class)
@RestMapping(name = "query", auth = false, comment = "查询Hello对象列表")
public Sheet<HelloEntity> queryHello(@RestParam(name = "bean", comment = "过滤条件") HelloBean bean, Flipper flipper) { //通过 /hello/query/offset:0/limit:20?bean={...} 查询列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询单个
@RestMapping(name = "find", auth = false, comment = "根据id查找单个Hello对象")
public HelloEntity findHello(@RestParam(name = "#", comment = "Hello对象id") int id) { //通过 /hello/find/1234 查询对象
return source.find(HelloEntity.class, id);
}
}

View File

@@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import org.redkale.convert.json.JsonFactory;
/**
*
* @author zhangjx
*/
public class LoginBean {
private String account = "";
private String password = "";
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,163 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import java.lang.reflect.*;
import java.util.*;
import org.redkale.service.*;
/**
*
* @author zhangjx
*/
public abstract class RetCodes {
protected static final Map<Integer, String> rets = new HashMap<>();
protected RetCodes() {
}
//-----------------------------------------------------------------------------------------------------------
protected static void load(Class clazz) {
for (Field field : clazz.getFields()) {
if (!Modifier.isStatic(field.getModifiers())) continue;
if (field.getType() != int.class) continue;
RetLabel info = field.getAnnotation(RetLabel.class);
if (info == null) continue;
int value;
try {
value = field.getInt(null);
} catch (Exception ex) {
ex.printStackTrace();
continue;
}
rets.put(value, info.value());
}
}
public static RetResult retResult(int retcode) {
if (retcode == 0) return RetResult.success();
return new RetResult(retcode, retInfo(retcode));
}
public static String retInfo(int retcode) {
if (retcode == 0) return "成功";
return rets.getOrDefault(retcode, "未知错误");
}
//2000_0001 - 2999_9999 预留给 Redkale的扩展包redkalex使用
//3000_0001 - 7999_9999 为平台系统使用
//8000_0001 - 9999_9999 为OSS系统使用
//------------------------------------- 通用模块 -----------------------------------------
@RetLabel("参数无效")
public static final int RET_PARAMS_ILLEGAL = 30010001;
@RetLabel("无上传文件")
public static final int RET_UPLOAD_NOFILE = 30010002;
@RetLabel("上传文件过大")
public static final int RET_UPLOAD_FILETOOBIG = 30010003;
@RetLabel("上传文件不是图片")
public static final int RET_UPLOAD_NOTIMAGE = 30010004;
//------------------------------------- 用户模块 -----------------------------------------
@RetLabel("未登录")
public static final int RET_USER_UNLOGIN = 30020001;
@RetLabel("用户登录失败")
public static final int RET_USER_LOGIN_FAIL = 30020002;
@RetLabel("用户或密码错误")
public static final int RET_USER_ACCOUNT_PWD_ILLEGAL = 30020003;
@RetLabel("密码设置无效")
public static final int RET_USER_PASSWORD_ILLEGAL = 30020004;
@RetLabel("用户被禁用")
public static final int RET_USER_FREEZED = 30020005;
@RetLabel("用户权限不够")
public static final int RET_USER_AUTH_ILLEGAL = 30020006;
@RetLabel("用户不存在")
public static final int RET_USER_NOTEXISTS = 30020007;
@RetLabel("用户状态异常")
public static final int RET_USER_STATUS_ILLEGAL = 30020008;
@RetLabel("用户注册参数无效")
public static final int RET_USER_SIGNUP_ILLEGAL = 30020009;
@RetLabel("用户性别参数无效")
public static final int RET_USER_GENDER_ILLEGAL = 30020010;
@RetLabel("用户名无效")
public static final int RET_USER_USERNAME_ILLEGAL = 30020011;
@RetLabel("用户账号无效")
public static final int RET_USER_ACCOUNT_ILLEGAL = 30020012;
@RetLabel("用户账号已存在")
public static final int RET_USER_ACCOUNT_EXISTS = 30020013;
@RetLabel("手机号码无效")
public static final int RET_USER_MOBILE_ILLEGAL = 30020014;
@RetLabel("手机号码已存在")
public static final int RET_USER_MOBILE_EXISTS = 30020015;
@RetLabel("手机验证码发送过于频繁")
public static final int RET_USER_MOBILE_SMSFREQUENT = 30020016;
@RetLabel("邮箱地址无效")
public static final int RET_USER_EMAIL_ILLEGAL = 30020017;
@RetLabel("邮箱地址已存在")
public static final int RET_USER_EMAIL_EXISTS = 30020018;
@RetLabel("微信绑定号无效")
public static final int RET_USER_WXID_ILLEGAL = 30020019;
@RetLabel("微信绑定号已存在")
public static final int RET_USER_WXID_EXISTS = 30020020;
@RetLabel("绑定微信号失败")
public static final int RET_USER_WXID_BIND_FAIL = 30020021;
@RetLabel("QQ绑定号无效")
public static final int RET_USER_QQID_ILLEGAL = 30020022;
@RetLabel("QQ绑定号已存在")
public static final int RET_USER_QQID_EXISTS = 30020023;
@RetLabel("绑定QQ号失败")
public static final int RET_USER_QQID_BIND_FAIL = 30020024;
@RetLabel("获取绑定QQ信息失败")
public static final int RET_USER_QQID_INFO_FAIL = 30020025;
@RetLabel("验证码无效")
public static final int RET_USER_RANDCODE_ILLEGAL = 30020026; //邮件或者短信验证码
@RetLabel("验证码已过期")
public static final int RET_USER_RANDCODE_EXPIRED = 30020027; //邮件或者短信验证码
@RetLabel("验证码错误或失效")
public static final int RET_USER_CAPTCHA_ILLEGAL = 30020028; //图片验证码
@RetLabel("用户类型无效")
public static final int RET_USER_TYPE_ILLEGAL = 30020029;
@RetLabel("用户设备ID无效")
public static final int RET_USER_APPTOKEN_ILLEGAL = 30020030;
static {
load(RetCodes.class);
}
}

View File

@@ -0,0 +1,39 @@
package org.redkale.test.rest;
import java.io.IOException;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
public class SimpleRestServlet extends HttpServlet {
protected static final RetResult RET_UNLOGIN = RetCodes.retResult(RetCodes.RET_USER_UNLOGIN);
protected static final RetResult RET_AUTHILLEGAL = RetCodes.retResult(RetCodes.RET_USER_AUTH_ILLEGAL);
@Resource
private UserService userService = new UserService();
@Override
public void preExecute(HttpRequest request, HttpResponse response) throws IOException {
final String sessionid = request.getSessionid(true);
if (sessionid != null) {
UserInfo user = userService.current(sessionid);
if (user != null) request.setCurrentUserid(user.getUserid());
}
response.nextEvent();
}
//普通鉴权
@Override
public void authenticate(HttpRequest request, HttpResponse response) throws IOException {
int userid = request.currentUserid(int.class);
if (userid < 1) {
response.finishJson(RET_UNLOGIN);
return;
}
response.nextEvent();
}
}

View File

@@ -0,0 +1,44 @@
package org.redkale.test.rest;
import javax.persistence.Id;
import org.redkale.convert.json.JsonFactory;
/**
* 当前用户对象
*
* @author zhangjx
*/
public class UserInfo {
@Id
private int userid;
private String username = "";
public int getUserid() {
return userid;
}
public boolean checkAuth(int moduleid, int actionid) {
if (moduleid == 0 || actionid == 0) return true;
//权限判断
return true;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import org.redkale.service.*;
/**
* 简单的定义UserService接口
*
* @author zhangjx
*/
public class UserService implements Service {
//根据登录态获取当前用户信息
public UserInfo current(String sessionid) {
return new UserInfo();
}
public RetResult<UserInfo> login(LoginBean bean) {
return new RetResult<>(new UserInfo());
}
}

View File

@@ -0,0 +1,156 @@
package org.redkale.test.rest;
import java.io.IOException;
import java.util.*;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.source.Flipper;
import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue;
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet1 extends SimpleRestServlet {
@Resource
private HelloService _redkale_service;
@Resource
private Map<String, HelloService> _redkale_servicemap;
public static void main(String[] args) throws Throwable {
final int port = 8888;
HelloService service = new HelloService();
HttpServer server = new HttpServer();
System.out.println(server.addRestServlet(null, service, null, SimpleRestServlet.class, "/pipes"));
System.out.println(server.addRestServlet(null, new HelloService(3), null, SimpleRestServlet.class, "/pipes"));
DefaultAnyValue conf = DefaultAnyValue.create("port", "" + port);
server.init(conf);
server.start();
Thread.sleep(100);
HelloEntity entity = new HelloEntity();
entity.setHelloname("my name");
Map<String, String> headers = new HashMap<>();
headers.put("hello-res", "my res");
//headers.put(Rest.REST_HEADER_RESOURCE_NAME, "my-res");
String url = "http://127.0.0.1:" + port + "/pipes/hello/update?entity={}&bean2={}";
System.out.println(Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/update2?entity={}&bean2={}";
System.out.println(Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/1234";
System.out.println("异步查找: " + Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/listmap?map={'a':5}";
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/create?entity={}";
System.out.println("增加记录: " + Utility.postHttpContent(url, headers, "{'a':2,'b':3}"));
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/111111";
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind2/22222";
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind3/333333";
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
}
@HttpMapping(url = "/hello/create", auth = false)
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setResname(req.getHeader("hello-res"));
UserInfo user = new UserInfo();
RetResult<HelloEntity> result = service.createHello(user, bean, req.getBodyJson(Map.class));
resp.finishJson(result);
}
@HttpMapping(url = "/hello/delete/", auth = false)
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.deleteHello(id);
resp.finishJson(RetResult.success());
}
@HttpMapping(url = "/hello/update", auth = false)
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
String clientaddr = req.getRemoteAddr();
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setResname(req.getHeader("hello-res"));
service.updateHello(clientaddr, bean);
resp.finishJson(RetResult.success());
}
@HttpMapping(url = "/hello/partupdate", auth = false)
public void partupdate(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setResname(req.getHeader("hello-res"));
String[] cols = req.getJsonParameter(String[].class, "cols");
service.updateHello(bean, cols);
resp.finishJson(RetResult.success());
}
@HttpMapping(url = "/hello/query", auth = false)
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setUseragent(req.getHeader("User-Agent"));
bean.setRescookie(req.getCookie("hello-cookie"));
bean.setSessionid(req.getSessionid(false));
Flipper flipper = req.getFlipper();
Sheet<HelloEntity> result = service.queryHello(bean, flipper);
resp.finishJson(result);
}
@HttpMapping(url = "/hello/list", auth = false)
public void list(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setUseragent(req.getHeader("User-Agent"));
bean.setRescookie(req.getCookie("hello-cookie"));
bean.setSessionid(req.getSessionid(false));
List<HelloEntity> result = service.queryHello(bean);
resp.finishJson(result);
}
@HttpMapping(url = "/hello/find/", auth = false)
public void find(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = service.findHello(id);
resp.finishJson(bean);
}
@HttpMapping(url = "/hello/asyncfind/", auth = false)
public void asyncfind(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
resp.finishJson(service.asyncFindHello(id));
}
@HttpMapping(url = "/hello/asyncfind2/", auth = false)
public void asyncfind2(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.asyncFindHello(resp.createAsyncHandler(), id);
}
@HttpMapping(url = "/hello/asyncfind3/", auth = false)
public void asyncfind3(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.asyncFindHello(resp.createAsyncHandler(HelloAsyncHandler.class), id);
}
}

View File

@@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.rest;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.source.Flipper;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet2 extends SimpleRestServlet {
@Resource
private HelloService2 _redkale_service;
@Resource
private Map<String, HelloService2> _redkale_servicemap;
@HttpMapping(url = "/hello/create", auth = false, comment = "创建Hello对象")
@HttpParam(name = "bean", type = HelloEntity.class, comment = "Hello对象")
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setResname(req.getHeader("hello-res"));
bean.setBodys(req.getBody());
bean.setBodystr(req.getBodyUTF8());
UserInfo user = new UserInfo();
RetResult<HelloEntity> result = service.createHello(user, bean);
resp.finishJson(result);
}
@HttpMapping(url = "/hello/delete/", auth = false, comment = "根据id删除Hello对象")
@HttpParam(name = "#", type = int.class, comment = "Hello对象id")
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.deleteHello(id);
resp.finishJson(RetResult.success());
}
@HttpMapping(url = "/hello/update", auth = false, comment = "修改Hello对象")
@HttpParam(name = "bean", type = HelloEntity.class, comment = "Hello对象")
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setResname(req.getHeader("hello-res"));
bean.setBodys(req.getBody());
bean.setBodystr(req.getBodyUTF8());
service.updateHello(bean);
resp.finishJson(RetResult.success());
}
@HttpMapping(url = "/hello/query", auth = false, comment = "查询Hello对象列表")
@HttpParam(name = "bean", type = HelloBean.class, comment = "过滤条件")
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
bean.setClientaddr(req.getRemoteAddr());
bean.setUseragent(req.getHeader("User-Agent"));
bean.setRescookie(req.getCookie("hello-cookie"));
bean.setSessionid(req.getSessionid(false));
Flipper flipper = req.getFlipper();
Sheet<HelloEntity> result = service.queryHello(bean, flipper);
resp.finishJson(result);
}
@HttpMapping(url = "/hello/find/", auth = false, comment = "根据id删除Hello对象")
@HttpParam(name = "#", type = int.class, comment = "Hello对象id")
public void find(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _redkale_servicemap == null ? _redkale_service : _redkale_servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = service.findHello(id);
resp.finishJson(bean);
}
}

View File

@@ -0,0 +1,205 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.logging.*;
import javax.annotation.Resource;
import org.redkale.convert.bson.BsonConvert;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.*;
import org.redkale.net.http.*;
import org.redkale.net.sncp.*;
import org.redkale.service.Service;
import org.redkale.util.AnyValue.DefaultAnyValue;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
@RestService(name = "abmain")
public class ABMainService implements Service {
@Resource
private BCService bcService;
public static void remotemain(String[] args) throws Throwable {
System.out.println("------------------- 远程模式调用 -----------------------------------");
final int abport = 8888;
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
ResourceFactory resFactory = ResourceFactory.create();
ExecutorService executor = Executors.newSingleThreadExecutor();
final TransportFactory transFactory = TransportFactory.create(asyncGroup, 0, 0);
transFactory.addGroupInfo("g77", new InetSocketAddress("127.0.0.1", 5577));
transFactory.addGroupInfo("g88", new InetSocketAddress("127.0.0.1", 5588));
transFactory.addGroupInfo("g99", new InetSocketAddress("127.0.0.1", 5599));
resFactory.register(JsonConvert.root());
resFactory.register(BsonConvert.root());
//------------------------ 初始化 CService ------------------------------------
CService cservice = Sncp.createSimpleLocalService(CService.class, null, resFactory, transFactory, new InetSocketAddress("127.0.0.1", 5577), "g77");
SncpServer cserver = new SncpServer();
cserver.getLogger().setLevel(Level.WARNING);
cserver.addSncpServlet(cservice);
cserver.init(DefaultAnyValue.create("port", 5577));
cserver.start();
//------------------------ 初始化 BCService ------------------------------------
BCService bcservice = Sncp.createSimpleLocalService(BCService.class, null, resFactory, transFactory, new InetSocketAddress("127.0.0.1", 5588), "g88");
CService remoteCService = Sncp.createSimpleRemoteService(CService.class, null, transFactory, new InetSocketAddress("127.0.0.1", 5588), "g77");
resFactory.inject(remoteCService);
resFactory.register("", remoteCService);
SncpServer bcserver = new SncpServer();
bcserver.getLogger().setLevel(Level.WARNING);
bcserver.addSncpServlet(bcservice);
bcserver.init(DefaultAnyValue.create("port", 5588));
bcserver.start();
//------------------------ 初始化 ABMainService ------------------------------------
ABMainService service = Sncp.createSimpleLocalService(ABMainService.class, null, resFactory, transFactory, new InetSocketAddress("127.0.0.1", 5599), "g99");
BCService remoteBCService = Sncp.createSimpleRemoteService(BCService.class, null, transFactory, new InetSocketAddress("127.0.0.1", 5599), "g88");
resFactory.inject(remoteBCService);
resFactory.register("", remoteBCService);
HttpServer server = new HttpServer();
server.getLogger().setLevel(Level.WARNING);
server.addRestServlet(null, service, null, HttpServlet.class, "/pipes");
resFactory.inject(cservice);
resFactory.inject(bcservice);
resFactory.inject(service);
server.init(DefaultAnyValue.create("port", abport));
server.start();
Thread.sleep(100);
//同步方法
String url = "http://127.0.0.1:" + abport + "/pipes/abmain/syncabtime/张先生";
System.out.println(Utility.postHttpContent(url));
//异步方法
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime/张先生";
System.out.println(Utility.postHttpContent(url));
//异步方法
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime2/张先生";
System.out.println(Utility.postHttpContent(url));
server.shutdown();
}
public static void main(String[] args) throws Throwable {
System.out.println("------------------- 本地模式调用 -----------------------------------");
final int abport = 8888;
ResourceFactory factory = ResourceFactory.create();
ABMainService service = new ABMainService();
BCService bcservice = new BCService();
factory.register("", bcservice);
factory.register("", new CService());
factory.inject(bcservice);
factory.inject(service);
HttpServer server = new HttpServer();
server.getLogger().setLevel(Level.WARNING);
server.addRestServlet(null, service, null, HttpServlet.class, "/pipes");
server.init(DefaultAnyValue.create("port", "" + abport));
server.start();
Thread.sleep(100);
//同步方法
String url = "http://127.0.0.1:" + abport + "/pipes/abmain/syncabtime/张先生";
System.out.println(Utility.postHttpContent(url));
//异步方法
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime/张先生";
System.out.println(Utility.postHttpContent(url));
//异步方法
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime2/张先生";
System.out.println(Utility.postHttpContent(url));
server.shutdown();
//远程模式
remotemain(args);
}
public static AsynchronousChannelGroup newChannelGroup() throws IOException {
final AtomicInteger counter = new AtomicInteger();
ExecutorService transportExec = Executors.newFixedThreadPool(16, (Runnable r) -> {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("Transport-Thread-" + counter.incrementAndGet());
return t;
});
return AsynchronousChannelGroup.withCachedThreadPool(transportExec, 1);
}
public static ObjectPool<ByteBuffer> newBufferPool() {
return ObjectPool.createSafePool(new LongAdder(), new LongAdder(), 16,
(Object... params) -> ByteBuffer.allocateDirect(8192), null, (e) -> {
if (e == null || e.isReadOnly() || e.capacity() != 8192) return false;
e.clear();
return true;
});
}
@RestMapping(name = "syncabtime")
public String abCurrentTime(@RestParam(name = "#") final String name) {
String rs = "同步abCurrentTime: " + bcService.bcCurrentTime(name);
System.out.println("执行了 ABMainService.abCurrentTime++++同步方法");
return rs;
}
@RestMapping(name = "asyncabtime")
public void abCurrentTime(final CompletionHandler<String, Void> handler, @RestParam(name = "#") final String name) {
bcService.bcCurrentTime(Utility.createAsyncHandler((v, a) -> {
System.out.println("执行了 ABMainService.abCurrentTime----异步方法");
String rs = "异步abCurrentTime: " + v;
if (handler != null) handler.completed(rs, a);
}, (t, a) -> {
if (handler != null) handler.failed(t, a);
}), name);
}
@RestMapping(name = "asyncabtime2")
public void abCurrentTime(final MyAsyncHandler<String, Void> handler, @RestParam(name = "#") final String name) {
bcService.bcCurrentTime(new MyAsyncHandler<String, Void>() {
@Override
public int id() {
return 1;
}
@Override
public void completed(String v, Void a) {
System.out.println("执行了 ABMainService.abCurrentTime----异步方法2");
String rs = "异步abCurrentTime: " + v;
if (handler != null) handler.completed(rs, a);
}
@Override
public void failed(Throwable exc, Void attachment) {
}
@Override
public int id2() {
return 2;
}
}, name);
}
}

View File

@@ -0,0 +1,62 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
import java.nio.channels.CompletionHandler;
import javax.annotation.Resource;
import org.redkale.service.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class BCService implements Service {
@Resource
private CService cService;
public String bcCurrentTime(final String name) {
String rs = "同步bcCurrentTime: " + cService.ccCurrentTime(name).getResult();
System.out.println("执行了 BCService.bcCurrentTime++++同步方法");
return rs;
}
public void bcCurrentTime(final CompletionHandler<String, Void> handler, final String name) {
cService.ccCurrentTime(Utility.createAsyncHandler((v, a) -> {
System.out.println("执行了 BCService.bcCurrentTime----异步方法");
String rs = "异步bcCurrentTime: " + (v == null ? null : v.getResult());
if (handler != null) handler.completed(rs, null);
}, (t, a) -> {
if (handler != null) handler.failed(t, a);
}), name);
}
public void bcCurrentTime(final MyAsyncHandler<String, Void> handler, final String name) {
cService.mcCurrentTime(new MyAsyncHandler<RetResult<String>, Void>() {
@Override
public int id() {
return 1;
}
@Override
public void completed(RetResult<String> v, Void a) {
System.out.println("执行了 BCService.bcCurrentTime----异步方法2");
String rs = "异步bcCurrentTime: " + (v == null ? null : v.getResult());
if (handler != null) handler.completed(rs, null);
}
@Override
public void failed(Throwable exc, Void attachment) {
}
@Override
public int id2() {
return 2;
}
}, name);
}
}

View File

@@ -0,0 +1,35 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
import java.nio.channels.CompletionHandler;
import org.redkale.service.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class CService implements Service {
public RetResult<String> ccCurrentTime(final String name) {
String rs = "同步ccCurrentTime: " + name + ": " + Utility.formatTime(System.currentTimeMillis());
System.out.println("执行了 CService.ccCurrentTime++++同步方法");
return new RetResult(rs);
}
public void ccCurrentTime(final CompletionHandler<RetResult<String>, Void> handler, final String name) {
String rs = "异步ccCurrentTime: " + name + ": " + Utility.formatTime(System.currentTimeMillis());
System.out.println("执行了 CService.ccCurrentTime----异步方法");
if (handler != null) handler.completed(new RetResult(rs), null);
}
public void mcCurrentTime(final MyAsyncHandler<RetResult<String>, Void> handler, final String name) {
String rs = "异步mcCurrentTime: " + name + ": " + Utility.formatTime(System.currentTimeMillis());
System.out.println("执行了 CService.mcCurrentTime----异步方法2");
if (handler != null) handler.completed(new RetResult(rs), null);
}
}

View File

@@ -0,0 +1,18 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
/**
*
* @author zhangjx
* @param <V> V
* @param <A> A
*/
public abstract class MyAsyncHandler<V, A> extends MyAsyncInnerHandler<V, A> {
public abstract int id();
}

View File

@@ -0,0 +1,18 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
import java.nio.channels.CompletionHandler;
/**
*
* @author zhangjx
*/
public abstract class MyAsyncInnerHandler<V, A> implements CompletionHandler<V, A> {
protected abstract int id2();
}

View File

@@ -0,0 +1,32 @@
package org.redkale.test.service;
import java.io.Serializable;
public class Person implements Serializable {
private byte[] b = new byte[1024 * 2];
private String name;
@Override
public String toString() {
return "{name=" + name + ", b =" + (b == null ? "null" : "[length=" + b.length + "]") + "}";
}
public byte[] getB() {
return b;
}
public void setB(byte[] b) {
this.b = b;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
/**
*
* @author zhangjx
*/
public class TestBean {
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.service;
import java.nio.channels.CompletionHandler;
import org.redkale.net.sncp.*;
import org.redkale.service.Service;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class TestService implements Service {
// public boolean change(TestBean bean, String name, int id) {
// return false;
// }
public void change(CompletionHandler<Boolean, TestBean> handler, TestBean bean, String name, int id) {
}
public static void main(String[] args) throws Throwable {
SncpServer cserver = new SncpServer();
cserver.addSncpServlet(new TestService());
cserver.init(AnyValue.DefaultAnyValue.create("port", 5577));
}
}

View File

@@ -0,0 +1,225 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import java.io.*;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.logging.LogManager;
import org.redkale.convert.bson.*;
import org.redkale.net.*;
import org.redkale.net.sncp.*;
import org.redkale.service.Service;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class SncpTest {
private static final String serviceName = "";
private static final String myhost = Utility.localInetAddress().getHostAddress();
private static final int port = 4040;
private static final int port2 = 4240;
private static final String protocol = "SNCP.UDP";
private static final ResourceFactory factory = ResourceFactory.create();
public static void main(String[] args) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
ps.println("handlers = java.util.logging.ConsoleHandler");
ps.println(".handlers = java.util.logging.ConsoleHandler");
ps.println(".level = FINEST");
ps.println("java.util.logging.ConsoleHandler.level = FINEST");
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
factory.register("", BsonConvert.class, BsonFactory.root().getConvert());
if (System.getProperty("client") == null) {
runServer();
if (port2 > 0) runServer2();
}
if (System.getProperty("server") == null) {
runClient();
}
if (System.getProperty("server") != null) {
System.in.read();
}
}
public static AsynchronousChannelGroup newChannelGroup() throws IOException {
final AtomicInteger counter = new AtomicInteger();
ExecutorService transportExec = Executors.newFixedThreadPool(16, (Runnable r) -> {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("Transport-Thread-" + counter.incrementAndGet());
return t;
});
return AsynchronousChannelGroup.withCachedThreadPool(transportExec, 1);
}
public static ObjectPool<ByteBuffer> newBufferPool() {
return ObjectPool.createSafePool(new LongAdder(), new LongAdder(), 16,
(Object... params) -> ByteBuffer.allocateDirect(8192), null, (e) -> {
if (e == null || e.isReadOnly() || e.capacity() != 8192) return false;
e.clear();
return true;
});
}
private static void runClient() throws Exception {
InetSocketAddress addr = new InetSocketAddress(myhost, port);
Set<InetSocketAddress> set = new LinkedHashSet<>();
set.add(addr);
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
final TransportFactory transFactory = TransportFactory.create(asyncGroup, protocol.endsWith(".UDP") ? "UDP" : "TCP", 0, 0);
transFactory.addGroupInfo("client", set);
final SncpTestIService service = Sncp.createSimpleRemoteService(SncpTestIService.class, null, transFactory, addr, "client");
factory.inject(service);
// SncpTestBean bean = new SncpTestBean();
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < 2000; i++) {
// sb.append("_").append(i).append("_0123456789");
// }
// bean.setContent(sb.toString());
// bean.setContent("hello sncp");
SncpTestBean callbean = new SncpTestBean();
callbean.setId(1);
callbean.setContent("数据X");
service.queryLongResult("f", 3, 33L);
service.insert(callbean);
System.out.println("bean.id应该会被修改(id不会是1) " + callbean);
System.out.println("---------------------------------------------------");
final int count = 10;
final CountDownLatch cld = new CountDownLatch(count);
final AtomicInteger ai = new AtomicInteger();
for (int i = 0; i < count; i++) {
final int k = i + 1;
new Thread() {
@Override
public void run() {
try {
Thread.sleep(k);
SncpTestBean bean = new SncpTestBean();
bean.setId(k);
bean.setContent("数据: " + (k < 10 ? "0" : "") + k);
StringBuilder sb = new StringBuilder();
sb.append(k).append("------");
for (int i = 0; i < 1200; i++) {
sb.append("_").append(i).append("_").append(k).append("_0123456789");
}
bean.setContent(sb.toString());
service.queryResult(bean);
//service.updateBean(bean);
} catch (Exception e) {
e.printStackTrace();
} finally {
long a = ai.incrementAndGet();
System.out.println("运行了 " + (a == 100 ? "--------------------------------------------------" : "") + a);
cld.countDown();
}
}
}.start();
}
cld.await();
final CountDownLatch cld2 = new CountDownLatch(1);
final CompletableFuture<String> future = service.queryResultAsync(callbean);
future.whenComplete((v, e) -> {
cld2.countDown();
System.out.println("异步执行完毕: " + v + ", 异常为: " + e);
});
cld2.await();
System.out.println("---全部运行完毕---");
System.exit(0);
}
private static void runServer() throws Exception {
InetSocketAddress addr = new InetSocketAddress(myhost, port);
final CountDownLatch cdl = new CountDownLatch(1);
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
new Thread() {
{
setName("Thread-Server-01");
}
@Override
public void run() {
try {
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
conf.addValue("host", "0.0.0.0");
conf.addValue("port", "" + port);
conf.addValue("protocol", protocol);
SncpServer server = new SncpServer(null, System.currentTimeMillis(), conf, factory);
Set<InetSocketAddress> set = new LinkedHashSet<>();
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
final TransportFactory transFactory = TransportFactory.create(asyncGroup, protocol.endsWith(".UDP") ? "UDP" : "TCP", 0, 0);
transFactory.addGroupInfo("server", set);
SncpTestIService service = Sncp.createSimpleLocalService(SncpTestServiceImpl.class, null, factory, transFactory, addr, "server");
factory.inject(service);
server.addSncpServlet(service);
System.out.println(service);
server.init(conf);
server.start();
cdl.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
cdl.await();
}
private static void runServer2() throws Exception {
InetSocketAddress addr = new InetSocketAddress(myhost, port2);
final CountDownLatch cdl = new CountDownLatch(1);
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
new Thread() {
{
setName("Thread-Server-02");
}
@Override
public void run() {
try {
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
conf.addValue("host", "0.0.0.0");
conf.addValue("port", "" + port2);
conf.addValue("protocol", protocol);
SncpServer server = new SncpServer(null, System.currentTimeMillis(), conf, factory);
Set<InetSocketAddress> set = new LinkedHashSet<>();
set.add(new InetSocketAddress(myhost, port));
final TransportFactory transFactory = TransportFactory.create(asyncGroup, protocol.endsWith(".UDP") ? "UDP" : "TCP", 0, 0);
transFactory.addGroupInfo("server", set);
Service service = Sncp.createSimpleLocalService(SncpTestServiceImpl.class, null, factory, transFactory, addr, "server");
server.addSncpServlet(service);
server.init(conf);
server.start();
cdl.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
cdl.await();
}
}

View File

@@ -0,0 +1,54 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import org.redkale.convert.bson.BsonFactory;
import org.redkale.util.Utility;
import org.redkale.source.FilterBean;
import javax.persistence.*;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class SncpTestBean implements FilterBean {
@Id
private long id;
private String content;
public static void main(String[] args) throws Exception {
SncpTestBean bean = JsonConvert.root().convertFrom(SncpTestBean.class, "{\"content\":\"数据: 01\",\"id\":1}");
System.out.println(bean);
byte[] bs = BsonFactory.root().getConvert().convertTo(bean);
Utility.println("---------", bs);
System.out.println(BsonFactory.root().getConvert().convertFrom(SncpTestBean.class, bs).toString());
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@@ -0,0 +1,28 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import java.util.concurrent.CompletableFuture;
import org.redkale.service.*;
/**
*
* @author zhangjx
*/
public interface SncpTestIService extends Service {
public String queryResult(SncpTestBean bean);
public double queryDoubleResult(String a, int b, double value);
public long queryLongResult(String a, int b, long value);
public CompletableFuture<String> queryResultAsync(SncpTestBean bean);
public void insert(@RpcCall(RpcCallArrayAttribute.class) SncpTestBean... beans);
public String updateBean(@RpcCall(SncpTestServiceImpl.CallAttribute.class) SncpTestBean bean);
}

View File

@@ -0,0 +1,144 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.*;
import org.redkale.net.*;
import org.redkale.net.sncp.*;
import org.redkale.service.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
@ResourceType(SncpTestIService.class)
public class SncpTestServiceImpl implements SncpTestIService {
@Override
public CompletableFuture<String> queryResultAsync(SncpTestBean bean) {
final CompletableFuture<String> future = new CompletableFuture<>();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 运行了异步方法-----------queryResultAsync方法");
future.complete("异步result: " + bean);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
return future;
}
@Override
public long queryLongResult(String a, int b, long value) {
return value + 1;
}
@Override
public double queryDoubleResult(String a, int b, double value) {
return value + 1;
}
public static class CallAttribute implements Attribute<SncpTestBean, Long> {
@Override
public Class<? extends Long> type() {
return long.class;
}
@Override
public Class<SncpTestBean> declaringClass() {
return SncpTestBean.class;
}
@Override
public String field() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Long get(SncpTestBean obj) {
System.out.println("返回ID: " + obj.getId());
return obj.getId();
}
@Override
public void set(SncpTestBean obj, Long value) {
System.out.println("设置ID: " + value);
obj.setId(value);
}
}
@Override
public void insert(@RpcCall(RpcCallArrayAttribute.class) SncpTestBean... beans) {
for (SncpTestBean bean : beans) {
bean.setId(System.currentTimeMillis());
}
}
@Override
public String queryResult(SncpTestBean bean) {
System.out.println(Thread.currentThread().getName() + " 运行了queryResult方法");
return "result: " + bean;
}
public void queryResult(CompletionHandler<String, SncpTestBean> handler, @RpcAttachment SncpTestBean bean) {
System.out.println(Thread.currentThread().getName() + " handler 运行了queryResult方法");
if (handler != null) handler.completed("result: " + bean, bean);
}
@Override
public String updateBean(@RpcCall(CallAttribute.class) SncpTestBean bean) {
bean.setId(System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " 运行了updateBean方法");
return "result: " + bean;
}
public static void main(String[] args) throws Exception {
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
asyncGroup.start();
final TransportFactory transFactory = TransportFactory.create(asyncGroup, 0, 0);
transFactory.addGroupInfo("g70", new InetSocketAddress("127.0.0.1", 7070));
Service service = Sncp.createSimpleLocalService(SncpTestServiceImpl.class, null, ResourceFactory.create(), transFactory, new InetSocketAddress("127.0.0.1", 7070), "g70");
for (Method method : service.getClass().getDeclaredMethods()) {
System.out.println(method);
}
System.out.println("-----------------------------------");
for (Method method : SncpClient.parseMethod(service.getClass())) {
System.out.println(method);
}
System.out.println("-----------------------------------");
service = Sncp.createSimpleRemoteService(SncpTestServiceImpl.class, null, transFactory, new InetSocketAddress("127.0.0.1", 7070), "g70");
for (Method method : service.getClass().getDeclaredMethods()) {
System.out.println(method);
}
System.out.println("-----------------------------------");
for (Method method : SncpClient.parseMethod(service.getClass())) {
System.out.println(method);
}
System.out.println("-----------------------------------");
service = Sncp.createSimpleRemoteService(SncpTestIService.class, null, transFactory, new InetSocketAddress("127.0.0.1", 7070), "g70");
for (Method method : service.getClass().getDeclaredMethods()) {
System.out.println(method);
}
System.out.println("-----------------------------------");
for (Method method : SncpClient.parseMethod(service.getClass())) {
System.out.println(method);
}
System.out.println("-----------------------------------");
}
}

View File

@@ -0,0 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import org.redkale.net.sncp.*;
import org.redkale.util.ResourceType;
/**
*
* @author zhangjx
*/
@ResourceType(SncpTestIService.class)
public class _DynLocalSncpTestService extends SncpTestServiceImpl {
private SncpClient _redkale_client;
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.io.Serializable;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public abstract class BaseEntity implements Serializable {
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -0,0 +1,100 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import javax.persistence.Id;
import org.redkale.convert.json.JsonConvert;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
@VirtualEntity(loader = CacheTestBean.DefaultBeanLoader.class)
public class CacheTestBean {
@Id
private long pkgid;
private String name;
private long price;
public static void main(String[] args) throws Exception {
Method method = EntityInfo.class.getDeclaredMethod("load", Class.class, boolean.class, Properties.class, DataSource.class, BiFunction.class);
method.setAccessible(true);
final EntityInfo<CacheTestBean> info = (EntityInfo<CacheTestBean>) method.invoke(null, CacheTestBean.class, true, new Properties(), null, new CacheTestBean.DefaultBeanLoader());
EntityCache<CacheTestBean> cache = new EntityCache(info, null);
cache.fullLoadAsync();
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.COUNT, "name", null));
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.DISTINCTCOUNT, "name", null));
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.AVG, "price", null));
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.SUM, "price", null));
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.MAX, "price", null));
System.out.println(cache.queryColumnMap("pkgid", FilterFunc.MIN, "price", null));
System.out.println(cache.find(null, FilterNode.create("name", FilterExpress.EQUAL, "BB")));
System.out.println(cache.find(null, FilterNode.create("name", FilterExpress.IGNORECASEEQUAL, "BB")));
System.out.println(cache.querySheet(null, null, FilterNode.create("name", FilterExpress.IGNORECASENOTLIKE, "B")));
}
public CacheTestBean() {
}
public CacheTestBean(long pkgid, String name, long price) {
this.pkgid = pkgid;
this.name = name;
this.price = price;
}
public long getPkgid() {
return pkgid;
}
public void setPkgid(long pkgid) {
this.pkgid = pkgid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static class DefaultBeanLoader implements BiFunction<DataSource, EntityInfo, CompletableFuture<List>> {
@Override
public CompletableFuture<List> apply(DataSource t, EntityInfo u) {
final List<CacheTestBean> list = new ArrayList<>();
list.add(new CacheTestBean(1, "a", 12));
list.add(new CacheTestBean(1, "a", 18));
list.add(new CacheTestBean(2, "b", 20));
list.add(new CacheTestBean(2, "bb", 60));
return CompletableFuture.completedFuture(list);
}
}
}

View File

@@ -0,0 +1,389 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import org.redkale.source.*;
import org.redkale.util.AutoLoad;
import static org.redkale.source.FilterExpress.*;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.*;
import javax.persistence.*;
import org.redkale.convert.json.*;
import org.junit.jupiter.api.*;
/**
* @author zhangjx
*/
public class FilterNodeTest {
private static Function<Class, EntityInfo> func;
private static EntityInfo<CarTestTable> carEntity;
@BeforeAll
public static void init() throws Exception {
final Properties props = new Properties();
final BiFunction<DataSource, EntityInfo, CompletableFuture<List>> fullloader = (s, t) -> CompletableFuture.completedFuture(new ArrayList());
func = (Class t) -> loadEntityInfo(t, false, props, null, fullloader);
carEntity = loadEntityInfo(CarTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(CarTestTable.createList()));
final EntityInfo<UserTestTable> userEntity = loadEntityInfo(UserTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(UserTestTable.createList()));
final EntityInfo<CarTypeTestTable> typeEntity = loadEntityInfo(CarTypeTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(CarTypeTestTable.createList()));
}
private static <T> EntityInfo<T> loadEntityInfo(Class<T> clazz, final boolean cacheForbidden, final Properties conf, DataSource source, BiFunction<DataSource, EntityInfo, CompletableFuture<List>> fullloader) {
try {
Method loadMethod = EntityInfo.class.getDeclaredMethod("load", Class.class, boolean.class, Properties.class, DataSource.class, BiFunction.class);
loadMethod.setAccessible(true);
return (EntityInfo) loadMethod.invoke(null, clazz, cacheForbidden, conf, source, fullloader);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Map<Class, String> getJoinTabalis(FilterNode node) {
try {
Method method = FilterNode.class.getDeclaredMethod("getJoinTabalis");
method.setAccessible(true);
return (Map) method.invoke(node);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> CharSequence createSQLJoin(FilterNode node, Function<Class, EntityInfo> func, final boolean update, final Map<Class, String> joinTabalis, final Set<String> haset, final EntityInfo<T> info) {
try {
Method method = FilterNode.class.getDeclaredMethod("createSQLJoin", Function.class, boolean.class, Map.class, Set.class, EntityInfo.class);
method.setAccessible(true);
return (CharSequence) method.invoke(node, func, update, joinTabalis, haset, info);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> CharSequence createSQLExpress(FilterNode node, DataSqlSource source, final EntityInfo<T> info, final Map<Class, String> joinTabalis) {
try {
Method method = FilterNode.class.getDeclaredMethod("createSQLExpress", DataSqlSource.class, EntityInfo.class, Map.class);
method.setAccessible(true);
return (CharSequence) method.invoke(node, source, info, joinTabalis);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> boolean isCacheUseable(FilterNode node, final Function<Class, EntityInfo> entityApplyer) {
try {
Method method = FilterNode.class.getDeclaredMethod("isCacheUseable", Function.class);
method.setAccessible(true);
return (Boolean) method.invoke(node, entityApplyer);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> Predicate<T> createPredicate(FilterNode node, final EntityCache<T> cache) {
try {
Method method = FilterNode.class.getDeclaredMethod("createPredicate", EntityCache.class);
method.setAccessible(true);
return (Predicate) method.invoke(node, cache);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Test
public void run() throws Exception {
final CarTestBean bean = CarTestBean.create();
FilterNode joinNode1 = FilterJoinNode.create(UserTestTable.class, new String[]{"userid", "username"}, "username", LIKE, bean.username)
.or(FilterJoinNode.create(UserTestTable.class, new String[]{"userid", "username"}, "createtime", GREATERTHAN, bean.createtime));
FilterNode joinNode2 = FilterJoinNode.create(CarTypeTestTable.class, "cartype", "typename", LIKE, bean.typename);
final FilterNode node = CarTestBean.caridTransient() ? (joinNode2.or(joinNode1)) : FilterNode.create("carid", GREATERTHAN, bean.carid).and(joinNode1).or(joinNode2);
final FilterNode beanNode = FilterNodeBean.createFilterNode(bean);
System.out.println("node.string = " + node);
System.out.println("bean.string = " + beanNode);
Assertions.assertEquals("(CarTypeTestTable.typename LIKE '%法拉利%' OR (UserTestTable.username LIKE '%用户1%' OR UserTestTable.createtime > 500))", node.toString());
Assertions.assertEquals(node.toString(), beanNode.toString());
Map<Class, String> nodeJoinTabalis = getJoinTabalis(node);
Map<Class, String> beanJoinTabalis = getJoinTabalis(beanNode);
CharSequence nodeJoinsql = createSQLJoin(node, func, false, nodeJoinTabalis, new HashSet<>(), carEntity);
CharSequence beanJoinsql = createSQLJoin(beanNode, func, false, beanJoinTabalis, new HashSet<>(), carEntity);
CharSequence nodeWhere = createSQLExpress(node, null, carEntity, nodeJoinTabalis);
CharSequence beanWhere = createSQLExpress(beanNode, null, carEntity, beanJoinTabalis);
System.out.println("node.sql = SELECT a.* FROM " + CarTestTable.class.getSimpleName().toLowerCase() + " a" + (nodeJoinsql == null ? "" : nodeJoinsql) + " WHERE " + nodeWhere);
System.out.println("bean.sql = SELECT a.* FROM " + CarTestTable.class.getSimpleName().toLowerCase() + " a" + (beanJoinsql == null ? "" : beanJoinsql) + " WHERE " + beanWhere);
boolean r1 = isCacheUseable(node, func);
Assertions.assertTrue(r1);
if (!r1) System.err.println("node.isCacheUseable 应该是true");
boolean r2 = isCacheUseable(beanNode, func);
Assertions.assertTrue(r2);
System.out.println("node.Predicate = " + createPredicate(node, carEntity.getCache()));
System.out.println("bean.Predicate = " + createPredicate(beanNode, carEntity.getCache()));
System.out.println("node.sheet = " + carEntity.getCache().querySheet(null, new Flipper(), node));
System.out.println("bean.sheet = " + carEntity.getCache().querySheet(null, new Flipper(), beanNode));
}
public static class CarTestBean implements FilterBean {
@FilterGroup("[OR].[AND]a")
@FilterColumn(express = GREATERTHAN)
@Transient
public long carid;
@FilterGroup("[OR].[AND]a.[OR]c")
@FilterColumn(express = LIKE)
@FilterJoinColumn(table = UserTestTable.class, columns = {"userid", "username"})
public String username;
@FilterGroup("[OR].[AND]a.[OR]c")
@FilterColumn(express = GREATERTHAN)
@FilterJoinColumn(table = UserTestTable.class, columns = {"userid", "username"})
public long createtime;
@FilterGroup("[OR]")
@FilterColumn(express = LIKE)
@FilterJoinColumn(table = CarTypeTestTable.class, columns = {"cartype"})
public String typename;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static boolean caridTransient() {
try {
return CarTestBean.class.getDeclaredField("carid").getAnnotation(Transient.class) != null;
} catch (Exception e) {
e.printStackTrace();
return true;
}
}
public static CarTestBean create() {
final CarTestBean bean = new CarTestBean();
bean.carid = 70002;
bean.username = "用户1";
bean.createtime = 500;
bean.typename = "法拉利";
return bean;
}
}
@AutoLoad
@Cacheable
public static class CarTestTable {
public static List<CarTestTable> createList() {
List<CarTestTable> list = new ArrayList<>();
list.add(new CarTestTable(70001, 101, 1000011, "我的车"));
list.add(new CarTestTable(70002, 102, 1000012, "我的车"));
list.add(new CarTestTable(70003, 103, 1000013, "我的车"));
list.add(new CarTestTable(70004, 104, 1000014, "我的车"));
list.add(new CarTestTable(70005, 105, 1000015, "我的车"));
list.add(new CarTestTable(70201, 201, 1000031, "我的车"));
list.add(new CarTestTable(70202, 202, 1000032, "我的车"));
list.add(new CarTestTable(70203, 203, 1000033, "我的车"));
list.add(new CarTestTable(70204, 204, 1000034, "我的车"));
list.add(new CarTestTable(70205, 205, 1000035, "我的车"));
list.add(new CarTestTable(70505, 301, 1008000, "我的车"));
return list;
}
@Id
private long carid;
private int cartype;
private int userid;
private String username;
private String cartitle;
public CarTestTable() {
}
public CarTestTable(long carid, int cartype, int userid, String cartitle) {
this.carid = carid;
this.cartype = cartype;
this.userid = userid;
this.username = "用户" + userid % 1000;
this.cartitle = cartitle;
}
public long getCarid() {
return carid;
}
public void setCarid(long carid) {
this.carid = carid;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getCartitle() {
return cartitle;
}
public void setCartitle(String cartitle) {
this.cartitle = cartitle;
}
public int getCartype() {
return cartype;
}
public void setCartype(int cartype) {
this.cartype = cartype;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
@AutoLoad
@Cacheable
public static class CarTypeTestTable {
public static List<CarTypeTestTable> createList() {
List<CarTypeTestTable> list = new ArrayList<>();
list.add(new CarTypeTestTable(101, "奥迪A1"));
list.add(new CarTypeTestTable(102, "奥迪A2"));
list.add(new CarTypeTestTable(103, "奥迪A3"));
list.add(new CarTypeTestTable(104, "奥迪A4"));
list.add(new CarTypeTestTable(105, "奥迪A5"));
list.add(new CarTypeTestTable(201, "奔驰S1"));
list.add(new CarTypeTestTable(202, "奔驰S2"));
list.add(new CarTypeTestTable(203, "奔驰S3"));
list.add(new CarTypeTestTable(204, "奔驰S4"));
list.add(new CarTypeTestTable(205, "奔驰S5"));
list.add(new CarTypeTestTable(301, "法拉利"));
return list;
}
@Id
private int cartype;
private String typename;
public CarTypeTestTable() {
}
public CarTypeTestTable(int cartype, String typename) {
this.cartype = cartype;
this.typename = typename;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public int getCartype() {
return cartype;
}
public void setCartype(int cartype) {
this.cartype = cartype;
}
public String getTypename() {
return typename;
}
public void setTypename(String typename) {
this.typename = typename;
}
}
@AutoLoad
@Cacheable
public static class UserTestTable {
public static List<UserTestTable> createList() {
List<UserTestTable> list = new ArrayList<>();
for (int i = 11; i <= 50; i++) {
list.add(new UserTestTable(1000000 + i, "用户" + i, i * 20));
}
list.add(new UserTestTable(1008000, "车主A", 20));
return list;
}
@Id
private int userid;
private String username;
private long createtime;
public UserTestTable() {
}
public UserTestTable(int userid, String username, long createtime) {
this.userid = userid;
this.username = username;
this.createtime = createtime;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
public class JDBCTest {
public static void main(String[] args) throws Exception {
DataSource source = DataSources.createDataSource(null, ""); //耗时37415
int count = 1000;
LoginTestRecord last = null;
long s = System.currentTimeMillis();
int c = 0;
try {
for (int i = 0; i < count; i++) {
LoginTestRecord record = new LoginTestRecord();
record.setSessionid(Long.toHexString(System.nanoTime()));
record.setLoginagent("win7");
record.setLogintime(System.currentTimeMillis());
record.setLoginip("127.0.0.1");
record.setUserid(i);
source.insert(record);
last = record;
c = i;
}
} catch (Exception e) {
System.out.println("异常了: " + c);
e.printStackTrace();
}
long e = System.currentTimeMillis() - s;
System.out.println("耗时:" + e);
}
}

View File

@@ -0,0 +1,122 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.io.Serializable;
import java.util.*;
import javax.persistence.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
//@Cacheable
public class JsonRecord {
@SourceConvert
private static JsonConvert createConvert() {
return JsonConvert.root();
}
@Id
@Column(comment = "主键ID;")
private long recordid;
@Column(comment = ";")
private String recordname = "";
@Column(comment = ";")
private Map<String, Integer> rmap;
@Column(comment = ";")
private List<String> rlist;
@Column(comment = ";")
private Set<String> rset;
public static JsonRecord create() {
JsonRecord record = new JsonRecord();
record.setRecordid(System.currentTimeMillis());
record.setRecordname("my name");
Map<String, Integer> map = new HashMap<>();
map.put("str111", 10000);
map.put("str222", 20000);
record.setRmap(map);
List<String> list = new ArrayList<>();
list.add("item11");
list.add("item22");
list.add("item11");
record.setRlist(list);
Set<String> set = new HashSet<>();
set.add("r1");
set.add("r2");
record.setRset(set);
return record;
}
public static void main(String[] args) throws Throwable {
Properties properties = new Properties();
properties.put("javax.persistence.jdbc.url", "jdbc:mysql://localhost:3306/center?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true");
properties.put("javax.persistence.jdbc.user", "root");
properties.put("javax.persistence.jdbc.password", "");
DataSource source = DataSources.createDataSource("", properties);
JsonRecord record = JsonRecord.create();
source.insert(record);
source.updateColumn(JsonRecord.class, record.getRecordid(), ColumnValue.mov("recordname", "my name 2"));
record.getRmap().put("haha", 2222);
source.updateColumn(JsonRecord.class, record.getRecordid(), ColumnValue.mov("rmap", (Serializable) (Object) record.getRmap()));
System.out.println(source.find(JsonRecord.class, record.getRecordid()));
System.out.println(source.findColumn(JsonRecord.class, "rmap", record.getRecordid()));
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public long getRecordid() {
return recordid;
}
public void setRecordid(long recordid) {
this.recordid = recordid;
}
public String getRecordname() {
return recordname;
}
public void setRecordname(String recordname) {
this.recordname = recordname;
}
public Map<String, Integer> getRmap() {
return rmap;
}
public void setRmap(Map<String, Integer> rmap) {
this.rmap = rmap;
}
public List<String> getRlist() {
return rlist;
}
public void setRlist(List<String> rlist) {
this.rlist = rlist;
}
public Set<String> getRset() {
return rset;
}
public void setRset(Set<String> rset) {
this.rset = rset;
}
}

View File

@@ -0,0 +1,157 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.io.Serializable;
import javax.persistence.*;
import org.redkale.source.*;
import org.redkale.util.Utility;
/**
*
* @author zhangjx
*/
@DistributeTable(strategy = LoginRecord.TableStrategy.class)
public class LoginRecord extends BaseEntity {
@Id
@Column(comment = "主键ID; 值=create36time(9位)+'-'+UUID(32位)")
private String loginid = ""; //主键ID; 值=create36time(9位)+'-'+UUID(32位)
@Column(updatable = false, comment = "C端用户ID")
private long userid; //C端用户ID
@Column(updatable = false, comment = "登录网络类型; wifi/4g/3g")
private String netmode = ""; //登录网络类型; wifi/4g/3g
@Column(updatable = false, comment = "APP版本信息")
private String appversion = ""; //APP版本信息
@Column(updatable = false, comment = "APP操作系统信息")
private String appos = ""; //APP操作系统信息
@Column(updatable = false, comment = "登录时客户端信息")
private String loginagent = ""; //登录时客户端信息
@Column(updatable = false, comment = "登录时的IP")
private String loginaddr = ""; //登录时的IP
@Column(updatable = false, comment = "创建时间")
private long createtime; //创建时间
/** 以下省略getter setter方法 */
//
public void setLoginid(String loginid) {
this.loginid = loginid;
}
public String getLoginid() {
return this.loginid;
}
public void setUserid(long userid) {
this.userid = userid;
}
public long getUserid() {
return this.userid;
}
public void setNetmode(String netmode) {
this.netmode = netmode;
}
public String getNetmode() {
return this.netmode;
}
public String getAppversion() {
return appversion;
}
public void setAppversion(String appversion) {
this.appversion = appversion;
}
public String getAppos() {
return appos;
}
public void setAppos(String appos) {
this.appos = appos;
}
public void setLoginagent(String loginagent) {
this.loginagent = loginagent;
}
public String getLoginagent() {
return this.loginagent;
}
public void setLoginaddr(String loginaddr) {
this.loginaddr = loginaddr;
}
public String getLoginaddr() {
return this.loginaddr;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
public long getCreatetime() {
return this.createtime;
}
private static DataSource source;
//创建对象
public static void main(String[] args) throws Throwable {
LoginRecord record = new LoginRecord();
long now = System.currentTimeMillis();
record.setCreatetime(now); //设置创建时间
record.setLoginid(Utility.format36time(now) + "-" + Utility.uuid()); //主键的生成规则
//.... 填充其他字段
source.insert(record);
}
public static class TableStrategy implements DistributeTableStrategy<LoginRecord> {
private static final String dayformat = "%1$tY%1$tm%1$td"; //一天一个表
private static final String yearformat = "%1$tY"; //一年一个库
//过滤查询时调用本方法
@Override
public String getTable(String table, FilterNode node) {
Serializable day = node.findValue("#day"); //LoginRecord没有day字段所以前面要加#,表示虚拟字段, 值为yyyyMMdd格式
if (day != null) getTable(table, (Integer) day, 0L); //存在#day参数则直接使用day值
Serializable time = node.findValue("createtime"); //存在createtime则使用最小时间且createtime的范围必须在一天内因为本表以天为单位建表
return getTable(table, 0, (time == null ? 0L : (time instanceof Range ? ((Range.LongRange) time).getMin() : (Long) time)));
}
//创建或单个查询时调用本方法
@Override
public String getTable(String table, LoginRecord bean) {
return getTable(table, 0, bean.getCreatetime());
}
//根据主键ID查询单个记录时调用本方法
@Override
public String getTable(String table, Serializable primary) {
String id = (String) primary;
return getTable(table, 0, Long.parseLong(id.substring(0, 9), 36));
}
private String getTable(String table, int day, long createtime) { //day为0或yyyyMMdd格式数据
int pos = table.indexOf('.');
String year = day > 0 ? String.valueOf(day / 10000) : String.format(yearformat, createtime); //没有day取createtime
return "platf_login_" + year + "." + table.substring(pos + 1) + "_" + (day > 0 ? day : String.format(dayformat, createtime));
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.BiFunction;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
public class LoginTestBean implements FilterBean {
private String sessionid;
private int sid;
public static void main(String[] args) throws Throwable {
LoginTestBean bean = new LoginTestBean();
bean.setSessionid("xxx");
bean.setSid(23333);
BiFunction<DataSource, Class, List> fullloader = (s, z) -> new ArrayList();
Method method = EntityInfo.class.getDeclaredMethod("load", Class.class, boolean.class, Properties.class,
DataSource.class, BiFunction.class);
method.setAccessible(true);
final EntityInfo<CacheTestBean> info = (EntityInfo<CacheTestBean>) method.invoke(null, CacheTestBean.class, true, new Properties(), null, fullloader);
EntityCache<CacheTestBean> cache = new EntityCache(info, null);
FilterNode node = FilterNodeBean.createFilterNode(bean);
System.out.println("cache = " + cache + ", node = " + node);
Method pre = FilterNode.class.getDeclaredMethod("createPredicate", EntityCache.class);
pre.setAccessible(true);
//为null是因为CacheTestBean 没有sid和sessionid这两个字段
System.out.println(pre.invoke(node,cache));
}
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
}

View File

@@ -0,0 +1,92 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import javax.persistence.*;
import org.redkale.convert.json.*;
/**
* CREATE TABLE `LoginTestRecord` (
* `sessionid` VARCHAR(64) NOT NULL COMMENT '登录会话ID',
* `userid` INT(11) NOT NULL COMMENT '登录用户ID',
* `loginagent` VARCHAR(128) NOT NULL COMMENT '登录端信息',
* `loginip` VARCHAR(255) NOT NULL COMMENT '登录IP',
* `logintime` BIGINT(20) NOT NULL COMMENT '登录时间',
* `logouttime` BIGINT(20) NOT NULL COMMENT '注销时间',
* PRIMARY KEY (`sessionid`)
* ) ENGINE=INNODB DEFAULT CHARSET=utf8;
*
* @author zhangjx
*/
public class LoginTestRecord {
@Id
private String sessionid;
private int userid;
private String loginagent;
private String loginip;
private long logintime;
private long logouttime;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getLoginagent() {
return loginagent;
}
public void setLoginagent(String loginagent) {
this.loginagent = loginagent;
}
public String getLoginip() {
return loginip;
}
public void setLoginip(String loginip) {
this.loginip = loginip;
}
public long getLogintime() {
return logintime;
}
public void setLogintime(long logintime) {
this.logintime = logintime;
}
public long getLogouttime() {
return logouttime;
}
public void setLogouttime(long logouttime) {
this.logouttime = logouttime;
}
}

View File

@@ -0,0 +1,92 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.io.Serializable;
import javax.persistence.*;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
@DistributeTable(strategy = LoginUserRecord.TableStrategy.class)
public class LoginUserRecord extends BaseEntity {
@Id
@Column(comment = "记录ID; 值=userid+'-'+UUID")
private String seqid = ""; //记录ID; 值=userid+'-'+UUID
@Column(updatable = false, comment = "C端用户ID")
private long userid; //C端用户ID
@Column(comment = "LoginRecord主键")
private String loginid = ""; //LoginRecord主键
@Column(updatable = false, comment = "创建时间")
private long createtime; //创建时间
/** 以下省略getter setter方法 */
//
public String getSeqid() {
return seqid;
}
public void setSeqid(String seqid) {
this.seqid = seqid;
}
public long getUserid() {
return userid;
}
public void setUserid(long userid) {
this.userid = userid;
}
public String getLoginid() {
return loginid;
}
public void setLoginid(String loginid) {
this.loginid = loginid;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
public static class TableStrategy implements DistributeTableStrategy<LoginUserRecord> {
@Override
public String getTable(String table, LoginUserRecord bean) {
return getTable(table, bean.getUserid());
}
@Override
public String getTable(String table, FilterNode node) {
Serializable id = node.findValue("userid");
if (id != null) return getTable(table, id);
return getHashTable(table, (Integer) node.findValue("#hash"));
}
@Override
public String getTable(String table, Serializable primary) {
String id = (String) primary;
return getHashTable(table, (int) (Long.parseLong(id.substring(0, id.indexOf('-'))) % 100));
}
private String getHashTable(String table, int hash) {
int pos = table.indexOf('.');
return "platf_login." + table.substring(pos + 1) + "_" + (hash > 9 ? hash : ("0" + hash));
}
}
}

View File

@@ -0,0 +1,141 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.lang.reflect.Method;
import java.util.*;
import org.redkale.source.VirtualEntity;
import org.redkale.source.FilterNodeBean;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterColumn;
import org.redkale.util.Sheet;
import org.redkale.source.FilterBean;
import org.redkale.source.Flipper;
import org.redkale.source.EntityInfo;
import org.redkale.source.FilterNode;
import java.util.concurrent.*;
import java.util.function.BiFunction;
import javax.persistence.*;
import org.redkale.convert.json.*;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
public class TestSourceCache {
public static class TestEntityBean implements FilterBean {
@FilterColumn(express = FilterExpress.GREATERTHAN)
public int userid;
@FilterColumn(express = FilterExpress.LIKE)
public String username;
public TestEntityBean(int userid, String username) {
this.userid = userid;
this.username = username;
}
}
public static void main(String[] args) throws Exception {
final BiFunction<DataSource, Class, List> fullloader = (DataSource t, Class u) -> null;
Method method = EntityInfo.class.getDeclaredMethod("load", Class.class, boolean.class, Properties.class,
DataSource.class, BiFunction.class);
method.setAccessible(true);
final EntityInfo<TestEntity> info = (EntityInfo<TestEntity>) method.invoke(null, TestEntity.class, false, new Properties(), null, fullloader);
TestEntity[] entitys = new TestEntity[10_0000];
for (int i = 0; i < entitys.length; i++) {
entitys[i] = new TestEntity(i + 1, "用户_" + (i + 1));
}
long s = System.currentTimeMillis();
for (TestEntity en : entitys) {
info.getCache().insert(en);
}
long e = System.currentTimeMillis() - s;
System.out.println("插入十万条记录耗时: " + e / 1000.0 + "");
s = System.currentTimeMillis();
TestEntity one = info.getCache().find(9999);
e = System.currentTimeMillis() - s;
System.out.println("十万条数据中查询一条记录耗时: " + e / 1000.0 + "" + one);
final Flipper flipper = new Flipper(2);
flipper.setSort("userid DESC, createtime DESC");
final FilterNode node = FilterNode.create("userid", FilterExpress.GREATERTHAN, 1000).and("username", FilterExpress.LIKE, "用户");
System.out.println("node = " + node);
Sheet<TestEntity> sheet = info.getCache().querySheet(null, flipper, node);
System.out.println(sheet);
System.out.println(info.getCache().querySheet(null, flipper, FilterNodeBean.createFilterNode(new TestEntityBean(1000, "用户"))));
final CountDownLatch cdl = new CountDownLatch(100);
s = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
new Thread() {
@Override
public void run() {
for (int k = 0; k < 10; k++) {
info.getCache().querySheet(true, false, null, flipper, node);
}
cdl.countDown();
}
}.start();
}
cdl.await();
e = System.currentTimeMillis() - s;
System.out.println("十万条数据中100并发查询一页循环10次记录耗时 " + e / 1000.0 + "" + sheet); // CopyOnWriteArrayList 0.798 ConcurrentLinkedQueue 1.063
}
@VirtualEntity
@Cacheable
public static class TestEntity {
@Id
private int userid;
private String username;
private long createtime = System.currentTimeMillis();
public TestEntity() {
}
public TestEntity(int userid, String username) {
this.userid = userid;
this.username = username;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.source;
import java.io.Serializable;
import javax.persistence.*;
import org.redkale.convert.*;
import org.redkale.source.*;
/**
*
* @author zhangjx
*/
@DistributeTable(strategy = UserDetail.TableStrategy.class)
public class UserDetail extends BaseEntity {
public static class TableStrategy implements DistributeTableStrategy<UserDetail> {
@Override
public String getTable(String table, UserDetail bean) {
return getTable(table, bean.getUserid());
}
@Override
public String getTable(String table, FilterNode node) {
Serializable id = node.findValue("userid");
if (id != null) return getTable(table, id);
return getHashTable(table, (Integer) node.findValue("#hash"));
}
@Override
public String getTable(String table, Serializable userid) {
return getHashTable(table, (int) (((Long) userid) % 100));
}
private String getHashTable(String table, int hash) {
int pos = table.indexOf('.');
return "platf_user." + table.substring(pos + 1) + "_" + (hash > 9 ? hash : ("0" + hash));
}
}
@Id
private long userid; //用户ID
@Column(length = 64, comment = "用户昵称")
private String username = ""; //用户昵称
@Column(length = 32, comment = "手机号码")
private String mobile = ""; //手机号码
@Column(length = 64, comment = "密码")
@ConvertColumn(ignore = true, type = ConvertType.ALL)
private String password = ""; //密码
@Column(length = 128, comment = "备注")
private String remark = ""; //备注
@Column(updatable = false, comment = "创建时间")
private long createtime; //创建时间
/** 以下省略getter setter方法 */
public long getUserid() {
return userid;
}
public void setUserid(long userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class OneBean {
public int id;
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class OneRound {
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
import org.redkale.service.RetResult;
/**
*
* @author zhangjx
* @param <OR>
* @param <OB>
*/
public class OneService<OR extends OneRound, OB extends OneBean> {
public RetResult run(OR round, OB bean) {
return RetResult.success();
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class ThreeBean extends TwoBean {
public String desc;
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class ThreeRound extends TwoRound {
}

View File

@@ -0,0 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
* @param <K>
* @param <ER>
* @param <EB>
*/
public class ThreeService<K extends CharSequence, ER extends ThreeRound, EB extends ThreeBean> extends OneService<ER, EB> {
public String key(K key) {
return "" + key;
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class TwoBean extends OneBean {
public String name;
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
*/
public class TwoRound extends OneRound {
}

View File

@@ -0,0 +1,16 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
/**
*
* @author zhangjx
* @param <TR>
* @param <TB>
*/
public class TwoService<TR extends TwoRound, TB extends TwoBean> extends OneService<TR, TB> {
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.type;
import java.lang.reflect.*;
import org.redkale.util.TypeToken;
/**
*
* @author zhangjx
*/
public class TypeTokenTest {
public static void main(String[] args) throws Throwable {
Class declaringClass = ThreeService.class;
ParameterizedType declaringType = (ParameterizedType) declaringClass.getGenericSuperclass();
System.out.println("getRawType:" + declaringType.getRawType());
TypeVariable argType0 = (TypeVariable)declaringType.getActualTypeArguments()[0];
System.out.println("argType0.getBounds[0]:" + argType0.getBounds()[0]);
for (Method method : declaringClass.getMethods()) {
if (!"run".equals(method.getName())) continue;
System.out.println("返回值应该是: " + ThreeRound.class);
System.out.println("返回值结果是: " + TypeToken.getGenericType(method.getGenericParameterTypes()[0], declaringClass));
break;
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import org.redkale.convert.json.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class CreatorRecord {
private int id = -1;
private String name;
private long lval;
private boolean tval;
private byte bval;
private short sval;
private char cval;
private float fval;
private double dval;
@ConstructorParameters({"id", "name", "lval", "tval", "bval", "sval", "cval", "fval", "dval"})
CreatorRecord(int id, String name, long lval, boolean tval, byte bval, short sval, char cval, float fval, double dval) {
this.id = id;
this.name = name;
this.lval = lval;
this.tval = tval;
this.bval = bval;
this.sval = sval;
this.cval = cval;
this.fval = fval;
this.dval = dval;
}
public static void main(String[] args) throws Exception {
CreatorRecord record = Creator.create(CreatorRecord.class).create(new Object[]{null, "ss", null, true, null, (short) 45, null, 4.3f, null});
String json = record.toString();
System.out.println(json);
System.out.println(JsonConvert.root().convertFrom(CreatorRecord.class, json).toString());
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public long getLval() {
return lval;
}
public boolean isTval() {
return tval;
}
public byte getBval() {
return bval;
}
public short getSval() {
return sval;
}
public char getCval() {
return cval;
}
public float getFval() {
return fval;
}
public double getDval() {
return dval;
}
}

View File

@@ -0,0 +1,37 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import org.redkale.util.Invoker;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
*
* @author zhangjx
*/
public class InvokerTest {
@Test
public void run1() {
Invoker<String, String> invoker = Invoker.create(String.class, "toLowerCase");
Assertions.assertEquals("aaa", invoker.invoke("AAA"));
}
@Test
public void run2() {
Invoker<String, Boolean> invoker = Invoker.create(String.class, "equals", Object.class);
Assertions.assertTrue(invoker.invoke("AAA", "AAA"));
}
@Test
public void run3() {
Invoker<java.sql.Date, java.sql.Date> invoker = Invoker.create(java.sql.Date.class, "valueOf", String.class);
String str = new java.sql.Date(System.currentTimeMillis()).toString();
System.out.println(str);
Assertions.assertEquals(str, invoker.invoke(null, str).toString());
}
}

View File

@@ -0,0 +1,67 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import java.io.File;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.reflect.Field;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class ResourceInjectMain {
public static void main(String[] args) throws Throwable {
ResourceFactory factory = ResourceFactory.create();
factory.register(new CustomConfLoader());
InjectBean bean = new InjectBean();
factory.inject(bean);
}
public static class CustomConfLoader implements ResourceInjectLoader<CustomConf> {
@Override
public void load(ResourceFactory factory, Object src, CustomConf annotation, Field field, Object attachment) {
try {
field.set(src, new File(annotation.path()));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("对象是 src =" + src + ", path=" + annotation.path());
}
@Override
public Class<CustomConf> annotationType() {
return CustomConf.class;
}
}
public static class InjectBean {
@CustomConf(path = "conf/test.xml")
public File conf;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
@Documented
@Target({FIELD})
@Retention(RUNTIME)
public static @interface CustomConf {
String path();
}
}

View File

@@ -0,0 +1,158 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template bigint, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import java.math.*;
import javax.annotation.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
public class ResourceTest {
public static void main(String[] args) throws Exception {
ResourceFactory factory = ResourceFactory.create();
factory.register("property.id", "2345"); //注入String类型的property.id
AService aservice = new AService();
BService bservice = new BService("eeeee");
factory.register(aservice); //放进Resource池内默认的资源名name为""
factory.register(bservice); //放进Resource池内默认的资源名name为""
factory.inject(aservice); //给aservice注入id、bservicebigint没有资源所以为null
factory.inject(bservice); //给bservice注入id、aservice
System.out.println(aservice); //输出结果为:{id:"2345", intid: 2345, bigint:null, bservice:{name:eeeee}}
System.out.println(bservice); //输出结果为:{name:"eeeee", id: 2345, aserivce:{id:"2345", intid: 2345, bigint:null, bservice:{name:eeeee}}}
factory.register("seqid", 200); //放进Resource池内, 同时ResourceFactory会自动更新aservice的seqid值
System.out.println(factory.find("seqid", int.class)); //输出结果为200
factory.register("bigint", new BigInteger("666666666666666")); //放进Resource池内, 同时ResourceFactory会自动更新aservice对象的bigint值
System.out.println(aservice); //输出结果为:{id:"2345", intid: 2345, bigint:666666666666666, bservice:{name:eeeee}} 可以看出seqid与bigint值都已自动更新
factory.register("property.id", "6789"); //更新Resource池内的id资源值, 同时ResourceFactory会自动更新aservice、bservice的id值
System.out.println(aservice); //输出结果为:{id:"6789", intid: 6789, bigint:666666666666666, bservice:{name:eeeee}}
System.out.println(bservice); //输出结果为:{name:"eeeee", id: 6789, aserivce:{id:"6789", intid: 6789, bigint:666666666666666, bservice:{name:eeeee}}}
bservice = new BService("ffff");
factory.register(bservice); //更新Resource池内name=""的BService资源, 同时ResourceFactory会自动更新aservice的bservice对象
factory.inject(bservice);
System.out.println(aservice); //输出结果为:{id:"6789", intid: 6789, bigint:666666666666666, bservice:{name:ffff}}
}
}
class BService {
@Resource(name = "property.id")
private String id;
@Resource
private AService aservice;
private String name = "";
@ResourceListener
private void changeResource(String name, Object newVal, Object oldVal) {
System.out.println("@Resource = " + name + " 资源变更: newVal = " + newVal + ", oldVal = " + oldVal);
}
@ConstructorParameters({"name"})
public BService(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public AService getAservice() {
return aservice;
}
public void setAservice(AService aservice) {
this.aservice = aservice;
}
@Override
public String toString() {
return "{name:\"" + name + "\", id: " + id + ", aserivce:" + aservice + "}";
}
}
class AService {
@Resource(name = "property.id")
private String id;
@Resource(name = "property.id") //property.开头的资源名允许String自动转换成primitive数值类型
private int intid;
@Resource(name = "bigint")
private BigInteger bigint;
@Resource(name = "seqid")
private int seqid;
@Resource
private BService bservice;
@Override
public String toString() {
return "{id:\"" + id + "\", intid: " + intid + ", bigint:" + bigint + ", bservice:" + (bservice == null ? null : ("{name:" + bservice.getName() + "}")) + "}";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getIntid() {
return intid;
}
public void setIntid(int intid) {
this.intid = intid;
}
public int getSeqid() {
return seqid;
}
public void setSeqid(int seqid) {
this.seqid = seqid;
}
public BigInteger getBigint() {
return bigint;
}
public void setBigint(BigInteger bigint) {
this.bigint = bigint;
}
public void setBservice(BService bservice) {
this.bservice = bservice;
}
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
/**
*
* @author zhangjx
*/
public class TestABean {
public long time;
}

View File

@@ -0,0 +1,46 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import java.util.Map;
/**
*
* @author zhangjx
*/
public class TestBean extends TestABean {
private String name;
private int id;
private Map<String, String> map;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
/**
*
* @author zhangjx
*/
public class TestXBean extends TestBean{
}

View File

@@ -0,0 +1,104 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.util;
import org.redkale.util.Reproduce;
import org.redkale.util.Attribute;
/**
*
* @author zhangjx
*/
public class UntilTestMain {
public static void main(String[] args) throws Throwable {
reproduce(args);
attribute(args);
}
public static void reproduce(String[] args) throws Throwable {
final TestBean bean = new TestBean();
bean.setId(123456);
bean.setName("zhangjx");
bean.time = 2000;
final TestXBean beanx = new TestXBean();
Reproduce<TestXBean, TestBean> action1 = Reproduce.create(TestXBean.class, TestBean.class);
Reproduce<TestXBean, TestBean> action2 = new Reproduce<TestXBean, TestBean>() {
@Override
public TestXBean apply(TestXBean dest, TestBean src) {
dest.time = src.time;
dest.setId(src.getId());
dest.setName(src.getName());
dest.setMap(src.getMap());
return dest;
}
};
final int count = 1_000_000;
long s = System.nanoTime();
for (int i = 0; i < count; i++) {
action2.apply(beanx, bean);
}
long e = System.nanoTime() - s;
System.out.println("静态Reproduce耗时: " + e);
s = System.nanoTime();
for (int i = 0; i < count; i++) {
action1.apply(beanx, bean);
}
e = System.nanoTime() - s;
System.out.println("动态Reproduce耗时: " + e);
System.out.println();
}
public static void attribute(String[] args) throws Throwable {
final TestBean bean = new TestBean();
bean.setId(123456);
bean.setName("zhangjx");
Attribute<TestBean, String> action1 = Attribute.create(TestBean.class.getDeclaredField("name"));
Attribute<TestBean, String> action2 = new Attribute<TestBean, String>() {
@Override
public String field() {
return "name";
}
@Override
public String get(TestBean obj) {
return obj.getName();
}
@Override
public void set(TestBean obj, String value) {
obj.setName(value);
}
@Override
public Class type() {
return String.class;
}
@Override
public Class declaringClass() {
return TestBean.class;
}
};
final int count = 1_000_000;
long s = System.nanoTime();
for (int i = 0; i < count; i++) {
action2.set(bean, "zhangjx2");
}
long e = System.nanoTime() - s;
System.out.println("静态Attribute耗时: " + e);
s = System.nanoTime();
for (int i = 0; i < count; i++) {
action1.set(bean, "zhangjx2");
}
e = System.nanoTime() - s;
System.out.println("动态Attribute耗时: " + e);
System.out.println();
System.out.println("TestBean.map: " + Attribute.create(TestBean.class.getDeclaredField("map")).genericType());
}
}

View File

@@ -0,0 +1,76 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.websocket;
import org.redkale.net.http.WebServlet;
import org.redkale.net.http.WebSocketServlet;
import org.redkale.net.http.WebSocket;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.test.rest.*;
import org.redkale.util.*;
/**
*
* @author zhangjx
*/
@WebServlet("/ws/chat")
public class ChatWebSocketServlet extends WebSocketServlet {
@Resource
private UserService userService;
@Override
public void init(HttpContext context, AnyValue conf) {
System.out.println("本实例的WebSocketNode: " + super.node);
}
@Override
public void destroy(HttpContext context, AnyValue conf) {
System.out.println("关闭了ChatWebSocketServlet");
}
@Override
protected WebSocket<Integer, ChatMessage> createWebSocket() {
return new WebSocket<Integer, ChatMessage>() {
private UserInfo user;
@Override
public void onMessage(ChatMessage message, boolean last) { // text 接收的格式: {"receiveid":200000001, "content":"Hi Redkale!"}
message.sendid = user.getUserid(); //将当前用户设为消息的发送方
message.sendtime = System.currentTimeMillis(); //设置消息发送时间
//给接收方发送消息, 即使接收方在其他WebSocket进程节点上有链接Redkale也会自动发送到其他链接进程节点上。
super.sendMessage(message, message.receiveid);
}
@Override
protected CompletableFuture<Integer> createUserid() { //创建用户ID
this.user = userService.current(String.valueOf(super.getSessionid()));
return CompletableFuture.completedFuture(this.user == null ? null : this.user.getUserid());
}
@Override
public CompletableFuture<String> onOpen(HttpRequest request) {
return CompletableFuture.completedFuture(request.getSessionid(false)); //以request中的sessionid字符串作为WebSocket的sessionid
}
};
}
public static class ChatMessage {
public int sendid; //发送方用户ID
public int receiveid; //接收方用户ID
public String content; //文本消息内容
public long sendtime; //消息发送时间
}
}

View File

@@ -0,0 +1,29 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.websocket;
import java.io.ByteArrayOutputStream;
import java.net.Socket;
/**
*
* @author zhangjx
*/
public class Flash843 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("113.105.88.229", 843);
socket.getOutputStream().write("<policy-file-request/>".getBytes());
socket.getOutputStream().flush();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int pos;
while ((pos = socket.getInputStream().read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
System.out.println(out.toString());
}
}

View File

@@ -0,0 +1,125 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.websocket;
import org.redkale.net.http.WebServlet;
import org.redkale.net.http.WebSocketServlet;
import org.redkale.net.http.HttpRequest;
import org.redkale.net.http.WebSocket;
import org.redkale.net.http.HttpServer;
import org.redkale.util.TypeToken;
import org.redkale.util.AnyValue;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
/**
*
* @author zhangjx
*/
@WebServlet({"/ws/listen"})
public class VideoWebSocketServlet extends WebSocketServlet {
private final Map<Serializable, Entry> sessions = new java.util.concurrent.ConcurrentHashMap<>();
private final Map<Serializable, String> users = new HashMap<>();
private static final class Entry {
public WebSocket socket;
public String username;
public Serializable userid;
}
public VideoWebSocketServlet() {
super();
users.put("zhangjx", "xxxx");
}
@Override
protected WebSocket createWebSocket() {
WebSocket socket = new WebSocket() {
private final TypeToken<Map<String, String>> mapToken = new TypeToken<Map<String, String>>() {
};
private boolean repeat = false;
@Override
public CompletableFuture<String> onOpen(final HttpRequest request) {
String uri = request.getRequestURI();
int pos = uri.indexOf("/listen/");
uri = uri.substring(pos + "/listen/".length());
this.repeat = sessions.get(uri) != null;
if (!this.repeat) this.repeat = users.get(uri) == null;
String sessionid = Long.toString(System.nanoTime());
if (uri.indexOf('\'') >= 0 || uri.indexOf('"') >= 0) return null;
if (!repeat) sessionid = uri;
return CompletableFuture.completedFuture(sessionid);
}
@Override
public CompletableFuture onConnected() {
if (repeat) {
super.close();
} else {
Entry entry = new Entry();
entry.userid = this.getSessionid();
entry.username = users.get(entry.userid);
sessions.put(this.getSessionid(), entry);
StringBuilder sb = new StringBuilder();
for (Map.Entry<Serializable, Entry> en : sessions.entrySet()) {
if (sb.length() > 0) sb.append(',');
sb.append("{'userid':'").append(en.getKey()).append("','username':'").append(en.getValue().username).append("'}");
}
super.send(("{'type':'user_list','users':[" + sb + "]}").replace('\'', '"'));
String msg = ("{'type':'discover_user','user':{'userid':'" + this.getSessionid() + "','username':'" + users.get(this.getSessionid()) + "'}}").replace('\'', '"');
super.broadcastMessage(msg);
}
return null;
}
@Override
public void onMessage(Object text, boolean last) {
//System.out.println("接收到消息: " + text);
super.broadcastMessage(text, last);
}
@Override
public CompletableFuture onClose(int code, String reason) {
sessions.remove(this.getSessionid());
String msg = ("{'type':'remove_user','user':{'userid':'" + this.getSessionid() + "','username':'" + users.get(this.getSessionid()) + "'}}").replace('\'', '"');
return super.broadcastMessage(msg);
}
@Override
protected CompletableFuture<Serializable> createUserid() {
return CompletableFuture.completedFuture("2");
}
};
return socket;
}
public static void main(String[] args) throws Throwable {
CountDownLatch cdl = new CountDownLatch(1);
AnyValue.DefaultAnyValue config = AnyValue.create()
.addValue("threads", System.getProperty("threads"))
.addValue("bufferPoolSize", System.getProperty("bufferPoolSize"))
.addValue("responsePoolSize", System.getProperty("responsePoolSize"))
.addValue("host", System.getProperty("host", "0.0.0.0"))
.addValue("port", System.getProperty("port", "8070"))
.addValue("root", System.getProperty("root", "./root3/"));
HttpServer server = new HttpServer();
server.addHttpServlet("/pipes", new VideoWebSocketServlet(), "/listen/*");
server.init(config);
server.start();
cdl.await();
}
}

View File

@@ -0,0 +1,27 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.ws;
import org.redkale.convert.json.JsonConvert;
/**
*
* @author zhangjx
*/
public class ChatMessage {
public int fromuserid;
public int touserid;
public String fromusername;
public String content;
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -0,0 +1,49 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.ws;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.redkale.net.http.WebSocketNode;
import org.redkale.service.*;
import org.redkale.util.Comment;
/**
*
* @author zhangjx
*/
public class ChatService implements Service {
@Comment("key=用户IDvalue=房间ID")
private final Map<Integer, Integer> userToRooms = new ConcurrentHashMap<>();
@Comment("key=房间IDvalue=用户ID列表")
private final Map<Integer, List<Integer>> roomToUsers = new ConcurrentHashMap<>();
protected final AtomicInteger idcreator = new AtomicInteger(10000);
@Resource(name = "chat")
protected WebSocketNode wsnode;
@Comment("创建一个用户ID")
public int createUserid() {
return idcreator.incrementAndGet();
}
@Comment("用户加入指定房间")
public boolean joinRoom(int userid, int roomid) {
userToRooms.put(userid, roomid);
roomToUsers.computeIfAbsent(roomid, (id) -> new CopyOnWriteArrayList()).add(userid);
System.out.println("加入房间: roomid: " + roomid);
return true;
}
public void chatMessage(ChatMessage message) {
wsnode.broadcastMessage(message);
}
}

View File

@@ -0,0 +1,94 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.ws;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.test.rest.*;
/**
*
* @author zhangjx
*/
//anyuser = true 表示WebSocket.createUserid返回的值不表示用户登录态
@RestWebSocket(name = "chat", catalog = "ws", comment = "文字聊天", anyuser = true)
public class ChatWebSocket extends WebSocket<Integer, Object> {
//@Resource标记的Field只能被修饰为public或protected
@Resource
protected ChatService service;
@Resource
protected UserService userService;
protected UserInfo user;
@Override
protected CompletableFuture<String> onOpen(final HttpRequest request) {
LoginBean bean = request.getJsonParameter(LoginBean.class, "bean");
RetResult<UserInfo> ret = userService.login(bean);
if (ret.isSuccess()) { //登录成功
user = ret.getResult();
//随机创建一个sessionid
return CompletableFuture.completedFuture(request.getSessionid(true));
} else { //登录失败, 返回null
return send("{\"onLoginFailMessage\":" + ret + "}").thenApply(x -> null);
}
}
@Override
protected CompletableFuture<Integer> createUserid() {
return CompletableFuture.completedFuture(user.getUserid());
}
/**
* 浏览器WebSocket请求
* <pre>
* websocket.send(JSON.stringify({
* sendmessage:{
* message:{
* content : "这是聊天内容"
* },
* extmap:{
* "a":1,
* "b":"haha"
* }
* }
* }));
* </pre>
*
* @param message 参数1
* @param extmap 参数2
*/
@RestOnMessage(name = "sendmessage")
public void onChatMessage(ChatMessage message, Map<String, String> extmap) {
message.fromuserid = getUserid();
message.fromusername = "用户" + getUserid();
System.out.println("获取消息: message: " + message + ", map: " + extmap);
service.chatMessage(message);
}
/**
* 浏览器WebSocket请求
* <pre>
* websocket.send(JSON.stringify({
* joinroom:{
* roomid: 10212
* }
* }));
* </pre>
*
* @param roomid 参数1
*/
@RestOnMessage(name = "joinroom")
public void onJoinRoom(int roomid) {
service.joinRoom(getUserid(), roomid);
}
}

View File

@@ -0,0 +1,169 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.wsdync;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.BiConsumer;
import javax.annotation.Resource;
import org.redkale.convert.ConvertDisabled;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*;
import org.redkale.test.ws.ChatMessage;
import org.redkale.test.ws.ChatService;
import org.redkale.test.ws.ChatWebSocket;
/**
*
* @author zhangjx
*/
//@WebServlet("/ws/chat")
public final class _DyncChatWebSocketServlet extends WebSocketServlet {
@Resource
private ChatService _redkale_resource_0;
public static Map<String, Annotation[]> _redkale_annotations;
public _DyncChatWebSocketServlet() {
super();
this.messageTextType = _DyncChatWebSocketMessage.class;
}
@Override
protected <G extends Serializable, T> WebSocket<G, T> createWebSocket() {
return (WebSocket) new _DyncChatWebSocket(_redkale_resource_0);
}
@Override
protected BiConsumer<WebSocket, Object> createRestOnMessageConsumer() {
return new _DynRestOnMessageConsumer();
}
public static class _DyncChatWebSocket extends ChatWebSocket {
public _DyncChatWebSocket(ChatService service) {
super();
this.service = service;
}
}
public static class _DyncChatWebSocketMessage {
public _DyncChatWebSocketMessage_sendmessagee_00 sendmessage;
public _DyncChatWebSocketMessage_joinroom_01 joinroom;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
public static class _DyncChatWebSocketMessage_sendmessagee_00 implements WebSocketParam, Runnable {
public ChatMessage message;
public Map<String, String> extmap;
@ConvertDisabled
public _DyncChatWebSocket _redkale_websocket;
@Override
public String[] getNames() {
return new String[]{"message", "extmap"};
}
@Override
public <T> T getValue(String name) {
if ("message".equals(name)) return (T) message;
if ("extmap".equals(name)) return (T) extmap;
return null;
}
@Override
public Annotation[] getAnnotations() {
Annotation[] annotations = _redkale_annotations.get("org/redkale/test/wsdync/_DyncChatWebSocketServlet$_DyncChatWebSocketMessage_sendmessagee_00");
if (annotations == null) return new Annotation[0];
return Arrays.copyOf(annotations, annotations.length);
}
public void execute(_DyncChatWebSocket websocket) {
this._redkale_websocket = websocket;
websocket.preOnMessage("sendmessage", this, this);
}
@Override
public void run() {
_redkale_websocket.onChatMessage(this.message, this.extmap);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
public static class _DyncChatWebSocketMessage_joinroom_01 implements WebSocketParam, Runnable {
public int roomid;
@ConvertDisabled
public _DyncChatWebSocket _redkale_websocket;
@Override
public String[] getNames() {
return new String[]{"roomid"};
}
@Override
public <T> T getValue(String name) {
if ("roomid".equals(name)) return (T) (Integer) roomid;
return null;
}
@Override
public Annotation[] getAnnotations() {
Annotation[] annotations = _redkale_annotations.get("org/redkale/test/wsdync/_DyncChatWebSocketServlet$_DyncChatWebSocketMessage_joinroom_01");
if (annotations == null) return new Annotation[0];
return Arrays.copyOf(annotations, annotations.length);
}
public void execute(_DyncChatWebSocket websocket) {
this._redkale_websocket = websocket;
websocket.preOnMessage("joinroom", this, this);
}
@Override
public void run() {
_redkale_websocket.onJoinRoom(this.roomid);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
public static class _DynRestOnMessageConsumer implements BiConsumer<WebSocket, Object> {
@Override
public void accept(WebSocket websocket0, Object message0) {
_DyncChatWebSocket websocket = (_DyncChatWebSocket) websocket0;
_DyncChatWebSocketMessage message = (_DyncChatWebSocketMessage) message0;
if (message.sendmessage != null) {
message.sendmessage.execute(websocket);
return;
}
if (message.joinroom != null) {
message.joinroom.execute(websocket);
return;
}
}
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ALL</shared-cache-mode>
<validation-mode>NONE</validation-mode>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/test?autoReconnect=true&amp;autoReconnectForPools=true&amp;characterEncoding=utf8"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="1234"/>
</properties>
</persistence-unit>
</persistence>