项目截图:
服务器端:
1 首先自定义一个注解。
2 Spring启动时, 构造一个线程用于与客户端进行通信。
3 使用自定义注解,实现业务处理类
4 启动Spring, 开启服务器端
1 自定义注解:
package com.xxz.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface SocketRpc {
Class<?> value();
}
2 启动Spring构造一个线程用于通信:
package com.xxz.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.xxz.annotation.SocketRpc;
import com.xxz.bean.TranportBean;
public class ServerSocketHandler implements ApplicationContextAware, InitializingBean{
private String host;
private int port;
private Map<String, Object> hashMap = new HashMap<String, Object>();
public ServerSocketHandler(String host){
this.host = host;
}
public void setApplicationContext(ApplicationContext ctx)throws BeansException {
// 获取所有的socketrpc注解的bean
Map<String, Object> beansWithAnnotation = ctx.getBeansWithAnnotation(SocketRpc.class);
if(MapUtils.isNotEmpty(beansWithAnnotation)){
for(Object serviceBean : beansWithAnnotation.values()){
String interfaceName = serviceBean.getClass().getAnnotation(SocketRpc.class).value().getName();
hashMap.put(interfaceName, serviceBean);
}
}
}
public void afterPropertiesSet() throws Exception {
// 在这里开启服务端
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(8080);
System.out.println("the time server is started in port : " + 8080);
while(true){
socket = serverSocket.accept();
// 主线程接受客户连接请求, 不做业务逻辑处理, 需要开启一个新线程实现业务逻辑处理, 新线程处理完逻辑后,就退出
new Thread(new HandlerBizThread(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class HandlerBizThread implements Runnable{
private Socket socket;
public HandlerBizThread(Socket socket){
this.socket = socket;
}
public void run() {
ObjectInputStream ois = null;
PrintWriter out = null;
try{
ois = new ObjectInputStream(socket.getInputStream());
TranportBean readObject = (TranportBean)ois.readObject();
// 服务器端 收到类名 方法名 参数 参数类型, 调用服务器端业务实现类执行
// 根据类名, 从hashmap中得出具体的实现类
Object serviceBean = hashMap.get(readObject.getClassName());
String className = readObject.getClassName();
String methodName = readObject.getFunctionName();
Class<?> [] paramType = readObject.getParamType();
Object [] args = readObject.getArgsParam();
Class<?> forName = Class.forName( className);
Method method = forName.getMethod(methodName, paramType);
Object resp = method.invoke(serviceBean, args);
out = new PrintWriter(socket.getOutputStream(), true);
// 返回结果写到socket中, 给客户端
out.println(resp);
}catch(Exception e){
e.printStackTrace();
}
}
}
/*
class HandlerThread implements Runnable{
private Socket socket = null;
public HandlerThread(Socket socket){
this.socket= socket;
}
//使用socket来进行通信
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try{
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String currentTime = null;
String body = null;
while(true){
body = in.readLine();
if(body == null) // bufferedReader当读到最后一个字符时, 返回null
break;
System.out.println("the time server received order : " + body);
currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
out.println(currentTime);
}
}catch(IOException e){
e.printStackTrace();
//出异常时, 关闭socket流
if(socket != null){
try {
socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if(in != null){
try {
in.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if(out != null){
out.close();
}
}
}
}*/
}
3 使用自定义注解, 实现业务处理:
package com.xxz.service.impl;
import com.xxz.annotation.SocketRpc;
import com.xxz.reflectInterfaceTest.BizService;
@SocketRpc(BizService.class)
public class BizServiceImpl implements BizService {
public String hello(String param) {
param = (Integer.parseInt(param)*2)+"";
return param;
}
}
4 启动Spring:
package com.xxz.service.impl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RpcBootstrap {
@SuppressWarnings("resource")
public static void main(String[] args) {
new ClassPathXmlApplicationContext("spring.xml");
}
}
客户端:
1 构造动态代理对象
2 获取客户端想要调用服务器端的类名, 方法名, 参数类型, 参数args
3 通过socket将类名, 方法名等, 传给服务器端。并且接受服务器端执行接口的返回值。
1 构造动态代理对象:
package com.xxz.proxy;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import com.xxz.bean.TranportBean;
public class RpcProxy {
private String host;
public RpcProxy(String host){
this.host = host;
}
@SuppressWarnings("unchecked")
public <T> T create(Class<?> interfaceName){
return (T) Proxy.newProxyInstance(
interfaceName.getClassLoader(),
new Class<?> [] {interfaceName},
new InvocationHandler() {
@SuppressWarnings("resource")
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
TranportBean tranportBean = new TranportBean();
// 获取调用的类名
String className = method.getDeclaringClass().getName();
tranportBean.setClassName(className);
// 获取调用方法名
String functionName = method.getName();
tranportBean.setFunctionName(functionName);
// 获取调用方法的参数类型
Class<?> [] paramType = method.getParameterTypes();
tranportBean.setParamType(paramType);
// 获取参数
Object[] argsParam = args;
tranportBean.setArgsParam(argsParam);
// 使用socket把该对象传输过去
Socket socket = null;
BufferedReader in = null;
ObjectOutputStream oos = null;
try{
socket = new Socket("127.0.0.1", 8080);
oos= new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(tranportBean);
socket.shutdownOutput();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取服务器端写回的执行结果
String resp = in.readLine();
return resp;
}catch(IOException e){
e.printStackTrace();
}
return null;
}
});
}
}
2 启动测试类:
package com.xxz.reflectInterfaceClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.xxz.proxy.RpcProxy;
import com.xxz.reflectInterfaceTest.BizService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class HelloServiceTest {
@Autowired
private RpcProxy rpcProxy;
@Test
public void testHello(){
BizService bizService = rpcProxy.create(BizService.class);
String hello = bizService.hello("2");// 调用内部invacationhandler实现类
System.out.println(hello);
}
}