简单服务器开发(八)响应动态:客户端访问小Java程序

之前的开发步骤:简单服务器开发

  上一个例子中,浏览器客户端发送的请求是 http://127.0.0.1:8080/oa/index.html,从请求路径上看到浏览器客户端访问的是 WebApp 中的静态 html 页面,服务器找到该静态页面之后直接将html页面响应到浏览器即可

  但是如果浏览器发送这样的请求:http://127.0.0.1:8080/oa/login?username=admin&password=123,从请求路径的字面意思上理解,这是浏览器向服务器发送了一个登录的请求,需要服务器端执行一段“Java 程序”来处理这次的登录请求,负责处理登录的 Java 程序应当获取到浏览器提交的用户名和密码,并且负责连接数据库,验证用户名和密码是否正确,如果正确则响应给浏览器一条登录成功的信息,如果错误则响应给浏览器一条登录失败的信息。

  需要注意的是,浏览器向服务器发送请求并且提交数据的格式是什么?这个提交数据的格式其实属于HTTP协议的一部分,这是W3C提前制定好的,格式是:

  http://ip:port/uri?name=value&name=value.....并且这个数据在HTTP 协议的请求行上提交,最终会显示在浏览器的地址栏上。

  接下来让我们一起实现上面的功能,该功能的实现需要 Web 服务器开发人员、WebApp 开发人员共同配合完成。我们现在的角色转变为 WebApp 的开发人员,开始编写 Java 程序处理用户的登
录请求。服务器端的小java程序英文是:Server Applet,所以我们把服务器端的小java程序叫做:Servlet。

(1)角色:webapp 开发人员:

A、新建软件包 org.zda.oa.servlet
B、该软件包中新建 LoginServlet.java ,编写 LoginServlet 处理用户的登录请求

package org.zda.oa.servlet;
/**
 * 处理登录业务的java程序,该java程序由webApp开发人,由web服务器开人员负责调用
 * @author webApp开发人员
 * @version    1.0
 * @since    1.0
 *
 */
public class LoginServlet {
    //处理业务的核心类
    public void service(){
        System.out.println("正在验证身份,请稍等....");
    }
}

(2) 角色:web 服务器开发人员

  开发服务器端程序调用 LoginServlet 的service 方法,当然是通过用户的请求路径了。其实LoginServlet 也是服务器端的一种资源,只不过这种资源不是 html,而是一段 Java 程序,所以服务器也可以先截获用户的请求路径,然后通过请求 URI 决定调用哪个 Servlet。因此可以说,“请求 URI”和对应要执行的“Servlet 程序”之间有一种绑定关系。那么接下来就让我们编写 Web 服务器端的程序,截获请求 URI,根据请求 URI 来对应调用 Servlet。(HandlerRequest)

A、在HandlerRequest 截获请求 URI,根据请求 URI 来对应调用 Servlet 
B、紧接上一版本,判断完是否为静态资源,如不是静态页面那肯定是动态资源

package com.zda.httpserver.core;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import org.zda.oa.servlet.LoginServlet;

import com.zda.httpserver.util.Logger;

/**
 * 处理客户端请求
 * @author zda
 * @version 1.0
 * @since    1.0
 */
public class HandlerRequest implements Runnable {
    public Socket clientSocket;
    public HandlerRequest(Socket clientSocket){
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        //处理客户端请求
        BufferedReader br = null;
        PrintWriter out = null;
        Logger.log("httpserver thread: " + Thread.currentThread().getName());
        try {
            //接收客户端消息
            br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            //获取响应流对象
            out = new PrintWriter(clientSocket.getOutputStream());
            //获取请求协议的请求行
            String requestLine = br.readLine();// GET /oa/index.html HTTP/1.1
            //获取URI -> 请求行(requestLine) -> 请求方式  URI 请求协议版本号 -> 三者之间是通过一个空格进行连接
            String requestURI = requestLine.split(" ")[1];//{"GET","/oa/index.html","HTTP/1.1"}
            System.out.println(requestURI);
            //判断用户请求是否为一个静态页面:以.html或.htm结尾的文件叫作html页面
            if(requestURI.endsWith(".html") || requestURI.endsWith(".htm")){
                //处理静态页面的方法
                responseStaticPage(requestURI,out);
            }else{//动态资源:java程序,业务处理类
                //requestURI: /oa/login?username=zhangsan&password=111
                //requestURI: /oa/login
                
                String servletPath = requestURI;
                //判断servletPath是否包含参数
                if(servletPath.contains("?")){
                    //split后面是正则表达式,?在正则表达式中有特殊含义,需要转义
                    servletPath = servletPath.split("[?]")[0];// /oa/login
                }
                    
                if("/oa/login".equals(servletPath)){
                    LoginServlet loginServlet = new LoginServlet();
                    loginServlet.service();
                }
            }
            //强制刷新
            out.flush();            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //关闭资源
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(clientSocket != null){
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
    }

    /**
     * 处理静态页面
     * @param requestURI 请求URI
     * @param out    响应流对象
     */
    public void responseStaticPage(String requestURI, PrintWriter out) {
        //requestURI:/oa/index.html
        //静态页面的路径:oa/index.html
        String htmlPath = requestURI.substring(1);
        BufferedReader br = null;
        try {
            //读取页面
            br = new BufferedReader(new FileReader(htmlPath));
            StringBuilder html = new StringBuilder();
            //拼接响应信息
            html.append("HTTP/1.1 200 OK\n");
            html.append("Content-Type:text/html;charset=utf-8\n\n");
            String temp = null;
            while((temp = br.readLine()) != null){
                html.append(temp);
            }
            //输出html
            out.print(html);
        } catch (FileNotFoundException e) {
            //404找不到资源
            StringBuilder html = new StringBuilder();
            html.append("HTTP/1.1 404 NotFound\n");
            html.append("Content-Type:text/html;charset=utf-8\n\n");
            html.append("<html>");
            html.append("<head>");
            html.append("<title>404-错误</title>");
            html.append("<meta content='text/html;charset=utf-8'/>");
            html.append("</head>");
            html.append("<body>");
            html.append("<center><font size='35px' color='red'>404-Not Found</font></center>");
            html.append("</body>");
            html.append("</html>");
            out.print(html);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

 

 

 

posted @ 2020-02-13 12:01  摘珰  阅读(262)  评论(0编辑  收藏  举报