JAVA RPC远程调用服务器实现用户登录、注册

版权声明:耕种 by 会种地的DT男 https://blog.csdn.net/weixin_42617530/article/details/82461620

先来百科扫盲 : 什么是 RPC(反正我也刚看的)

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。


有图就不看字这里写图片描述

分层来实现

Client 客户端; Server 服务端; Controller 解析客户端请求; Service 储存方法, 实现Dao层接口; Dao 对数据库操作; 利用c3p0 数据库连接池连接数据库(绕口)
下面代码长又长(主要客户端封装Bean多), 建议复制粘贴, 创建多个类(分界线已标出)

eclipse包结构

Client 服务端

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
import com.doit.bean.Request;
import com.doit.bean.Response;
import com.doit.bean.User;

public class Client {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        try {
            Socket s = new Socket("127.0.0.1", 30000);
            OutputStream out = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            Request req = new Request();//需要建立Request类,包含方法类型和参数等,序列化发送
            User user = new User();
            user.setUserName("金刚葫芦娃");//注册 姓名
            user.setPassWord("123456");//注册 密码
            user.setPhoneNum("15000000000");//注册 手机号
            req.setClassName("com.doit.service.ServiceImpl");// 全类名
            req.setMethodName("regist");//客户端发出注册指令
            req.setParameterTypes(new Class[] { User.class });
            req.setParameterValues(new Object[] { user });
            oos.writeObject(req);//使用Object输出流发送 Request

            InputStream in = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(in);
            Response readObject = (Response) ois.readObject();
            System.out.println(readObject.getDesc());
            oos.close();
            out.close();
            s.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


----------


import java.io.Serializable;
    /**
     * Request 实现序列化
     */
public class Request implements Serializable{

    private static final long serialVersionUID = 1L;
    private String className;
    private String methodName;
    private Class[] parameterTypes;
    private Object[] parameterValues;


    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public Class[] getParameterTypes() {
        return parameterTypes;
    }
    public void setParameterTypes(Class[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }
    public Object[] getParameterValues() {
        return parameterValues;
    }
    public void setParameterValues(Object[] parameterValues) {
        this.parameterValues = parameterValues;
    }

----------
    import java.io.Serializable;
    /**
     * Response 实现序列化,实现向客户端友好响应效果
     */
public class Response implements Serializable{

    private static final long serialVersionUID = 1L;
    private Object object;
    private int status;
    private String desc;
    public Object getObject() {
        return object;
    }
    public void setObject(Object object) {
        this.object = object;
    }
    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    @Override
    public String toString() {
        return "Response [object=" + object + ", status=" + status + ", desc=" + desc + "]";
    }

}

----------
/**
*javaBean 封装User类 里面包括所需的用户基本信息, 并实现序列化
*/
import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    private String  userName;
    private String  passWord;
    private String  phoneNum;

    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public String getPhoneNum() {
        return phoneNum;
    }
    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }
    @Override
    public String toString() {
        return "User [userName=" + userName + ", passWord=" + passWord + ", phoneNum=" + phoneNum + "]";
    }



Server服务端
复制粘贴 客户端的Request 、 Response 、User 三个类(保证服务端和客户端这三个文件类名和内容相同。)
此处不再写上述3个

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import com.doit.bean.Request;
import com.doit.bean.Response;
/**
* 服务端 接收 客户端 , 反射Request中信息, 确定调用方法
*/
public class Server {

    private static final Object User = null;

    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(30000);
        while(true) {
            Socket s = ss.accept();
            InputStream ins = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(ins);
            Request readObject = (Request) ois.readObject();
            /*
             * 反射获取 Request 中的信息
             */
            //获取类名
            String className = readObject.getClassName();
            //获取方法名
            String methodName = readObject.getMethodName();
            //获取参数类型
            Class[] parameterTypes = readObject.getParameterTypes();
            //获取 参数(实参)
            Object[] parameterValues = readObject.getParameterValues();

            //调用服务器中本地方法
            Class<?> request = Class.forName(className);

            Method method = request.getMethod(methodName,parameterTypes);
            //方法调用, 创建反射Class的对象  newInstance
            Response invoke = (Response)method.invoke(request.newInstance(),parameterValues)    ;

            //System.out.println(invoke);

            OutputStream out = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            oos.writeObject(invoke);
            oos.flush();
            s.close();
        }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


----------
import com.doit.bean.Response;
import com.doit.bean.User;
/**
* 创建Service 接口 方法包括用户登录和注册
*/
public interface Service {
    public Response login(User user) throws Exception;
    public Response regist(User user) throws Exception;
}


----------
import com.doit.bean.User;
/**
* Dao 层 , 创建调用服务器接口
*/
public interface Dao {
    //注册
    public void insert(User user) throws Exception;
    public void delete() throws Exception;
    public void update() throws Exception;

    //登录
    public User getUserByNameAndPassword(User user) throws Exception;
    public User selectByname(User user)throws Exception;
}
----------
/**
* Dao 层 , 创建实现Dao接口DaoImpl类
*/
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.doit.bean.User;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DaoImpl implements Dao {
    static QueryRunner runner=null;
    static {

        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        runner = new QueryRunner(dataSource);
    }
    /*
     * 增加数据(注册)
     */
    @Override
    public void insert(User user) throws Exception {

        String sql="insert into usersinfo values(null,?,?,?)" ;
        runner.update(sql, user.getUserName(),user.getPassWord(),user.getPhoneNum());


    }
    /*
     * 登录数据库
     */
    @Override
    public User getUserByNameAndPassword(User user) throws Exception {
        String sql="select * from usersinfo where name = ? and passWord = ?";

        User query = runner.query(sql, new BeanHandler<User>(User.class),user.getUserName(),user.getPassWord());
        return query;

    }
        @Override  //实现用户注册时反应用户名是否存在功能
    public User selectByname (User user) throws Exception {
        String sql ="select * from usersinfo where name = ?";
        User query = runner.query(sql, new BeanHandler<User>(User.class),user.getUserName());
        return query;
    }
}


----------
import com.doit.bean.Response;
import com.doit.bean.User;
import com.doit.dao.Dao;
import com.doit.dao.DaoImpl;
    /*
     * Service 接口的实现类, 该类中包含对数据库操作的判断,并返回给客户端
     */
public class ServiceImpl implements Service {

    Dao daoImpl = new DaoImpl();

    @Override
    public Response login(User user) throws Exception {
        Response r = new Response();
        User res = null;
        if (user != null) {// 如果提供信息不为空, 执行登录
            res = daoImpl.getUserByNameAndPassword(user);
            if (res == null) {
                r.setStatus(500);
                r.setDesc("对不起,你的用户名或者密码错误");
            } else {
                r.setStatus(200);
                r.setDesc("欢迎登录");
                r.setObject(res);

            }
        } else {
            r.setStatus(500);
        }
        return r;

    }

    @Override
    public Response regist(User user) throws Exception {
        Response r = new Response();
        if(user.getUserName()!=null&&user.getUserName().length()>0) {//解决什么都不输入也能进行注册的问题
            User u = daoImpl.selectByname(user);
            if (u == null) {// 如果数据库中不存在要注册名字,则进行注册
                daoImpl.insert(user);
                r.setDesc("注册成功");
            } else {// 如果数据库中存在要注册的名字, 不进行注册
                r.setDesc("哇呀,这个名字已经被抢,换个试试");
            }
        }else {//解决什么都不输入也能进行注册的问题
            r.setDesc("请认真对待自己的用户名!");
        }
        return r;
    }

}

啰里啰嗦那么多 , 看着就头痛, 如何使用动态代理完善一下呢?

思考许久,还是用框架吧

猜你喜欢

转载自blog.csdn.net/weixin_42617530/article/details/82461620
今日推荐