简单服务器开发(八)响应动态:客户端访问小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(); } } }