• 零基础学习java------day27-28---------电影评分数据案例,. RPC案例


    一.  电影评分数据案例

    movie:电影id

    rate:用户评分

    timeStamp:评分时间

    uid:用户id

    简化数据:

     需求:

    (1)每个用户评分最高的3部电影

    (2)每个用户评分的平均值

    (3)最大方(评分平均值高)的N个用户

    (4)最热门的N部电影(评论次数)

    (5)评价最高的N部电影

     代码(此处只写了1-3题,剩下的类似的写)

    工具类

    public class LoadDataUtils {
        
        /**
         * 以用户id分组
         */
        public static Map<String, List<Movie>> getUidMap(){
            Map<String, List<Movie>> uidMap = new HashMap<>();
            // 获取缓冲字符流
            try (
                    BufferedReader br = new BufferedReader(new FileReader("E:/javafile/movie.txt"));
                    ){
                String line = null;
                while((line = br.readLine()) != null) {
                    // 获取movie对象
                    Movie m = JSON.parseObject(line, Movie.class);
                    String uid = m.getUid();
                    List<Movie> list = uidMap.getOrDefault(uid, new ArrayList<Movie>());
                    list.add(m);
                    //将数据封装进uidMap
                    uidMap.put(uid,list);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return uidMap;
        }
        /**
         * 以movie分组
         * @return
         */
        public static Map<String, List<Movie>> getMovieMap(){
            Map<String, List<Movie>> movieMap = new HashMap<>();
            // 获取缓冲字符流
            try (
                    BufferedReader br = new BufferedReader(new FileReader("E:/javafile/movie.txt"));
                    ){
                String line = null;
                while((line = br.readLine()) != null) {
                    Movie m = JSON.parseObject(line, Movie.class);
                    String mid = m.getMovie();
                    List<Movie> list = movieMap.getOrDefault(mid, new ArrayList<Movie>());
                    list.add(m);
                    movieMap.put(mid,list);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return movieMap;
        }
    }
    View Code

    实现类

    public class MovieTest1 {
        public static void main(String[] args) {
    //        movieTop3OfEveryone();
    //        avrgOfEveryone();
            userRateTop3();
        }
        
        // 每个用户评分最高的3部电影
        public static void movieTop3OfEveryone() {
            Map<String, List<Movie>> uidMap = LoadDataUtils.getUidMap();
            System.out.println(uidMap);
            Set<Entry<String, List<Movie>>> entrySet = uidMap.entrySet();
            for (Entry<String, List<Movie>> entry : entrySet) {
                List<Movie> list = entry.getValue();
                if(list !=null && list.size() >= 3) {
                    Collections.sort(list, new Comparator<Movie>() {
                        @Override
                        public int compare(Movie o1, Movie o2) {
                            return (o1.getRate()>o2.getRate())?-1:1;
                        }
                    });
                    for (int i=0;i<3; i++) {
                        Movie m = list.get(i);
                        System.out.println(entry.getKey()+":"+m);        
                    }
                }
            }
        }
        
        // 每个用户评分的平均值
        public static void avrgOfEveryone() {
            Map<String, List<Movie>> uidMap = LoadDataUtils.getUidMap();
            Set<Entry<String, List<Movie>>> entrySet = uidMap.entrySet();
            for (Entry<String, List<Movie>> entry : entrySet) {
                List<Movie> list = entry.getValue();
                double total = 0;
                for(Movie movie : list) {
                    total += movie.getRate();
                }
                double avrg = total/list.size();
                System.out.println(entry.getKey()+"电影评分的平均分为:"+avrg);
            }
        }
        
        // 最大方(评分平均值高)的N个用户
        public static void userRateTop3() {
            Map<String, List<Movie>> uidMap = LoadDataUtils.getUidMap();
            HashMap<String, Double> map = new HashMap<>();
            Set<Entry<String, List<Movie>>> entrySet = uidMap.entrySet();
            for (Entry<String, List<Movie>> entry : entrySet) {
                List<Movie> list = entry.getValue();
                double total = 0;
                for(Movie movie : list) {
                    total += movie.getRate();
                }
                double avrg = total/list.size();
                map.put(entry.getKey(), avrg);
            }
            Set<Entry<String, Double>> entrySet1 = map.entrySet();
            ArrayList<Entry<String, Double>> list = new ArrayList<>(entrySet1);
            Collections.sort(list, new Comparator<Entry<String, Double>>() {
                @Override
                public int compare(Entry<String, Double> o1, Entry<String, Double> o2) {
                    return o1.getValue()>o2.getValue()?-1:1;
                }
            });
            for(int i = 0;i<3;i++) {
                System.out.println(list.get(i));
            }
        }
    }
    View Code

    二. RPC案例

      RPC(Remote Procedure Call)-远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果

    案例:

    客户端远程请求注册,登录服务端,服务端响应客户端登录和注册是否成功(获取信息分为从数据库中获取和从本地磁盘中获取)

    大致思路图:

     流程:客户端请求(即发送request请求对象)服务端(登录或者注册),请求中包含的信息为请求所要调用的方法,方法参数列表(形参),方法的全类名以及实参。客户端为了接受这个请求(request对象),其要在服务端创建一个一样的request去接收客户端请求中的参数(注意;全类名也要一样)。接着使用反射的方法调用该请求中的方法(此处不用new的形式来创建对象并调用方法,若业务区有多个方法,就需要new很多对象,消耗性能)。方法中包含了与数据库或是磁盘文件的交互,一般与数据库的交互是通过dao,所以业务区通过dao层与数据库或是磁盘文件交互。最终响应由dao层返回业务区,再返回给server端,最终客户端读取服务端的响应,即可拿到响应数据(登录或是注册是否成功)。

    代码:

    客户端:

    项目构造:

    MyClient代码:

    public class MyServer {
        @SuppressWarnings("resource")
        public static void main(String[] args) throws Exception {
            System.out.println("开始服务");
            ServerSocket serverSocket = new ServerSocket(7788);
            while(true) {
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(inputStream);
                System.out.println("开始读取数据");
                // 获取调用方法必须的参数
                Request request = (Request)ois.readObject();
                System.out.println("数据读取完毕");
                String className = request.getClassName();
                String methodName = request.getMethodName();
                Class<?>[] parameterTypes = request.getParameterTypes();
                Object[] paraterValues = request.getParaterValues();
                // 反射调用方法,并接收返回数据
                Class<?> clazz = Class.forName(className);
                Method method = clazz.getMethod(methodName, parameterTypes);
                Response response = (Response)method.invoke(clazz.newInstance(), (User)paraterValues[0]);
                System.out.println("接收数据完毕");
                
                // 向客户端发送响应
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(response);
                System.out.println(response);
                oos.close();
                ois.close();
                socket.close();
            }
        }
    }
    View Code

    POJO(简单java对象,一般是由私有属性以及相应的设置或者获取这些属性的方法构成)部分代码:

    request

    public class Request implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private String className;
        private String methodName;
        private Class<?>[] parameterTypes;
        private Object[] paraterValues;
        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[] getParaterValues() {
            return paraterValues;
        }
        public void setParaterValues(Object[] paraterValues) {
            this.paraterValues = paraterValues;
        }
        @Override
        public String toString() {
            return "Request [className=" + className + ", methodName=" + methodName + ", parameterTypes="
                    + Arrays.toString(parameterTypes) + ", paraterValues=" + Arrays.toString(paraterValues) + "]";
        }
    }
    View Code

    response:

    public class Response implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private String msg;
        private String statusCode;
        private User user;
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
        public String getStatusCode() {
            return statusCode;
        }
        public void setStatusCode(String statusCode) {
            this.statusCode = statusCode;
        }
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
        @Override
        public String toString() {
            return "Response [msg=" + msg + ", statusCode=" + statusCode + ", user=" + user + "]";
        }
    }
    View Code

    User:

    public class User implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        String name;
        int age;
        String password;
        
        public User() {
            
        }
        
        public User(String name, int age, String password) {
            super();
            this.name = name;
            this.age = age;
            this.password = password;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User [name=" + name + ", age=" + age + ", password=" + password + "]";
        }
    View Code

    服务端(server):

    Myserver

    public class MyServer {
        @SuppressWarnings("resource")
        public static void main(String[] args) throws Exception {
            System.out.println("开始服务");
            ServerSocket serverSocket = new ServerSocket(7788);
            while(true) {
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(inputStream);
                System.out.println("开始读取数据");
                // 获取调用方法必须的参数
                Request request = (Request)ois.readObject();
                System.out.println("数据读取完毕");
                String className = request.getClassName();
                String methodName = request.getMethodName();
                Class<?>[] parameterTypes = request.getParameterTypes();
                Object[] paraterValues = request.getParaterValues();
                // 反射调用方法,并接收返回数据
                Class<?> clazz = Class.forName(className);
                Method method = clazz.getMethod(methodName, parameterTypes);
                Response response = (Response)method.invoke(clazz.newInstance(), (User)paraterValues[0]);
                System.out.println("接收数据完毕");
                
                // 向客户端发送响应
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(response);
                System.out.println(response);
                oos.close();
                ois.close();
                socket.close();
            }
        }
    }
    View Code

    业务区(service)

    UserServer(接口)

    public interface UserServer {
        
        /**
         *  用于用户登录
         * @param user
         * @return
         * @throws Exception
         */
         
        public Response login(User user) throws Exception;
            
        /**
          *  用于用户的注册
         * @param user
         * @return
         * @throws Exception
         */
        public Response register(User user) throws Exception;
    }
    View Code

    UserServerImpl(实现注册和登录)

    public class UserServerImpl implements UserServer{
        // 使用静态代码块加载配置文件
        static String className;
        static UserDao userDao;
        static {
            try {
                Properties p = new Properties();
                p.load(UserServerImpl.class.getClassLoader().getResourceAsStream("class.properties"));
                className = p.getProperty("className");
                userDao = (UserDao)Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 为了提高代码的扩展性,使用配置文件并使用反射获取实例对象
        // 实现登录
        @Override
        public Response login(User user) throws Exception {
            System.out.println(user);
            User user1 = userDao.getUserFromDbByNameAndPwd(user);
            Response response = new Response();
            System.out.println(user1);
            // 登录失败
            if(user1==null) {
                response.setMsg("登录失败");
                response.setStatusCode("500");
                response.setUser(null);
            }else {
                response.setMsg("登录成功");
                response.setStatusCode("200");
                response.setUser(user1);
            }
            return response;
        }
    
        // 实现注册
        @Override
        public Response register(User user) throws Exception {
            Response response = new Response();
            boolean b = userDao.insertMessageOfUser(user);
            if(b){
                response.setMsg("注册成功");
                response.setStatusCode("200");
            }else{
                response.setMsg("注册失败");
                response.setStatusCode("500");
            }
            return response;
        }
        
    }
    View Code

    dao

     UserDao(接口)

    public interface UserDao {
        
        /**
          * 根据用户名和密码从数据库中查询用户
         * @param name
         * @param password
         * @return
         */
        public User getUserFromDbByNameAndPwd(User user) throws Exception;
        
        /**
         *  往数据库插入数据
         * @param user
         * @return
         */
        public boolean insertMessageOfUser(User user) throws Exception;
    }
    View Code

    UserDaoImpl1(与磁盘文件交互)

    /**
     * 操作文件
     * @author ASUS
     *
     */
    public class UserDaoImpl1 implements UserDao{
        @Override
        public User getUserFromDbByNameAndPwd(User u) throws Exception {
            Map<String, User> map = TestMyUtil.getUserFromFile();
            User user = null;
            if(map != null) {
                user = map.get(u.getName());
                if(user !=null) {
                    String pwd = user.getPassword();
                    if(u.getPassword().equals(pwd)) {
                        return user;
                    }
                }
            }
            return user;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public boolean insertMessageOfUser(User user) throws Exception {
            Map<String, User> map =null ;
            File f = new File(Const.PATH);
            boolean result = false; 
            if(!f.exists()) { //文件不存在,直接存map
                map = new HashMap<>();
                map.put(user.getName(), user);
                FileUtil.addObjectToFile(map, Const.PATH);
                result = true;
    
                // 文件已经存在,则先取出文件中的map对象,再存入相应的数据
            }else { 
                // 取出map
                map = (Map<String, User>) FileUtil.getObjectFromFile(Const.PATH);
                boolean b = map.containsKey(user.getName());
                if(!b) {
                    // 将数据存入已存在的map中,并将之写入文件
                    map.put(user.getName(), user);
                    FileUtil.addObjectToFile(map, Const.PATH);
                    result = true;
                }
            }
            return result;
        }
    }
    View Code

    UserDaoImpl2

    /**
      *  操作数据库
     * @author ASUS
     *
     */
    public class UserDaoImpl2 implements UserDao{
        static ComboPooledDataSource dataSource;
        static QueryRunner runner;
        static {
            // 获取连接池对象,其中包含连接数据库所需要的参数
            dataSource = new ComboPooledDataSource();
            // 连接数据库
            runner = new QueryRunner(dataSource);
        }
        // 查询数据
        @Override
        public User getUserFromDbByNameAndPwd(User u) throws Exception {
            
            String sql = "select * from user where name=?and password=?";
            User user = runner.query(sql, new BeanHandler<>(User.class),u.getName(),u.getPassword());
            return user;
        }
        
        // 插入数据
        @Override
        public boolean insertMessageOfUser(User u) throws Exception {
            String sql = "insert into user values(?,?,?)";
            int i = runner.update(sql,u.getName(),u.getAge(),u.getPassword());
            if(i>0) {
                return true;
            }
            return false;
        }
        
    }
    View Code

    工具类(utils)

    Const(保证操作的路径一致)

    /**
     * 指定路径
     * @author ASUS
     *
     */
    public class Const {
        public static final String PATH = "E:/javafile/object.txt";
        
    }
    View Code

    FileUtil

    /**
     * 1 读取指定文件   获取对象
     * 2 向指定文件中存储对象
     * @author ASUS
     *
     */
    public class FileUtil {
        
        /**
         * 读取指定文件   获取对象
         * @param path
         * @return
         * @throws Exception
         */
        public static Object getObjectFromFile(String path) throws Exception {
            File f = new File(path);
            Object obj = null ;
            if(f.exists()){
                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
                 obj = ois.readObject();
                 ois.close();
            }
            return obj;
        }
        
        /**
         * 向指定文件中存储对象
         * @param obj
         * @param path
         * @throws Exception
         */
        public static void addObjectToFile(Object obj , String path) throws Exception{
            File f = new File(path);
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
            oos.writeObject(obj);
            oos.close();
        }
    }
    View Code
  • 相关阅读:
    Linux软件安装之JDK的安装
    VMWARE虚拟机安装系统提示CPU已被客户机操作系统禁用和secureCUT乱码
    联网配置及静态更改
    全文搜索技术--Solr7.1之配置中文分析器
    全文搜索技术--solr7.1之mysql的安装步骤
    建立主从的九大步及配置哨兵
    mysql 模糊匹配优化(全文索引)
    微服务架构的身份验证解决方案
    spring声明式事务回滚
    spring 通过@responsebody接收多个对象参数
  • 原文地址:https://www.cnblogs.com/jj1106/p/11519123.html
Copyright © 2020-2023  润新知