原码:
package com.anran.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author anran
* @version 创建时间:2017年9月9日 上午11:22:16
* 类说明 :分别为每一个创建本地对应端口的客户端创建一个线程,并获取每一个客户端的输入
*/
public class EchoServer {
private static final int ECHO_SERVER_PORT = 6789;
public static void main(String[] args) {
// 创建监听本地端口的服务
try (ServerSocket server = new ServerSocket(ECHO_SERVER_PORT)) {
System.out.println("服务器已经启动...");
while (true) {
// 侦听并接受到此套接字的连接。(如果有才会往下运行,否则一直等待)
Socket client = server.accept();
// 当有链接接入的时候,创建线程获取对于对应的后续操作(异步)
new Thread(new ClientHandler(client)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClientHandler implements Runnable {
private Socket client;
public ClientHandler(Socket client) {
this.client = client;
}
@Override
public void run() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(
client.getInputStream()));
PrintWriter pw = new PrintWriter(client.getOutputStream())) {
String msg = null;
while (null != (msg = br.readLine())) {
System.out.println("收到" + client.getInetAddress() + "发送的: "
+ msg);
}
pw.println(msg);
pw.flush();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.anran.socket;
import java.io.PrintWriter;
import java.net.Socket;
/**
* @author anran
* @version 创建时间:2017年9月9日 上午11:22:56
* 类说明 : 创建多个线程,向一个端口发送信息(这个端口必须是要已经被其它程序监听)
*/
public class EchoClient {
public static void main(String[] args) throws Exception {
String ip = "localhost";
int port = 6789;
for(int i=0; i<5; i++){
new Thread(new CreateSocket(ip, port)).start();
}
}
private static class CreateSocket implements Runnable {
private String ip;
private int port;
CreateSocket(String ip, int port){
this.ip = ip;
this.port = port;
}
@Override
public void run() {
try (Socket client = new Socket(ip, port)){
PrintWriter pw = new PrintWriter(client.getOutputStream());
for (int i=0; i<2; i++){
pw.println("{" + Thread.currentThread() + "}" + i);
//flush()方法可以使得监听端口读取一次
pw.flush();
Thread.sleep(2000);
}
}catch (Exception e){
e.printStackTrace();
}
//当该客户端close()的时候,对应监听线程也会执行完成(这里不写是因为Java 7的TWR会自己关闭)
// client.close();
}
}
}
输出:
服务器已经启动...
收到/127.0.0.1发送的: {Thread[Thread-1,5,main]}0
收到/127.0.0.1发送的: {Thread[Thread-2,5,main]}0
收到/127.0.0.1发送的: {Thread[Thread-4,5,main]}0
收到/127.0.0.1发送的: {Thread[Thread-0,5,main]}0
收到/127.0.0.1发送的: {Thread[Thread-3,5,main]}0
收到/127.0.0.1发送的: {Thread[Thread-1,5,main]}1
收到/127.0.0.1发送的: {Thread[Thread-3,5,main]}1
收到/127.0.0.1发送的: {Thread[Thread-2,5,main]}1
收到/127.0.0.1发送的: {Thread[Thread-4,5,main]}1
收到/127.0.0.1发送的: {Thread[Thread-0,5,main]}1
如果希望用NIO的多路复用套接字实现服务器,代码如下所示。NIO的操作虽然带来了更好的性能,但是有些操作是比较底层的,对于初学者来说还是有些难于理解(我也没有理解,待学习!!!!!!)。
package com.anran.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午12:19:32 类说明 :
*/
public class EchoServerNIO {
private static final int ECHO_SERVER_PORT = 6789;
private static final int ECHO_SERVER_TIMEOUT = 5000;
private static final int BUFFER_SIZE = 1024;
private static ServerSocketChannel serverChannel = null;
private static Selector selector = null; // 多路复用选择器
private static ByteBuffer buffer = null; // 缓冲区
public static void main(String[] args) {
init();
listen();
}
private static void init() {
try {
serverChannel = ServerSocketChannel.open();
buffer = ByteBuffer.allocate(BUFFER_SIZE);
serverChannel.socket()
.bind(new InetSocketAddress(ECHO_SERVER_PORT));
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void listen() {
while (true) {
try {
if (selector.select(ECHO_SERVER_TIMEOUT) != 0) {
Iterator it = selector.selectedKeys()
.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
it.remove();
handleKey(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void handleKey(SelectionKey key) throws IOException {
SocketChannel channel = null;
try {
if (key.isAcceptable()) {
ServerSocketChannel serverChannel = (ServerSocketChannel) key
.channel();
channel = serverChannel.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
channel = (SocketChannel) key.channel();
buffer.clear();
if (channel.read(buffer) > 0) {
buffer.flip();
CharBuffer charBuffer = CharsetHelper.decode(buffer);
String msg = charBuffer.toString();
System.out.println("收到" + channel.getRemoteAddress()
+ "的消息:" + msg);
channel.write(CharsetHelper.encode(CharBuffer.wrap(msg)));
} else {
channel.close();
}
}
} catch (Exception e) {
e.printStackTrace();
if (channel != null) {
channel.close();
}
}
}
}
package com.anran.socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午12:20:16 类说明 :
*/
public class CharsetHelper {
private static final String UTF_8 = "UTF-8";
private static CharsetEncoder encoder = Charset.forName(UTF_8).newEncoder();
private static CharsetDecoder decoder = Charset.forName(UTF_8).newDecoder();
private CharsetHelper() {
}
public static ByteBuffer encode(CharBuffer in)
throws CharacterCodingException {
return encoder.encode(in);
}
public static CharBuffer decode(ByteBuffer in)
throws CharacterCodingException {
return decoder.decode(in);
}
}
代码:
package com.anran.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午4:05:32 类说明 :
*/
public class ConnectionSql {
public static void main(String[] args) throws ClassNotFoundException,
SQLException {
String driver = "org.postgresql.Driver";
String url = "jdbc:postgresql://localhost:5432/messagepush_db";
String user = "postgres";
String password = "ajl930919";
// 加载数据库驱动
Class.forName(driver);
// 获取数据库连接
Connection conn = DriverManager.getConnection(url, user, password);
try {
// 创建语句
PreparedStatement ps = conn
.prepareStatement("select * from rule where 3=?");
try {
// 填写语句中却是的参数
ps.setInt(1, 3);
// 执行语句
ResultSet set = ps.executeQuery();
try {
// 读取所有行
while (set.next()) {
// 获取某一行中列的值
System.out.println(set.getInt("rid") + " "
+ set.getString("rname"));
}
} finally {
set.close();
}
} finally {
ps.close();
}
} finally {
conn.close();
}
}
}
输出:
1 系统推送
2 微信推送规则
3 支付宝推送规则
4 1
8 无短信推送
9 NoSMS
10 无短信
事务中数据读取常见问题:
时间 | 转账事务A | 取款事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询账户余额为1000元 | |
T4 | 取出500元余额修改为500元 | |
T5 | 查询账户余额为500元(脏读) | |
T6 | 撤销事务余额恢复为1000元 | |
T7 | 汇入100元把余额修改为600元 | |
T8 | 提交事务 |
时间 | 转账事务A | 取款事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询账户余额为1000元 | |
T4 | 查询账户余额为1000元 | |
T5 | 取出100元修改余额为900元 | |
T6 | 提交事务 | |
T7 | 查询账户余额为900元(不可重复读) |
时间 | 转账事务A | 取款事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 统计总存款为10000元 | |
T4 | 新增一个存款账户存入100元 | |
T5 | 提交事务 | |
T6 | 再次统计总存款为10100元(幻读) |
时间 | 取款事务A | 转账事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询账户余额为1000元 | |
T4 | 查询账户余额为1000元 | |
T5 | 汇入100元修改余额为1100元 | |
T6 | 提交事务 | |
T7 | 取出100元将余额修改为900元) | |
T8 | 撤销事务 | |
T9 | 余额恢复为1000元(丢失更新) |
时间 | 转账事务A | 取款事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询账户余额为1000元 | |
T4 | 查询账户余额为1000元 | |
T5 | 取出100元将余额修改为900元 | |
T6 | 提交事务 | |
T7 | 汇入100元将余额修改为1100元 | |
T8 | 提交事务 | |
T9 | 查询账户余额为1100元(丢失更新) |
package com.anran.object;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午8:20:22 类说明 :
*/
public class Object {
public Object() {
// TODO Auto-generated constructor stub
}
public Object(String str) {
}
}
package com.anran.object;
import java.lang.reflect.InvocationTargetException;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午8:20:37 类说明 :
*/
public class ObjectTest {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException {
// 类的反射创建对象
Object object = Object.class.newInstance();
// 获取默认构造函数构建对象
Object object1 = Object.class.getDeclaredConstructor().newInstance(
"Hello");
// 获取其它构造函数构建对象
Object object2 = Object.class.getConstructor(String.class).newInstance(
"anran");
}
}
原码:
package com.anran.object;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午8:20:22 类说明 :
*/
public class Object {
private int num = 99;
public Object() {
// TODO Auto-generated constructor stub
}
public Object(String str) {
}
private int save(String str, Integer i){
System.out.println(str + " " + i);
return 0;
}
}
package com.anran.object;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author anran
* @version 创建时间:2017年9月9日 下午8:20:37 类说明 :
*/
public class ObjectTest {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
Object object = new Object();
//获取对象中私有的变量
//getDeclaredFields()获取所有私有变量
Field f = object.getClass().getDeclaredField("num");
//设置属性是可以使用
f.setAccessible(true);
//获取私有变量名称
System.out.println(f.getName());
//获取私有变量的类型
System.out.println(f.getType());
//获取对象私有变量的值
System.out.println(f.get(object));
//修改对象私有变量的值
f.set(object, 1);
System.out.println(f.get(object));
//获取对象中私有方法
//获取所有私有方法getDeclaredMethods()
Method m = object.getClass().getDeclaredMethod("save", String.class, Integer.class);
m.setAccessible(true);
//获取方法名称
System.out.println(m.getName());
//获取返回值类型
System.out.println(m.getReturnType());
//获取参数类型
Class>[] clasz = m.getParameterTypes();
for(int i=0; i< clasz.length; i++){
System.out.println(clasz[i]);
}
//调用方法
System.out.println(m.invoke(object, "anran", 1));
}
}
输出:
num
int
99
1
save
int
class java.lang.String
class java.lang.Integer
anran 1
0
public abstract class A{
……
}
public class B extends A{
……
}
B类继承自A类,那么B类和A类的关系就是Is-A的关系。
public class Heart{
……
}
public class Man{
private Heart heart = new Heart();
……
}
public abstract class Course{
……
}
public class Student{
public void Learn(Course course){
……
}
}
Student类和Course的关系就是Use-A关系,Student类总是单向指向Course,学生知道自己学的是什么课程,而课程根本不关心它被哪个学生学习。
UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(use case diagram)、类图(class diagram)、时序图(sequence diagram)、协作图(collaboration diagram)、状态图(statechart diagram)、活动图(activity diagram)、构件图(component diagram)、部署图(deployment diagram)等。
1.用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)
2.类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)
3.时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)