java-web 第四讲 servlet 学习心得

1:servlet 接口:

1.1 servlet 主要方法: init()    --ServletConfig
servlet 实例化后,容器会先调用init 方法,用于初始化该对象,即在处理客户需求前完成一些初始化工作。每一个 servlet实例,init 只能被调用一次,相当于java的static 块。
   servlet 使用 ServletConfig 对象 从web 应用程序的配置信息中获取以 键值对形式提供的初始化参数。
   servlet 使用 ServletConfig 对象获取 ServletContext 对象,使用 ServletContext 可以使 servlet 和servlet 容器进行通信。 
service() --ServeltRequest ServletResponse
容器调用service() 方法来处理客户的请求,注意: 在service 方法前必须确保 init 方法正确完成。
容器会构造一个请求对象 ServletRequest 和 响应对象 ServletResponse 作为参数传递给service ().
destroy(): 当容器检测到servlet 对象从服务中移除的时候会调用该方法。释放资源 给GC
getServletConfig() 返回servletconfig 对象
getServletInfo() 返回一个字符串,包含servlet 信息
1.2 servlet 创建的三种方法一是实现Servlet接口,二是继承抽象类GenericServlet,三是继承HttpServlet类。
1: 实现servlet 接口 必须实现servlet 五个方法
  1. public class TestServlet implements Servlet{  
  2.     public void init(ServletConfig config) throws ServletException{  
  3.         System.out.println("init");  
  4.         }  
  5.     public ServletConfig getServletConfig(){  
  6.         reture null;  
  7.         }  
  8.     public void service(ServletRequest req,ServletResponse res)   
  9.         throws ServletException,IOException{  
  10.             //这里可以实现请求后要做的内容  
  11.             PrintWriter out = response.getWriter();  
  12.       out.println("Hello World!");  
  13.  
  14.             }  
  15.     public String getServletInfo(){  
  16.         return null;  
  17.         }  
  18.     public void destroy(){  
  19.         System.out.println("destory");  
  20.         }  
  21.     }  
2: 继承抽象类 GenericServletGenericServlet类中只有一个抽象方法,即service(ServletRequest req, ServletResponse res)
  1. public TestGenericServlet extends GenericServlet{  
  2.     public abstract void service(ServletRequest req,ServletResponse res)  
  3.                       throws ServletException,IOException{  
  4.      PrintWriter out = response.getWriter();  
  5.      out.println("Hello World!");                       
  6.      }  
		3: 继承HttpServlet类编写Servlet应该是最容易的,而且是最常见的,我们一般要编写Servlet直接继承这个类就行了,重写doGet()或者doPost()方法即可
  1. public TestHttpServlet extends HttpServlet{  
  2.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  3.         throws IOException, ServletException {  
  4.   response.setContentType("text/html;charset=gb2312");  
  5.   PrintWriter out = response.getWriter();  
  6.  
  7.   out.println("<html>");  
  8.   out.println("<head>");  
  9.   out.println("<title>HelloWorld</title>");  
  10.   out.println("</head>");  
  11.   out.println("<body bgcolor=\"white\">");  
  12.   out.println("<hr>");  
  13.   out.println("HelloWorld");  
  14.   out.println("</body></html>");  
  15.  }  
  16.  
  17.  public void doPost(HttpServletRequest request, HttpServletResponse response)  
  18.    throws IOException, ServletException {  
  19.   doGet(request, response);  
  20.  }  
  21.  

在servlet 中,主要接口与类方法如下:

1.3: HttpServlet 详解

1:七种请求方法 doGet doPost doHead doPut doDelete doTrace doOptions 参数都是 HttpRequest HttpResponse

2:servlet 执行顺序: 当容器收到一个servlet 请求后, 先调用 公共的 service() 方法 在调用service 时候,首先将参数转换为 HttpRequest 和 HttpResponse
然后调用保护的(protected) service() 方法 将转换后的 HttpRequest 和 HttpResponse 作为参数传递下去
在 protected service 中 ,首先调用 HttpRequest 的 getMethod() 获取 HTTP 请求方法的名字,然后根据类型调用相应的 doXXX() 方法

1.4: HttpServletRequest,HttpServletResponse 详解

	HttpServletRequest:	String getContextPath()  返回请求URL 中表示上下文的部分 如: /simple/test  返回 /simple
				Cookie[] getCookies()  返回本次请求所有的Cookie 对象
				String  getHeader()  返回请求报头的值
				String getMethod() 返回本次请求使用的HTTP 方法的名字  如 post  get Trace 等
				String getPathInfo()  返回额外 url 信息 如 /simple/test  返回 test
				String getPathTranslated() 返回真实路径信息  如 
				String getQueryString() 返回请求的action 名称 如  返回 logon
				
				HttpSession getSession() 返回和此次请求相关联的session
	HttpServletResponse:	void addCookie(Cookie cookie) 新增一个cookie 到响应中去,可以设置多个。
				addheader(String name,String value) 用给出的name and value 增加一个响应报头到响应中去
				sendRedirect(String location)  发送一个临时的重定向到客户端 让客户端访问的url重新定位

1.5: ServletConfig
		servlet容器使用ServletConfig 对象在容器初始化的时候向其传递配置信息
		四种主要方法:   String getInitParemeter(String name) 返回名字为 name 的初始化参数的值,初始化参数在配置文件 web.xml 中配置
				Enumeration getInitParameterNames() 返回servlet 所有初始化参数名字的枚举集合
				ServletContext getServletContext() 返回servlet 上下文对象的引用
				String getServletName() 返回 当前servlet 的名称

2:servlet 配置

  1:web.xml: web 应用程序的配置和部署都是通过web.xml 来完成的,其包含以下信息:
ServletContext 的初始化参数
		Session 的配置
		Servlet/Jsp 的定义
		Servlet/jsp 的
		MIME 类型映射
		欢迎文件列表
		错误页面
		安全
		地区和编码映射
		JSP 配置 
 
  
	
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
  	<!-- Servlet名字,可以随便取,有多个Servlet时不允许重名 -->
  	<servlet-name>SimpleServlet</servlet-name>
  	<!-- 指定实现这个Servlet的类 完整的包名+类名 -->
  	<servlet-class>com.tide.servlet.SimpleServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <!-- –必须和<servlet>里的<servlet-name>内容一样 -->
  	<servlet-name>SimpleServlet</servlet-name>
  	<!-- 指定访问这个Servlet的URL。这里给出的是对于整个Web应用的相对URL路径  这里是浏览器访问时的地址 http://localhost:8080/Myservlet/hello  即可访问--> 
  	<url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

	对于servlet 上的页面 有两种访问方式: 一种是在web.xml 中的 url-pattern 中直接访问地址   另一种是访问jsp 对象


3:servlet 例子

3.1 简单表单模拟
web.xml 部署为
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0"  xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">   <display-name></display-name>   <welcome-file-list>     <welcome-file>index.jsp</welcome-file>   </welcome-file-list>      <servlet>   <servlet-name>loginjsp</servlet-name>   <servlet-class>com.tide.servlet.Login</servlet-class>   </servlet>     <servlet-mapping>   <servlet-name>loginjsp</servlet-name>   <url-pattern>/login</url-pattern>   </servlet-mapping> </web-app>
login.jsp 测试登陆
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%> <% request.setCharacterEncoding("UTF-8"); %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>   <head>     <title>用户注册</title>   </head>      <body>     <center>     <h2>用户注册</h2>     <hr>     <form action="login" method="post">     用户姓名:<input type="text" name="username" style="width:138px" />     <br>     用户密码:<input type="password" name="password" style="width:138px" />     <br>     <br>     <input type="submit" value="确定"/>     <input type="reset" value="取消"/>     </form>     </center>   </body> </html>


package com.tide.servlet;


import java.io.IOException;
import java.io.PrintWriter;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class Login extends HttpServlet {


	public void doGet(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		String name = req.getParameter("username");
		System.out.println("获取的名称为-- " + name);
		PrintWriter pw;


		pw = res.getWriter();
		/*pw.print("<html><head><title>");
		pw.print("Welcome");
		pw.print("<title><head>");
		pw.print("<body>");
		pw.print("hello " + name);
		pw.print("</body></html>");*/
		pw.print("hello "+name);
		pw.close();


	}
	public void doPost(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException{
		  	String username = req.getParameter("username");
	        String password = req.getParameter("password");


	        res.setContentType("text/html");


	        PrintWriter out = res.getWriter();


	        out.println("<html><head><title>Login Result</title></head>");
	        out.println("<body> username: " + username + "<br>");
	        out.println("password: " + password + "</body></html>");


	        out.flush();
	}
}

--------------------------------------------------------------------------------------------------
采用post 模式 可以避免密码的泄露

get与post方法之间的差别:

  1.浏览器地址栏呈现的结果不同(表象);
  2.真正的原因在于向服务器端发送请求时的形式是不同的。
  3.get的请求格式:
  GET /test/LoginServlet?username=hello&password=world HTTP/1.1
  4.post的请求格式:
  POST /test/LoginServlet HTTP/1.1
 
  Connection: Keep-Alive
  username=hello&password=world
  5.通过浏览器进行文件上传时,一定要使用post方式而绝不能使用get方式。
  6.通过浏览器地址栏输入网址的方式来访问服务器端资源,全部使用的是get方法请求的。
------------------------------------------------------------------------------------------------------
3.2 消息包头输出到客户端
		servlet 实现:  报文头部 客户端的运行环境等信息 全部通过 HttpServletRequest 来获取
	
	public class OutputInfo extends HttpServlet {
	
	public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException{
		res.setContentType("text/html;charset=gb2312");
		PrintWriter pw = res.getWriter();
		Enumeration headName = (Enumeration) req.getHeaderNames();
		pw.println("<html><head>");
		pw.println("<title> Info Page </title>");
		pw.println("</head>");
		pw.println("<body><center>");
		pw.println("<table border=1 align=center>");
		pw.println("<caption>Servlet 接收到的Http 消息 包头的信息</caption>");
		pw.println("<tr bgcolor=#999999>");
		pw.println("<th>消息包头的名字</th>");
		pw.println("<th>消息包头的值</th>");
		pw.println("</tr>");
		
		while(headName.hasMoreElements()){
			String name = (String) headName.nextElement();
			String value = req.getHeader(name);
			pw.println("<tr>");
			pw.println("<td>"+name+"</td>");
			pw.println("<td>"+value+"</td>");
			pw.println("</tr>");
		}
		pw.println("</table><p>");
		pw.println("<table border=1 align=center>");
		pw.println("<caption> 其他访问信息 </caption>");
		pw.println("</tr>");
		pw.println("<tr>");
		pw.println("<td>客户端的IP地址</td>");
		pw.println("<td>"+req.getRemoteAddr()+"</td>");
		pw.println("</tr>");
		pw.println("<tr>");
		pw.println("<td>客户端的端口号</td>");
		pw.println("<td>"+req.getRemotePort()+"</td>");
		pw.println("</tr>");
		pw.println("<tr>");
		pw.println("<td>服务器端的IP地址</td>");
		pw.println("<td>"+req.getLocalAddr()+"</td>");
		pw.println("</tr>");
		pw.println("<tr>");
		pw.println("<td>服务器端的端口号</td>");
		pw.println("<td>"+req.getLocalPort()+"</td>");
		pw.println("</tr>");
		pw.println("</table>");
		pw.println("</center></body></html>");
		pw.close();
		}
	}
	将 servlet 添加到 web.xml 中 然后在客户端测试结果为 :
	
  
  
Servlet 接收到的Http 消息 包头的信息
消息包头的名字消息包头的值
hostlocalhost:8080
connectionkeep-alive
cache-controlmax-age=0
accepttext/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
user-agentMozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36
accept-encodinggzip,deflate,sdch
accept-languagezh-CN,zh;q=0.8
其他访问信息
客户端的IP地址127.0.0.1
客户端的端口号60255
服务器端的IP地址127.0.0.1
服务器端的端口号8080
 
 
	

4:Servlet 生命周期

	Servlet 运行期间,其生命周期由容器来统一管理,生命周期通过 Servlet 的 init()  destroy()  service()  三种方法来表示
	 	主要包含了四个阶段:
			1:加载和实例化
				在容器启动 或者响应第一个客户请求时,创建servlet  实例。
			2:初始化
				servlet 实例化后,容器必须调用 servlet 的 init() 方法来初始化这个servlet 对象,目的为了servlet 在处理客户请求前完成一系列的初始化工作,
				对于每一个servlet  init() 只调用一次, 此时可以使用 ServletConfig 来从web.xml 中获取初始化的参数信息。
			3:请求处理
				servlet 容器调用servlet 的 service() 方法对请求进行处理,在此之前 init() 方法必须调用成功。 
				Servlet 通过 ServletRequest 来获取客户端的信息和请求,对请求处理后 调用 ServletResponse 来设置响应信息。出现错误的话:该实例永久不可用-404  暂时不可用-503
			4:服务终止
				容器检测到实例从服务中移除后,调用 destroy()
				

5:Servlet 上下文

		运行在java 虚拟机中的每一个web程序都有一个与之相关的 Servlet 上下文, java servlet API 提供了一个 ServletContext 接口来表示上下文。
		一个 ServletContext 对象表示了一个web 程序的上下文, servlet 容器在初始化实例期间,向其传递 ServletConfig 对象, 通过其  getServletContext() 获取上下文。

		上下文例子: 统计页面访问量   *************注意这里的上下文必须放在安全锁里 
			public class CountDemo extends HttpServlet {
	
				public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException{
				ServletContext context = getServletContext();
				//Enumeration<String> count = context.getAttributeNames();
				Integer count = null;
				synchronized(context){
					count = (Integer)context.getAttribute("counter");
					if(null == count){
						count = new Integer(1);
					}else{
						count = new Integer(count.intValue()+1);
					}
					context.setAttribute("counter", count);
				}
				res.setContentType("text/html;charset=gb2312");
				PrintWriter pw = res.getWriter();
				pw.println("<html><head>");
				pw.println("<title>页面访问统计</title>");
				pw.println("</head><body>");
				pw.println("该页面已经被访问了  :"+"<b>"+count+"</b>"+" 次");
				pw.println("</body></html>");
				pw.close();
		
				}
			}

	

6:Servlet 请求转发

		好处:  <1> 提供了统一的访问方式   <2> 控制器(controller)可以将不同的请求发送给不同的servlet 来进行处理 本身不处理请求,缩短了响应时间
6.1 RequestDispacher: servlet 控制器
				RequestDispacher 对象由 Servlet 来创建,用于封装一个由路径所标示的服务器资源。  主要有以下两种方法:
				forward(ServletRequest req,ServletResponse res) :  该方法用于将 请求从一个servlet 传递给服务器上的 另外的 servlet  jsp 页面,或者 HTML 文件
					 注意: 这个方法必须在响应被提交给客户端之前使用,之后的话会爆出 IllegastateException 错误  在 forward() 调用后原先在响应缓存中的未被提交的内容将自动清除。
				include(ServletRequest req,ServletResponse res)  该方法用于响应中包含其他的资源信息(servlet  jsp  html)等内容。
					
				这两个方法的区别是:include 将请求转发给其他对象后,被调用的servlet 做出的响应将并入原来的响应对象中,原来的servlet 对象还可以继续输出响应数据。
							   forward  将请求转发给其他对象后,将由被调用的servlet 对象做出响应,原来的servlet 执行将终止。
			
		    6.2  RequestDispache 对象的获取
				三种方法:
					<1> ServletRequest.getRequestDispacher(String path)   --资源路径名
					<2> ServletContext.getNamedDispacher(String name)      --  jsp  或  servlet 名称
					<3> SerletContext.getRequestDispacher(String path)	-- 这里路径必须以 /  开头  相对于当前上下文根的路径  如 /MyServlet

		  6.3  请求转发的实例
				package com.tide.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.apache.commons.lang3.StringUtils;


public class Login extends HttpServlet {


	public void doPost(HttpServletRequest req,HttpServletResponse res)throws ServletException,IOException{
		res.setContentType("text/html;charset=GB2312");
		ServletContext context = getServletContext();
		String name = req.getParameter("user");
		String pass = req.getParameter("passwd");
		System.out.println("获取到的用户名为 :"+name+"  --密码为 :"+pass);
		if(StringUtils.isBlank(name) || StringUtils.isBlank(pass)){
			System.out.println("用户名或密码为空");
			RequestDispatcher dis = context.getRequestDispatcher("/register.jsp");
			dis.forward(req, res);
		}else{
			RequestDispatcher dis = context.getRequestDispatcher("/loginsuccess.jsp");
			dis.forward(req, res);
		}
		
	}
}
	底层分析:
	
      
      
请求转发(RequestDispatcher)的过程:
         客户首先发送一个请求到服务器端,服务器端发现匹配的servlet,并指定它去执行,当这个servlet执行完之后,它要调用getRequestDispacther()方法,把请求转发给指定的test.jsp,整个流程都是在服务器端完成的,而且是在同一个请求里面完成的,因此servlet和jsp共享的是同一个request,在servlet里面放的所有东西,在jsp中都能取出来,因此,jsp能把结果getAttribute()出来,getAttribute()出来后执行完把结果返回给客户端。整个过程是一个请求,一个响应。
重定向(sendRedirect)的工作原理:
             客户发送一个请求到服务器,服务器匹配servlet,这都和请求转发一样,servlet处理完之后调用了sendRedirect()这个方法,这个方法是response的方法,所以,当这个servlet处理完之后,看到response.senRedirect()方法,立即向客户端返回这个响应,响应行告诉客户端你必须要再发送一个请求,去访问test.jsp,紧接着客户端受到这个请求后,立刻发出一个新的请求,去请求test.jsp,这里两个请求互不干扰,相互独立,在前面request里面setAttribute()的任何东西,在后面的request里面都获得不了。可见,在sendRedirect()里面是两个请求,两个响应。
					

  
  

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值