zoukankan      html  css  js  c++  java
  • java24 手写服务器最终版本

    手写服务器最终版本;
    <?xml version="1.0" encoding="UTF-8"?>
    
     <web-app>
         <servlet>
             <servlet-name>login</servlet-name>
             <servlet-class>com.bjsxt.servlet.LoginWeb</servlet-class>
         </servlet>
          <servlet-mapping>
              <servlet-name>login</servlet-name>
              <url-pattern>/g</url-pattern>
              <url-pattern>/y</url-pattern>
          </servlet-mapping>
     </web-app>
     
     
     
    public class CloseUtil {
        /**
         * 关闭IO流
         */
        /*
        public static void closeIO(Closeable... io){
            for(Closeable temp:io){
                try {
                    if (null != temp) {
                        temp.close();
                    }
                } catch (Exception e) {
                }
            }
        }*/
        /**
         * 使用泛型方法实现关闭IO流
         * @param io
         */
        public static <T extends Closeable> void closeIO(T... io){
            for(Closeable temp:io){
                try {
                    if (null != temp) {
                        temp.close();
                    }
                } catch (Exception e) {
                }
            }
        }
        public static  void closeSocket(ServerSocket socket){
            try {
                if (null != socket) {
                    socket.close();
                }
            } catch (Exception e) {
            }
        }
        public static  void closeSocket(Socket socket){
            try {
                if (null != socket) {
                    socket.close();
                }
            } catch (Exception e) {
            }
    }
        public static  void closeSocket(DatagramSocket socket){
                try {
                    if (null != socket) {
                        socket.close();
                    }
                } catch (Exception e) {
                }
        }
    }
    
    
    
    
    /**
     * 抽象为一个父类
     * @author Administrator
     *
     */
    public abstract class Servlet {
        public void service(Request req,Response rep) throws Exception{
            this.doGet(req,rep);
            this.doPost(req,rep);
        }
        
        protected abstract void doGet(Request req,Response rep) throws Exception;
        protected abstract void doPost(Request req,Response rep) throws Exception;
    }
    
    
    
    public class LoginWeb extends Servlet {
    
        @Override
        public void doGet(Request req, Response rep) throws Exception {
            rep.println("success.....");
        }
    
        @Override
        public void doPost(Request req, Response rep) throws Exception {
            // TODO Auto-generated method stub
            
        }
    
    }
    
    
    
    
    /**
     * 创建服务器,并启动
     * 
     * 1、请求
     * 2、响应
     * @author Administrator
     *
     */
    public class Server {
        private ServerSocket server;
        public static final String CRLF="
    ";
        public static final String BLANK=" ";
        
        private boolean isShutDown= false;
        /**
         * @param args
         */
        public static void main(String[] args) {
        
            Server server = new Server();
            server.start();
            
            
        }
        /**
         * 启动方法
         */
        public void start(){        
            start(8888);
        
        }
        /**
         * 指定端口的启动方法
         */
        public void start(int port){        
            try {
                server = new ServerSocket(port);
                this.receive();
            } catch (IOException e) {
                //e.printStackTrace();
                stop();
            }
        
        }
        /**
         * 接收客户端
         */
        private void receive(){
            try {
                while(!isShutDown){
                    new Thread(new Dispatcher(server.accept())).start();
                }
            } catch (IOException e) {
                //e.printStackTrace();
                stop();
            }
            
        }
        
        /**
         * 停止服务器
         */
        public void stop(){
            isShutDown=true;
            CloseUtil.closeSocket(server);
        }
        
        
    }
    
    
    
    public class ServletContext {
        //为每一个servlet取个别名  
        // login  -->com.bjsxt.server.demo03.LoginServlet
        private Map<String,String> servlet ;
        //url -->login
        //   /log -->login
        //   /login -->login
        private Map<String,String> mapping;
        
        ServletContext(){
            servlet =new HashMap<String,String>();
            mapping =new HashMap<String,String>();
        }
        
        
        public Map<String, String> getServlet() {
            return servlet;
        }
        public void setServlet(Map<String, String> servlet) {
            this.servlet = servlet;
        }
        public Map<String, String> getMapping() {
            return mapping;
        }
        public void setMapping(Map<String, String> mapping) {
            this.mapping = mapping;
        }
    }
    
    
    public class WebApp {
        private static ServletContext contxt;
        static{
            try {
                //获取解析工厂
                SAXParserFactory factory = SAXParserFactory.newInstance();
                //获取解析器
                SAXParser sax = factory.newSAXParser();
                //指定xml+处理器
                WebHandler web = new WebHandler();
                sax.parse(Thread.currentThread().getContextClassLoader()
                        .getResourceAsStream("WEB_INFO/web.xml"), web);
                
                
                //将list 转成Map
                contxt =new ServletContext();            
                Map<String,String> servlet =contxt.getServlet();
                
                //servlet-name  servlet-class 
                for(Entity entity:web.getEntityList()){
                    servlet.put(entity.getName(), entity.getClz());
                    
                }
                
                //url-pattern servlet-name            
                Map<String,String> mapping =contxt.getMapping();
                for(Mapping mapp:web.getMappingList()){
                    List<String> urls =mapp.getUrlPattern();
                    for(String url:urls ){
                        mapping.put(url, mapp.getName());
                    }
                }
                
            } catch (Exception e) {
                
            }
            
            
        }
        
        public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
            if((null==url)||(url=url.trim()).equals("")){
                return null;
            }
            //根据字符串(完整路径)创建对象
            
            //return contxt.getServlet().get(contxt.getMapping().get(url));
            String name=contxt.getServlet().get(contxt.getMapping().get(url));
            return (Servlet)Class.forName(name).newInstance();//确保空构造存在
        }
    }
    
    
    
    
    
    
    public class WebHandler extends DefaultHandler{
        private List<Entity> entityList;
        private List<Mapping> mappingList;
        private Entity entity;
        private Mapping mapping;
        private String beginTag ;    
        private boolean isMap; 
        
        
         @Override
        public void startDocument() throws SAXException {
            //文档解析开始
             entityList =new ArrayList<Entity>() ;
             mappingList =new ArrayList<Mapping>() ;
             
        }
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            //开始元素
            if(null!=qName){
                beginTag=qName;
                
                if(qName.equals("servlet")){
                    isMap=false;
                    entity=new Entity();
                }else if(qName.equals("servlet-mapping")){
                    isMap=true;
                    mapping=new Mapping();
                }        
                
            }
            
        }
        
        
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            //处理内容
            if(null!=beginTag){
                String str =new String(ch,start,length);
                if(isMap ){
                    
                    if(beginTag.equals("servlet-name")){
                        mapping.setName(str);
                    }else if(beginTag.equals("url-pattern")){
                        mapping.getUrlPattern().add(str);
                    }
                }else{
                    if(beginTag.equals("servlet-name")){
                        entity.setName(str);                    
                    }else if(beginTag.equals("servlet-class")){
                        entity.setClz(str);
                    }
                }
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            //结束元素
            if(null!=qName){
                
                if(qName.equals("servlet")){
                    entityList.add(entity);
                }else if(qName.equals("servlet-mapping")){
                    mappingList.add(mapping);
                }
                
            }
            beginTag=null;
        }
    
        
        @Override
        public void endDocument() throws SAXException {
            //文档解析结束
        }
    
        
        /*public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
            //获取解析工厂
            SAXParserFactory factory =SAXParserFactory.newInstance();
            //获取解析器
            SAXParser sax =factory.newSAXParser();
            //指定xml+处理器
            WebHandler web = new WebHandler();
            sax.parse(Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("com/bjsxt/server/demo4/web.xml")
                    ,web);
            
            System.out.println(web.getEntityList());
        }*/
        public List<Entity> getEntityList() {
            return entityList;
        }
        public void setEntityList(List<Entity> entityList) {
            this.entityList = entityList;
        }
        public List<Mapping> getMappingList() {
            return mappingList;
        }
        public void setMappingList(List<Mapping> mappingList) {
            this.mappingList = mappingList;
        }
        
        
        
    
    }
    
    
    
    
    
    /**
     * 封装响应信息
     * @author Administrator
     *
     */
    public class Response {
        //两个常量
        public static final String CRLF="
    ";
        public static final String BLANK=" ";
        //
        private BufferedWriter bw ;
        
        //正文
        private StringBuilder content;
        
        
        //存储头信息
        private StringBuilder headInfo;
        //存储正文长度
        private int len =0;
        public Response(){
            headInfo =new StringBuilder();
            content =new StringBuilder();
            len =0;
        }
        public Response(Socket client){
            this();
            try {
                bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
            } catch (IOException e) {
                headInfo=null;
            }
        }
        public Response(OutputStream os){
            this();
            bw= new BufferedWriter(new OutputStreamWriter(os));
        }
        /**
         * 构建正文
         */
        public Response print(String info){
            content.append(info);
            len+=info.getBytes().length;
            return this;
        }
        
        /**
         * 构建正文+回车
         */
        public Response println(String info){
            content.append(info).append(CRLF);
            len+=(info+CRLF).getBytes().length;
            return this;
        }
        
        /**
         * 构建响应头
         */
        private void createHeadInfo(int code){
            //1)  HTTP协议版本、状态代码、描述
            headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
            switch(code){
                case 200:
                    headInfo.append("OK");
                    break;
                case 404:
                    headInfo.append("NOT FOUND");
                    break;
                case 505:
                    headInfo.append("SEVER ERROR");
                    break;    
            }
            headInfo.append(CRLF);
            //2)  响应头(Response Head)
            headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
            headInfo.append("Date:").append(new Date()).append(CRLF);
            headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
            //正文长度 :字节长度
            headInfo.append("Content-Length:").append(len).append(CRLF);
            headInfo.append(CRLF); //分隔符
        } 
        //推送到客户端
        void pushToClient(int code) throws IOException{
            if(null==headInfo){
                code =500;
            }
            createHeadInfo(code);
            //头信息+分割符
            bw.append(headInfo.toString());
            //正文
            bw.append(content.toString());
            bw.flush();
        }
        public void close(){
            CloseUtil.closeIO(bw);
        }
        
        
    }
    
    
    
    
    
    
    /**
     * 封装request
     * @author Administrator
     *
     */
    public class Request {
        //请求方式
        private String method;
        //请求资源
        private String url;
        //请求参数
        private Map<String,List<String>> parameterMapValues;
        
        //内部
        public static final String CRLF="
    ";
        private InputStream is;
        private String requestInfo;
        
        public Request(){
            method ="";
            url ="";
            parameterMapValues=new HashMap<String,List<String>>();
            requestInfo="";
        }
        public Request(InputStream is){
            this();
            this.is=is;
            try {
                byte[] data = new byte[20480];
                int len = is.read(data);
                requestInfo = new String(data, 0, len);
            } catch (Exception e) {
                return ;
            }
            //分析请求信息
            parseRequestInfo();
        }
        /**
         * 分析请求信息
         */
        private void parseRequestInfo(){
            if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){
                return ;
            }        
            /**
             * =====================================
             * 从信息的首行分解出 :请求方式    请求路径   请求参数(get可能存在)
             *   如:GET /index.html?name=123&pwd=5456 HTTP/1.1
             * 
             * 如果为post方式,请求参数可能在 最后正文中
             * 
             * 思路:
             * 1)请求方式 :找出第一个/  截取即可
             * 2)请求资源:找出第一个/   HTTP/ 
             * =====================================
             */
            String paramString =""; //接收请求参数 
            
            //1、获取请求方式
            String firstLine =requestInfo.substring(0,requestInfo.indexOf(CRLF));
            int idx =requestInfo.indexOf("/"); // /的位置
            this.method=firstLine.substring(0, idx).trim();
            String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
            if(this.method.equalsIgnoreCase("post")){
                this.url=urlStr;        
                paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
                
            }else if(this.method.equalsIgnoreCase("get")){
                if(urlStr.contains("?")){ //是否存在参数
                    String[] urlArray=urlStr.split("\?");
                    this.url=urlArray[0];
                    paramString=urlArray[1];//接收请求参数 
                }else{
                    this.url=urlStr;            
                }
            }
            
        
            //不存在请求参数
            if(paramString.equals("")){
                return ;
            }
            //2、将请求参数封装到Map中    
            parseParams(paramString);
        }
        private void parseParams(String paramString){
            //分割 将字符串转成数组
            StringTokenizer token=new StringTokenizer(paramString,"&");
            while(token.hasMoreTokens()){
                String keyValue =token.nextToken();
                String[] keyValues=keyValue.split("=");
                if(keyValues.length==1){
                    keyValues =Arrays.copyOf(keyValues, 2);
                    keyValues[1] =null;
                }
                
                String key = keyValues[0].trim();
                String value = null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk");
                //转换成Map 分拣
                if(!parameterMapValues.containsKey(key)){
                    parameterMapValues.put(key,new ArrayList<String>());
                }
                
                List<String> values =parameterMapValues.get(key);
                values.add(value);            
            }        
            
        }
        /**
         * 解决中文
         * @param value
         * @param code
         * @return
         */
        private String decode(String value,String code){
            try {
                return java.net.URLDecoder.decode(value, code);
            } catch (UnsupportedEncodingException e) {
                //e.printStackTrace();
            }
            return null;
        }
        /**
         * 根据页面的name 获取对应的多个值
         * @param args
         */
        public String[] getParameterValues(String name){
            List<String> values=null;
            if((values=parameterMapValues.get(name))==null){
                return null;
            }else{
                return values.toArray(new String[0]);
            }
        }
        /**
         * 根据页面的name 获取对应的单个值
         * @param args
         */
        public String getParameter(String name){
            String[] values =getParameterValues(name);
            if(null==values){
                return null;
            }
            return values[0];
        }
        public String getUrl() {
            return url;
        }
        
        public void close(){
            CloseUtil.closeIO(is);
        }
    }
    
    
    
    /*
     <servlet-mapping>
             <servlet-name>login</servlet-name>
             <url-pattern>/login</url-pattern> 
         </servlet-mapping>
          <servlet-mapping>
             <servlet-name>login</servlet-name>
             <url-pattern>/log</url-pattern> 
         </servlet-mapping>
     
      
     */
    public class Mapping {
        private String name;
        private List<String> urlPattern;
        
        public Mapping(){
            urlPattern =new ArrayList<String>();
        }
        
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public List<String> getUrlPattern() {
            return urlPattern;
        }
        public void setUrlPattern(List<String> urlPattern) {
            this.urlPattern = urlPattern;
        }
        
        
        
    }
    
    
    
    /*  
     <servlet>
             <servlet-name>login</servlet-name>
             <servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
         </servlet> 
     */
    public class Entity {
        private String name;
        private String clz;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getClz() {
            return clz;
        }
        public void setClz(String clz) {
            this.clz = clz;
        }
        
    }
    
    
    
    /**
     * 一个请求与响应 就一个此对象
     * @author Administrator
     *
     */
    public class Dispatcher implements Runnable{
        private Socket client;
        private Request req;
        private Response rep;
        private int code=200;
        Dispatcher(Socket client){
            this.client=client;
            try {
                req =new Request(client.getInputStream());
                rep =new Response(client.getOutputStream());
            } catch (IOException e) {
                //e.printStackTrace();
                code =500;
                return ;
            }
        }
        
        
        
        
        
        @Override
        public void run() {
            try {
                Servlet serv =WebApp.getServlet(req.getUrl());
                if(null==serv){
                    this.code=404; //找不到处理
                }else{
                    serv.service(req, rep);
                }
                rep.pushToClient(code); //推送到客户端
            }catch (Exception e) {
                e.printStackTrace();
                this.code=500;
            }    
            try {
                rep.pushToClient(500);
            } catch (IOException e) {
                e.printStackTrace();
            }
            req.close();
            rep.close();        
            CloseUtil.closeSocket(client);
        }
    
    }
  • 相关阅读:
    【转】:java遍历List时动态添加和删除元素
    【转】:浅析 Comparable和 Comparator的区别
    【转】:Synchronized同步静态方法和非静态方法总结
    【转】:学习路线(自用)
    js原型链的理解
    关于浏览器切换标签或者移动端切换应用时,js不执行的解决方案
    .net core连接mongoDB
    首先从项目结构开始讲起
    iOS应用内支付(IAP)服务端端校验详解
    .net支付宝SDK接入这些坑你必须知道
  • 原文地址:https://www.cnblogs.com/yaowen/p/4833664.html
Copyright © 2011-2022 走看看