1. Servlet
1.1 基本流程
1 2 3 4 5 6 7 (*)-> "login.html" -right-> "form表单处理给 '/login' " -down-> "web.xml映射,给LoginServlet处理" -right-> "LoginServlet处理" -right-> "实例化Servelt" -up-> "重写 doGet,doPost等方法,获取参数,设置响应" -up-> "返回html"
flowchart TD
A[login.html] -->|form提交到 /login| B(/login)
B -->|web.xml 映射| C[LoginServlet]
C --> D[实例化 Servlet]
D --> E[重写 doGet/doPost]
E -->|获取参数 & 设置响应| F[返回 HTML]
web.xml
1 2 3 4 5 6 7 8 9 10 11 <servlet > <servlet-name > HelloServlet</servlet-name > <servlet-class > HelloServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > HelloServlet</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping >
主要实现了处理映射(servlet-mapping标签) 和注册Servlet(servlet标签)
loginServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override protected void service (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { System.out.println("3. ========== service ============= 函数" ); request.setCharacterEncoding("UTF-8" ); response.setContentType("text/html;charset=UTF-8" ); String name = request.getParameter("name" ); String password = request.getParameter("password" ); if (name.equals("admin" ) && password.equals("admin" )) { request.getRequestDispatcher("success.html" ).forward(request, response); } else { response.sendRedirect("fail.html" ); } }
service将请求类型分发给doPost, doGet 等方法,用户只用重写这些方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1 ) { doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { ifModifiedSince = -1 ; } if (ifModifiedSince < (lastModified / 1000 * 1000 )) { maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { String errMsg = lStrings.getString("http.method_not_implemented" ); Object[] errArgs = new Object [1 ]; errArgs[0 ] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
servlet 跳转
服务端跳转
1 request.getRequestDispatcher("success.html" ).forward(request, response);
1 2 3 4 @startuml 浏览器 -> Tomcat : <color:#0867ff> /login</color> Tomcat -> 浏览器 : <color:#0867ff>把success.html的内容发送给浏览器 @enduml
客户端跳转
1 response.sendRedirect("fail.html" );
1 2 3 4 5 6 @startuml 浏览器 -> Tomcat : <color: #0867ff> /login</color> Tomcat -> 浏览器 : <color: #0867ff>服务器发送一条特殊信息给浏览器让浏览器访问fail.html</color> 浏览器 -> Tomcat : <color: #0867ff> 访问Tomcat</color> Tomcat -> 浏览器: <color: #0867ff> 服务端获取fail.html的内容,发送给浏览器</color> @enduml
1.2 生命周期
a. 实例化
1 2 3 4 5 6 7 8 9 public LoginServlet () { System.out.println("1. ============ 构造 ========= 函数" ); System.out.println("LoginServlet 构造方法 被调用" ); }
b. 初始化
1 2 3 4 5 6 7 8 9 10 11 @Override public void init (ServletConfig config) { System.out.println("2. ============ init ========= 函数" ); System.out.println("初始化函数" ); System.out.println("init(ServletConfig)" ); }
c. 提供服务
service -> doGet or service -> doPost
d. 销毁
1 2 3 4 5 6 7 8 @Override public void destroy () { System.out.println("4. ============= destroy ============ 函数" ); System.out.println("destroy 执行" ); }
e. 被回收
1.3 自启动
如果tomcat启动就需要执行一些初始化代码,就需要自启动,如校验数据库完整性
web.xml 需要配置自启动
1 2 3 4 5 6 7 <servlet > <servlet-name > HelloServlet</servlet-name > <servlet-class > HelloServlet</servlet-class > <load-on-startup > 10</load-on-startup > </servlet >
且将业务逻辑写在servlet 中的init()部分
1 2 3 4 5 6 7 @Override public void init () { System.out.println("init of Hello Servlet" ); }``java
1.4 request常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 System.out.println("3. ========== service ============= 函数" ); System.out.println("浏览器发出请求时的完整URL,包括协议 主机名 端口(如果有j):" + request.getRequestURL()); System.out.println("浏览器发出请求时的资源名部分,去掉了协议和主机名: " + request.getRequestURI()); System.out.println("请求行中的参数部分: " + request.getQueryString()); System.out.println("浏览器所处于的客户机的IP地址: " + request.getRemoteAddr()); System.out.println("浏览器所处于的客户机的主机名: " + request.getRemoteHost()); System.out.println("浏览器所处的客户机使用的网络端口" + request.getRemotePort()); System.out.println("服务器的ip地址" + request.getLocalAddr()); System.out.println("服务器的主机名" + request.getLocalName()); System.out.println("客户机的请求方式" + request.getMethod());
运行结果 例子