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="\r\n";
    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="\r\n";
    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="\r\n";
    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);
    }

}
复制代码

 


本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/4833664.html,如需转载请自行联系原作者

相关文章
|
1月前
|
存储 数据安全/隐私保护 索引
Windows Server 各版本搭建文件服务器实现共享文件(03~19)
Windows Server 各版本搭建文件服务器实现共享文件(03~19)
161 1
|
8天前
|
Oracle Java 关系型数据库
Java 开发者必备:JDK 版本详解与选择策略(含安装与验证)
Oracle Java SE 支持路线图显示,JDK 8(LTS)支持至2030年,非LTS版本如9-11每6个月发布且支持有限。JDK 11(LTS)支持至2032年,而JDK 17及以上版本现在提供免费商用许可。LTS版本提供长达8年的支持,每2年发布一次。Oracle JDK与OpenJDK有多个社区和公司构建版本,如Adoptium、Amazon Corretto和Azul Zulu,它们在许可证、商业支持和更新方面有所不同。个人选择JDK时,可考虑稳定性、LTS、第三方兼容性和提供商支持。
23 0
|
15天前
|
Linux
centos 查看服务器信息 版本cpu
centos 查看服务器信息 版本cpu
12 0
|
17天前
|
弹性计算 前端开发 Java
使用阿里云 mqtt serverless 版本超低成本快速实现 webscoket 长链接服务器
使用阿里云 MQTT Serverless 可轻松实现弹性伸缩的 WebSocket 服务,每日成本低至几元。适用于小程序消息推送的 MQTT P2P 模式。前端需注意安全,避免 AK 泄露,采用一机一密方案。后端通过调用 `RegisterDeviceCredential` API 发送消息。示例代码包括 JavaScript 前端连接和 Java 后端发送。
165 0
|
1月前
|
Java 关系型数据库 MySQL
Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
【2月更文挑战第33天】Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
50 2
|
1月前
|
Java API 计算机视觉
java实现人脸识别V3版本开发
java实现人脸识别V3版本开发
17 0
|
1月前
|
数据安全/隐私保护 Windows
Windows Server 各版本搭建终端服务器实现远程访问(03~19)
左下角开始➡管理工具➡管理您的服务器,点击添加或删除角色点击下一步勾选自定义,点击下一步蒂埃涅吉终端服务器,点击下一步点击确定重新登录后点击确定点击开始➡管理工具➡计算机管理,展开本地用户和组,点击组可以发现有个组关门用来远程登录右键这个组点击属性,点击添加输入要添加的用户名,点击确定添加成功后点击确定打开另一台虚拟机(前提是在同一个局域网内),按 WIN + R 输入 mstsc 后回车输入 IP 地址后点击连接输入用户名及密码后点击确定连接成功!
34 0
|
1月前
|
Windows
Windows Server 各版本搭建 Web 服务器实现访问本地 Web 网站(03~19)
Windows Server 各版本搭建 Web 服务器实现访问本地 Web 网站(03~19)
57 2
|
1月前
|
Java
916.【Java】javap 查看 class 文件的jdk编译版本
916.【Java】javap 查看 class 文件的jdk编译版本
49 2
|
2月前
|
Java
java上传、下载、预览、删除ftp服务器上的文件
java上传、下载、预览、删除ftp服务器上的文件