zoukankan      html  css  js  c++  java
  • 2.一个简单的Servlet容器

    章前准备
        如何处理ifelse众多的问题,当然也可以说是switch case
        我们经常写这样的代码,如果这货小一点,且可预测什么的,那都不是事,问题是如果他要是可拓展的类- -!让他见鬼去吧
        我曾经被要求实现一个接口,这个接口会接受一个Scene参数用以区分不同实现方式(不用吐槽,国企喜欢超级接口),我相信你也会见过类似的代码,显然如果Scene是可确定的话,if...else并没有什么不可以的...遗憾的是设计人员会明确的告诉你,Scene是会不断增加的,而且if中的内容绝对不会像你想象的那么简单。。。
        唯一令人兴奋的是java作为面向对象语言,最喜欢解决这种问题

        呆毛:Paint类拥有print方法,他会根据传来的参数来画不同的人物
    简单实现一:尝试着完成呆毛并观察

    public class Paint {
        public static void main(String[] args)  {
            Paint paint = new Paint();
            paint.print("lf","", "");
            paint.print("nm","", "");
        }
        /**
         * @param Scene 场景参数
         * @param name  路人甲,实现场景什么的会使用到的参数
         * @param id    路人乙
         */
        void print(String scene,String name,String id){
            if("lf".equals(scene)){
                //好长好长的代码
                System.out.println("路飞");
            }else if("sl".equals(scene)){
                //好长好长的代码
                System.out.println("索隆");
            }else if("sz".equals(scene)){
                //好长好长的代码
                System.out.println("山治");
            }else{
                //好长好长的代码
                System.out.println("熊猫人");
            }
        }
    }

    这里只是用System.out.println("");来替代绘画的过程,如果真的很长的话,即使作为BI端的屌丝程序猿也知道,这时候应该封装具体的实现


    简单实现二:尝试着将ifelse中具体的实现进行封装(通过接口,不是通过方法。。。)

    /**
     * @author 程猿
     * 尝试着封装所谓的具体实现,print中的逻辑将会在Print的实现
     */
    public class Paint {
        public static void main(String[] args)  {
            Paint paint = new Paint();
            paint.print("lf","", "");
            paint.print("nm","", "");
        }
    
        void print(String scene,String name,String id){
            if("lf".equals(scene)){
                new PrintLF().print(scene, name, id);
            }else if("sl".equals(scene)){
                new PrintSL().print(scene, name, id);
            }else if("sz".equals(scene)){
                new PrintSZ().print(scene, name, id);
            }else{
                new PrintXMR().print(scene, name, id);
            }
        }
    }
    public interface Print {
        void print(String scene,String name,String id);
    }
    public class PrintLF  implements Print{
        @Override
        public void print(String scene, String name, String id) {
            System.out.println("路飞");
        }
    }

    其他实现就不贴了
    我们已用封装的方式,将处理的问题全都放在Print的实现类中,代码此处会少一节。。。当然这只是对封装的简单应用,可以看到print的方法中,是简单的判断关系与实现类的1对1的关系,如果我这里使用类似于Map这种结构的话,情况或许就不一样了....其实作为BI端的屌丝程序猿明白,我们的实现,基本上就是这样了(严格来说应该是放到方法里,而不是放到接口实现里)

    简单实现三:我们要使用Map结构,key为判断,val为实现类

    /**
     * @author 程猿
     * key对应判断依据,value对应实现类
     * 如果value为null,会使用默认类,这里的默认类的key为""...
     */
    public class Paint2 {
        public static void main(String[] args)  {
            Paint2 paint = new Paint2();
            paint.print("lf","", "");
            paint.print("nm","", "");
        }
    
        Map<String,Print>  paintMap=new HashMap(){
            {
                put("lf", new PrintLF());
                put("sl", new PrintSL());
                put("sz", new PrintSZ());
                put("", new PrintXMR());
            }
        };
        
        void print(String scene,String name,String id){
            Print object = paintMap.get(scene);
            if(object==null){
                object= paintMap.get("");
            }
            if(object==null){
                return;
            }
            object.print(scene, name, id);
        }
    }

    main是控制台,很显然,如果给map一个get/set方法的话,我们就可以在控制台来控制Paint类方法的走向,而不需要在进入Paint进行修改,当然,主流的控制台还是配置文件,我们都是懂ioc的男人,当然因为说使用了ioc所以就结束显然太没良心了,那就试试用加点伪ioc呗

    简单实现四:加入伪ioc实现

    /**
     * @author 程猿 并没有一个容器去实现Print类...所以才叫伪嘛
     */
    public class Paint {
        public static void main(String[] args) {
            Paint paint = new Paint();
            paint.print("lf", "", "");
            paint.print("nm", "", "");
        }
    
        Paint() {
            InputStream in = this.getClass().getResourceAsStream(
                    "/t3/print.properties");
            try {
                paintMap.load(in);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        Properties paintMap = new Properties();
    
        void print(String scene, String name, String id) {
            String string = paintMap.getProperty(scene);
            if (string == null) {
                string = paintMap.getProperty("");
            }
            if (string == null) {
                return;
            }
            Class clazz = null;
            try {
                clazz = Class.forName(string);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            Print newInstance = null;
            try {
                newInstance = (Print) clazz.newInstance();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            newInstance.print(scene, name, id);
        }
    }

    这是一种解决ifelse众多的解决方案,而且还是经理们经常念叨的可插拔可配置的,那他算不算一种神奇的设计模式呢?那我个人认为设计模式是解决继承,封装,多态使用时的一种不便利性而存在的,比如子类过多,或者方法暴露过多什么的,显然这里只是简单地封装和多态的使用(无视ioc...),当然或许这就是面向对象最有意思的地方,或者说面向接口

    不在联想了,我们是在学tomcat,聊一下web服务器与网民(客户端的操作人员)的交互过程,首先,网民输入url,浏览器通过url(和自身设置)生成请求报文发送给服务器,服务器分析请求报文,并返回相应报文,通过这个过程可以发现,url应该称的上最精简的请求报文(或者说最重要的地方),也是网民唯一能修改的地方,换句话说不同的url对应不同的响应报文,那么,来一个

    自制的可以相应多种URL的web服务器

    /**
     * @author 程猿 通过请求报文可以观察出第一行,以空格分割,第二个就是url的路径
     */
    public class Test {
        public static String getUrl(InputStream inputStream) throws IOException {
            int i;
            String str = "";
            while ((i = inputStream.read()) != '
    ') {
                str += (char) i;
            }
            String[] split = str.split(" ");
            if (split.length > 2) {
                return split[1];
            }
            return null;
        }
    
        public static void main(String[] args) throws Exception {
            ServerSocket server = new ServerSocket(8080);
            while (true) {
                Socket socket = server.accept();
                // 接受请求
                InputStream inputStream = socket.getInputStream();
                String url = getUrl(inputStream);
                System.out.println("url:" + url);
                if ("/a".equals(url)) {
                    // 发送回应
                    OutputStream outputStream = socket.getOutputStream();
                    String str = "HTTP/1.1 200 OK
    "
                            + "Server: Apache-Coyote/1.1
    "
                            + "Content-Type: text/html
    "
                            + "Transfer-Encoding: chunked
    "
                            + "Date: Mon, 27 Oct 2014 13:38:35 GMT
    "
                            + "
    "
                            + "bb
    "
                            + "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    "
                            + "<HTML>
    "
                            + "  <HEAD><TITLE>A Servlet</TITLE></HEAD>
    "
                            + "  <BODY>
    " + "    this is A~
    " + "  </BODY>
    "
                            + "</HTML>";
                    outputStream.write(str.getBytes());
                    socket.close();
                } else if ("/b".equals(url)) {
                    OutputStream outputStream = socket.getOutputStream();
                    String str = "HTTP/1.1 200 OK
    "
                            + "Server: Apache-Coyote/1.1
    "
                            + "Content-Type: text/html
    "
                            + "Transfer-Encoding: chunked
    "
                            + "Date: Mon, 27 Oct 2014 13:38:35 GMT
    "
                            + "
    "
                            + "bb
    "
                            + "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    "
                            + "<HTML>
    "
                            + "  <HEAD><TITLE>A Servlet</TITLE></HEAD>
    "
                            + "  <BODY>
    " + "    BBBBBBBBBBBBBBB~
    "
                            + "  </BODY>
    " + "</HTML>";
                    outputStream.write(str.getBytes());
                    socket.close();
                }
            }
    
        }
    }

    分别输入http://localhost:8080/a和http://localhost:8080/b很显然,在浏览器中的显示的情况是不一样的,我们可以通过完成多个ifelse达到不同的url对应不同的界面的目的,而且我们也能够解决ifelse众多的问题

    tomcat_2.ifelse.zip

    第二章 一个简单的Servlet容器

    1.java大叔提供了一种解决web服务器的调用与实现的方案,(其接口)称之为Servlet
    2.因为存在2组人工作(tomcat小组和servlet实现小组),2组人可能根本就不认识(认识就好了...),为了解决继承的向下转型的暴露问题是用外观模式

  • 相关阅读:
    IB(InterBase Server) 的完整连接格式
    jna
    编写基于Prototype的Javascript动画类
    Go——使用 go mod ——有依赖的Go工程
    pkgconfig—— PKG_CONFIG_PATH——Makefile——pkgconfig的作用与使用
    Go——Goland Debug报错Version of Delve is too old for this version of Go
    NATS——NATS Streaming 是什么 (转)
    Go——Go语言调用C语言
    go get安装包超时处理
    NATS—基础介绍 (转自 https://www.cnblogs.com/yorkyang/p/8392172.html)
  • 原文地址:https://www.cnblogs.com/liuCy/p/4018371.html
Copyright © 2011-2022 走看看