Java Socket simple implementation of http server imitating Servlet

The TCP protocol based on java Scoket simply implements the http server, using the browser as the client to achieve the effect of accessing Servlet in javaWeb.

(You must have a certain understanding of http protocol and Servlet)

Improved version

Execution effect :

  • http server side :
  • server
    Client (login.html) :
    Insert picture description here
    After login: Test account: zjl 123456
    Login result

Ideas

  • Browser side : It is an html form. After entering the name and password, click login. The access server address is localhost:8080/login, and then it will automatically connect to the server and send the request message of the http protocol.
  • Server : After receiving the message from the client, parse it, parse the resource (here /login), request method (get or post), and request parameters that the client wants to request in the request message, and then encapsulate it into the Request entity. Then it is necessary to obtain the corresponding Servlet according to the requested resource. The mapping relationship between the requested resource and the full path class name of the Servlet is placed in the web.xml file, so the full path class name of the servlet can be obtained by parsing the web.xml file by dom4j , And then use reflection to create an instance of this servlet. After having the Servlet instance, call the service method of the Servlet instance and pass in the encapsulated Request object and Response object as parameters, so that the service method of the Servlet is executed, and then the print method can be sent to the client by calling the response. Response message.

Graphical thinking

Insert picture description here

Code directory structure

Insert picture description here

web.xml configuration

<?xml version="1.0" encoding="UTF-8" ?>
<web-app>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>demo.ServletImpl.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

Core code

public class startServer {
    
    

    public static void main(String[] args) throws Exception {
    
    
        ServerSocket server   = new ServerSocket(8080);
        System.out.println("http服务器启动成功....");

        //多线程处理每个请求
        while(true){
    
    
            Socket client = server.accept();
            new ServerThread(client).start();
        }

    }
}


/**
 *    服务器处理浏览器请求线程
 */
class ServerThread extends Thread{
    
    

    private Request request;  //请求
    private Response reponse;   //响应
    private Socket client;   //客户端套接字

    //初始化request,reponse
    public ServerThread(Socket client) {
    
    
        try {
    
    
            this.client = client;
            request = new Request(client.getInputStream());
            reponse = new Response(client.getOutputStream());
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
    
    
        try {
    
    
             System.out.println(client.getRemoteSocketAddress()+" 发出请求");
             
             //浏览器会默认请求网站图标资源,我们这里忽略掉这个请求
             if (request.getUrl().equals("/favicon.ico"))
                 return;

            //1-根据请求的url获得Servlet
            Servlet servlet  = ServletFactory.getServlet(request.getUrl());

            //请求资源不存在404
            if (servlet == null){
    
    
                reponse.setCode(404);
                reponse.print("");
            }

            //2-执行Servlet
            if (servlet != null){
    
    
                servlet.service(request,reponse);
            }


        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                client.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}


Obtain Servlet code according to the requested resource

  • The path xmlpath of the web.xml file below needs to be set according to your computer environment, otherwise the file will not be found
/**
 *   Servlet工厂
 *
 *          根据url和xml文件创建Servlet
 *
 *
 */
public class ServletFactory {
    
    

    //Servlet上下文环境
    private static ServletContext context = new ServletContext();

    //web.xml文件路径
    private static String xmlpath = "http服务器/src/demo/web.xml";

    private ServletFactory(){
    
    }

    /**
     *      读取web.xml文件把servlet和url的关系进行配置存储
     */
    static {
    
    
        try {
    
    
            //1-获得doucument
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(new File(xmlpath));

            //2-获得根元素      <web-app>
            Element rootElement = document.getRootElement();

            //3-获得所有子元素
            List<Element> elements = rootElement.elements();

            //4-遍历处理所有子元素
            for (Element e : elements) {
    
    
                if ("servlet-mapping".equals(e.getName())) {
    
    
                    Element servlet_name = e.element("servlet-name");
                    Element url_pattern = e.element("url-pattern");
                    context.getUrl_map().put(url_pattern.getText(),servlet_name.getText());
                }
                else if ("servlet".equals(e.getName())) {
    
    
                    Element servlet_name = e.element("servlet-name");
                    Element servlet_class = e.element("servlet-class");
                    context.getServlet_map().put(servlet_name.getText(),servlet_class.getText());
                }
            }
        } catch (DocumentException e) {
    
    
            e.printStackTrace();
        }
    }


    /**
     *  获得Servlet
     */
    public static synchronized Servlet getServlet(String url) throws Exception {
    
    
        String servletClass = context.getServlet_map().get(context.getUrl_map().get(url));

   
            return servletClass != null ? (Servlet)Class.forName(servletClass).newInstance() : null;
       
    }
}

ServletContext context

/**
 *   Servlet的上下文环境
 */
public class ServletContext {
    
    

    //Servlet别名和Servlet全路径类名的映射关系
    private  Map<String,String>  servlet_map;

    //url和 Servlet别名的映射关系
    private  Map<String,String> url_map;

    public ServletContext() {
    
    
        servlet_map = new HashMap<>();
        url_map = new HashMap<>();
    }

    public Map<String, String> getServlet_map() {
    
    
        return servlet_map;
    }


    public Map<String, String> getUrl_map() {
    
    
        return url_map;
    }
}

Servlet abstract class code

/**
 *   Servlet抽象类
 */
public abstract class Servlet {
    
    

    public void service(Request request,Response reponse) throws Exception {
    
    
        this.doGet(request,reponse);
        this.doPost(request,reponse);
    }


    public abstract void doGet(Request request,Response reponse) throws Exception;
    public abstract void doPost(Request request,Response reponse) throws Exception;

}

Execute LoginServlet code

import demo.domain.Request;
import demo.domain.Response;
import demo.domain.Servlet;
public class LoginServlet extends Servlet {
    
    
    @Override
    public void doGet(Request request, Response reponse) throws Exception {
    
    

        String name = request.getParameter("name");
        String password = request.getParameter("password");

        if (name!= null && password !=null && name.equals("zjl") && password.equals("123456"))
            reponse.print("登陆成功!");
        else
            reponse.print("登陆失败!");
    }

    @Override
    public void doPost(Request request, Response reponse) throws Exception {
    
    
        doGet(request,reponse);
    }
}

After completing the above, now you can implement your own custom Servlet to handle each request, as long as you inherit the Servlet abstract class, and then configure the attributes of Setvlet in web.xml.

Full code address

Link: https://pan.baidu.com/s/1NN7oNdD5m1U_36YI_wNvrA Password: w80h

Reward

If you find the article useful, you can encourage the author

Insert picture description here


Guess you like

Origin blog.csdn.net/weixin_41347419/article/details/89047053