1. servlet的目录结构(以tomcat为例)。
所有application工程需要放到tomcat的webapps文件下,并建立如下文件,例子中webapps的名字为my。
³ Web App 下面必须要有WEB-INF目录,可以有META-INF目录。
² WEB-INF(下面必须有lib和classes文件夹以及web.xml文件)
± web.xml为该web app的配置文件
± lib 该文件夹下存放当前这个web app用到的库文件(jar包)。tomcat会自动加载。要注意这个lib是只对这个webapp有效的。
± classes存放编译好的servlet class文件(可以有子目录,作为包的结构)。
² META-INF (和WEB-INF同级)
± 存放该web app的上下文信息,符合J2EE标准
目录层次如下:
Web Application可以直接放在webapp下面,也可以通过配置文件指定到其他目录 <host>里面
² <Context path=“/虚拟路径名“ docBase=”目录位置"debug="0" reloadable="true"/>
2. 什么是servlet和servlet的开发过程。
Servlet本身是一个接口,来自于javax.servlet。有两个子类:GenericServlet (抽象类),和HttpServlet。而HttpServlet又继承了GenericServlet,并且实现序列化接口。HttpServlet才是我们正式使用的类。
在使用HttpServlet类的时候, 最常用的两个方法是doGet和doPost。这两个都是默认由service方法来自动调用了。service方法不用重写。 通常我们都是重写doGet和doPost。
Get方式和post方式有什么区别?
get方式:在浏览器栏敲入地址。
post方式:从form中提交,并且form指明了是使用post方式。
在HttpServlet类的doxxx方法都有两个参数,分别是request和response。
Request是客户机对服务器的请求。所以服务器向从客户机里读东西,都是从request里面拿。
Response是服务器对客户机的相应。所以服务器向对客户机写东西,都是写到response里面。
在eclipse当中编译servlet程序,必须引入C:\apache-tomcat-6.0.14\lib下面的jsp-api.jar包。然后才可以再java程序当中引入javax.servlet.*;
在一个tomcat的执行过程中:service方法是默认会调用的,用来去执行各个doxxx方法。
注意在HttpServlet类下面有两个service方法,分别是:
protected void | service(HttpServletRequest req, HttpServletResponse resp) |
void | service(ServletRequest req, ServletResponse res) |
没有protected 的service方法是HttpServlet实现的父类的接口,也就是说,tomcat先调用这个没有protected的方法,然后这个没有proteced的方法会去调用有protected的service方法。
有protected的service方法是专门对应http协议的方法。所以他可以去专门去处理相应的doXXX(doGet,doPost等等)方法。具体调用doXXX什么方法,在于客户端的请求是以什么方式过来的。
tips:不要把代码考来考去的,只放到一个地方,修改的时候就方便。宁愿用方法调用的方式去执行。
3. Servlet的部署
第一步,把在eclipse当中编译好的class文件,复制到C:\apache-tomcat-6.0.14\webapps\my\WEB-INF\classes目录下。
第二步,编辑相应的webapp的对应的web.xml,本例中是C:\apache-tomcat-6.0.14\webapps\my\WEB-INF下的web.xml。对每一个servlet,加入servlet和servletmapping标签。
<?xmlversion="1.0" encoding="ISO-8859-1"?>
<web-appxmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>myfirstservlet</servlet-name>
<servlet-class>HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myfirstservlet</servlet-name>
<url-pattern>/HelloWorldServlet</url-pattern>
</servlet-mapping>
</web-app>
<servlet-name>myfirstservlet</servlet-name>是告诉tomcat这个servlet的名字,可以自己随便定义。<servlet-class>HelloWorldServlet</servlet-class>是放在C:\apache-tomcat-6.0.14\webapps\my\WEB-INF\classes下面那个class文件的名字。
servlet和servletmapping是配对的,也就是说,servletmapping通过和servlet描述同样的<servlet-name>来设定对于该servlet的URL地址。注意<url-pattern> </url-pattern>当中放入的连接是相对于webapp而言的,也就是说,与html当中不一样,在这里,/代表当前的webapp,访问的是webapp的根目录,而不是tomcat的根目录。
带有包的servlet的部署。
在如果class文件是有包的层级结构的,在C:\apache-tomcat-6.0.14\webapps\my\WEB-INF\classes当中也要加入相应的层次结构(必须是用全名)。把myfirstservlet.class放到C:\apache-tomcat-6.0.14\webapps\my\WEB-INF\classes\com\bjsxt\test\目录下。
同时修改C:\apache-tomcat-6.0.14\webapps\my\WEB-INF下的web.xml,加入servlet和servletmapping标签。
Servlet标签的写法:
<servlet>
<servlet-name>com.bjsxt.test.myfirstservlet</servlet-name>
<servlet-class>HelloWorldServlet</servlet-class>
</servlet>
才可以正常访问。
为了方便修改tomcat当中的信息(比如配置xml等),在C:\apache-tomcat-6.0.14\conf下修改context.xml,把第一行改成<Context reloadable="true">,那么tomcat就会检查我们对tomcat的改动,每个1分钟reload一次。
在tomcat容器的情况下,注意在地址栏当中输入的地址,必须区分大小写,不然就会出现访问不到的情况。
默认情况下,中文没有办法在tomcat里面显示?
解决方法是:在打印流把字符集设成GBK。
代码如下:resp.setContentType(“text/html; charset=gbk”);
4. Serlvet生命全过程
第一步,加载 ClassLoader
第二步,实例化 new 在客户端的第一次请求到达的时候。而且只new一遍。
第三步,初始化 init(ServletConfig) 也只执行一次。
第四步,处理请求 service doGet doPost
第五步,退出服务 destroy()
其核心在于整个生命周期当中,只有一个servlet对象
API中的过程:
init()//只执行一次, 第一次初始化的时候
public void init(ServletConfig config)throws ServletException
service()
public void service(ServletRequest req,ServletResponse res) throws ServletException, java.io.IOException
destroy()//webapp 退出的时候
public void destroy()
关于为什么有两个init()方法?
有两个init(),一个是不带参数的init(),另外一个是init(ServletConfig config),其实就只有一个。不带参数的init()是用来方便程序员重写的。
5. servlet从上一个页面取参数的方式。
通过在doxxx方法里面的request.getParameter("param1")方法。
页面如下:
<formid="form1" name="form1" method="post"action="ThreeParams">
<table width="343"border="1">
<tr>
<tdwidth="92">param1</td>
<td width="94"><inputname="param1" type="text" id="param1" /> </td>
</tr>
<tr>
<td>param2</td>
<td><label>
<input name="param2"type="text" id="param2" />
</label></td>
</tr>
<tr>
<td>param3</td>
<td><inputname="param3" type="text" id="param3"/></td>
</tr>
<tr>
<td> </td>
<td><label>
<input type="submit"value="提交" />
</label></td>
</tr>
</table>
</form>
servlet如下,要注意是的中文乱码问题:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
publicclass ThreeParams extends HttpServlet{
privatestaticfinallongserialVersionUID = 1L;
@Override
protectedvoid doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
response.setContentType("text/html;charset=GBK");
//解决post方式提交内容的乱码
//一定要写在存取第一个参数之前
request.setCharacterEncoding("GBK");
//解决get方式乱码问题:在server.xml当中,connector标签-->URIEncoding="GBK"
PrintWriter out = response.getWriter();
out.println(request.getParameter("param1"));
out.println("<br>");
out.println(request.getParameter("param2"));
out.println("<br>");
out.println(request.getParameter("param3"));
out.println("<br>");
System.out.println("indoGet");
}
@Override
protectedvoid doPost(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
System.out.println("indoPost");
doGet(request, response);
}
}
参数传递的是通过html文件的当中的name来确定参数的名称,而不是id,这点要注意。
5.1对于多参数的页面传递:
有两种方式遍历:
一个是Enumeration。
要注意!这里的Enumeration不是枚举的类型,而是一个容器便利器。Enumeration是一个接口,来自java.util。而且是一个从jdk1.0就有的接口。其功能和Iterator功能是重复的,而且已经被Iterator所取代。可以认为Enumeration就是一个已经废弃的Iterator。
而,Emum才是真正的枚举类型。,而且是一个类。来自java.lang。是一个从jdk1.5才有的类。其功能才是真正的枚举。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
//获取所有的参数
publicclass ShowParameters extends HttpServlet {
publicvoid doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
String title = "Reading AllRequest Parameters";
out.println("<html><head><title>读取所有参数</title></head>"
+ "<BODYBGCOLOR='#FDF5E6'>\n" + "<H1 ALIGN=CENTER>" + title
+ "</H1>\n" + "<TABLEBORDER=1 ALIGN=CENTER>\n"
+ "<TRBGCOLOR=\"#FFAD00\">\n"
+ "<TH>ParameterName<TH>Parameter Value(s)");
//通过Eumeration容器遍历器,类似Iterator方式
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName =(String) paramNames.nextElement();
out.print("<TR><TD>" + paramName + "\n<TD>");
//同一个名字的参数,但是有不同的值。通过同样的一个名字,取出多个值。
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.println("<I>No Value</I>");
else
out.println(paramValue);
} else {
out.println("<UL>");
for (int i = 0; i < paramValues.length; i++) {
out.println("<LI>" + paramValues[i]);
}
out.println("</UL>");
}
}
out.println("</TABLE>\n</BODY></HTML>");
}
publicvoid doPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
doGet(request, response);
}
}
另外一个方式是使用map接口。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
//获取所有的参数
publicclass ShowParametersMap extends HttpServlet {
publicvoid doGet(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
String title = "Reading AllRequest Parameters";
out.println("<html><head><title>读取所有参数</title></head>"
+ "<BODYBGCOLOR='#FDF5E6'>\n" + "<H1 ALIGN=CENTER>" + title
+ "</H1>\n" + "<TABLEBORDER=1 ALIGN=CENTER>\n"
+ "<TRBGCOLOR=\"#FFAD00\">\n"
+ "<TH>ParameterName<TH>Parameter Value(s)");
//不用枚举,用map,注意采用的方法是request.getParamterMap()获取的是字符串(key)+字符串数组(value)
Map<String, String[]> paramMap =request.getParameterMap();
Set<Map.Entry<String, String[]>> entries =paramMap.entrySet();
//map不能用iterator,所以把内容放到set里面。
for(Iterator<Map.Entry<String, String[]>> it =entries.iterator(); it.hasNext(); ) {
Map.Entry<String, String[]> entry = it.next();
String paramName = entry.getKey();
out.print("<TR><TD>" + paramName + "\n<TD>");
String[] paramValues = entry.getValue();
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.println("<I>No Value</I>");
else
out.println(paramValue);
} else {
out.println("<UL>");
for (int i = 0; i < paramValues.length; i++) {
out.println("<LI>" + paramValues[i]);
}
out.println("</UL>");
}
}
out.println("</TABLE>\n</BODY></HTML>");
}
publicvoid doPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
doGet(request, response);
}
}
6. COOKIE的用法
6.1 HTTP协议的特点:
由于HTTP本身是无连接性的:也就是说和客户端的连接断掉了以后,不保存任何来自客户端的信息。那么在客户端再次访问的时候,服务器将没有办法找到任何来自客户端的信息,也就是说,在客户端再次访问的时候,根本就没有上次访问的任何信息。
6. 2 COOKIE是什么?
1:服务器可以向客户端写信息,也就是Cookie。
2:cookie只能是文本内容(不可以是exe,也不可以是图片),并且最大只能是4k。
3:客户端可以阻止服务器写入:浏览器可以把cookie禁用。所以对服务器而言,Cookie当中不应该放有核心的业务逻辑。一般是可有可无的内容。
4:服务器在读取cookie的时候,只能拿自己输入webapp写入的东西。也就是说,服务器只能拿自己在客户端上写入的cookie,而不能去拿别的网站的信息。
5:Cookie分为两种
第一种叫session cookie,属于窗口/子窗口(放在内存中的),也就是说当前浏览器窗口关闭就消失。但是从当前窗口打开的窗口,是可以看到session cookie的。
第二种叫persistent cookie,属于文本(有生命周期的),可以设定它的存在时间。
6:一个servlet/jsp设置的cookies能够被同一个路径下面或者子路径下面的servlet/jsp读出来。 反过来,父路径不能访问在子路径的设置的cookies.
要注意:类似于map, Cookie当中存储的也是键值对。注意,这里所说的路径是指在web.xml当中设置的路径<url-pattern>/HelloWorldServlet</url-pattern>,而不是物理文件在硬盘上存储的位置(实际上,物理文件的层次结构代表的是包的结构)。
把cookie写到客户端用response.addCookie(cookie),从客户端读cookie用request.getCookies()。
1.SetCookies
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
publicclass SetCookies extends HttpServlet {
publicvoid doGet(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
for (int i = 0; i < 3; i++) {
// Default maxAgeis -1, indicating cookie applies only to current browsing session.
//通过tomcat new出一个cookie,第一个参数是cookie的名字,第二个参数是cookie的值。
Cookie cookie = new Cookie("Session-Cookie-" + i, "Cookie-Value-S" + i);
//把cookie的内容写到客户端。
response.addCookie(cookie);
//是Persistent类型的cookie
cookie = new Cookie("Persistent-Cookie-" + i, "Cookie-Value-P" + i);
// Cookie isvalid for an hour, regardless of whether user quits browser, reboots computer,or whatever.
//cookie存在的时间,以秒为单位,这里就是1个小时。退出浏览器,重启电脑,都对不对这个cookie的存活时间造成影响。
cookie.setMaxAge(3600);
response.addCookie(cookie);
}
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
out.println("<html><head><title>设置Cookie</title></head>"
+ "<BODY>\n"
+ "<H1ALIGN=\"CENTER\">"
+ "设置Cookie" + "</H1>\n"
+ "6个Cookie\n"
+ "<AHREF=\"ShowCookies\">\n"
+ "查看</A>.\n"
+ "</BODY></HTML>");
}
}
2.ShowCookies
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
//读取客户端的Cookie
publicclass ShowCookies extends HttpServlet {
publicvoid doGet(HttpServletRequest request,
HttpServletResponseresponse)
throws ServletException, IOException{
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
String title = "Active Cookies";
out.println("<html><head><title>获取客户端Cookie</title></head>" +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=\"CENTER\">\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
" <TH>CookieName\n" +
" <TH>Cookie Value");
//得到来自于客户端的cookie,放到一个数组里面
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Cookie cookie;
for(int i=0; i<cookies.length; i++) {
cookie = cookies[i];
out.println("<TR>\n" +
//获取cookie的键
" <TD>" + cookie.getName() + "</TD>\n" +
//获取cookie的值
" <TD>" + cookie.getValue() + "</TD></TR>\n" );
}
}
out.println("</TABLE></BODY></HTML>");
}
}
7. Session的用法:
和cookie最大的区别在于session是放在服务器端的。当客户端第一次访问服务器的时候,服务器上采用对每个不同的客户生成ID的方式来区分不同客户对象,同时也会把ID的信息通过cookie写到客户端去。也就说,使用session的时候,依然是要使用cookie的。当一个新的客户端放过服务器的时候,服务器首先检查该客户端的ID,如果有服务器有相应的ID于之相配对,就是说明是老客户,已经访问过该服务器。如果没有ID就马上创建一个为其下次访问做准备,同时也会把ID的信息通过cookie写到客户端去。
Session就是在某段时间一连串客户端与服务器端的“交易”。其实建立一个session就是服务器生成属于一个客户端的session的ID号。
在Jsp/Servlet中,Seesion的两种实现方式:
1.使用cookie实现。
2.如果浏览器不支持Cookie,可以通过URL重写来实现,就是将一些额外数据追加到表示会话的每个URL末尾,服务器在该标示符与其存储的有关的该会话的数据之间建立关联。如hello.jsp?jsessionid=1234
可以通过程序来终止一个session。如果客户端在一定时间内没有操作,服务器会自动终止session。
不象Cookie,Session没有路径访问的问题:
同一个webapp下的servlet/jsp可以在一个客户端窗口,共享同一个session. 也就是说只要在同一个webapp,无论访问什么地方,都可以访问的到。
getRequestedSessionId():返回随客户端请求到来的会话ID。可能与当前的会话ID相同,也可能不同。
getSession(booleanisNew):如果会话已经存在,则返回一个HttpSession,如果不存在并且isNew为true,则会新建一个HttpSession.
isRequestedSessionIdFromCookie():当前的Session ID如果是从Cookie获得,为true
isRequestedSessionIdFromURL():当前Session ID如果是由URL获得,为true
isRequestedSessionIdValid():如果客户端的会话ID代表的是有效会话,则返回true。否则(比如,会话过期或根本不存在),返回false
HttpSession的常用方法
getAttributeNames()/getAttribute()
getCreateTime()
getId()
getMaxInactiveInterval()
invalidate()
isNew()
setAttribute()
setMaxInactivateInterval()
ShowSession
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
import java.util.*;
//Session追踪
publicclass ShowSession extends HttpServlet {
publicvoid doGet(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "SessionTracking Example";
//得到客户端对应的session对象,如果找不到(客户端第一次访问),就创建一个。
//可以得到一个session对象的引用。
HttpSession session = request.getSession(true);
String heading;
// Use getAttribute instead ofgetValue in version 2.2.
//取出"accessCount",返回的是"accessCount"的对象(object类型)。
Integer accessCount = (Integer) session.getAttribute("accessCount");
if (accessCount == null) {
accessCount = new Integer(0);
heading = "Welcome,Newcomer";
} else {
heading = "Welcome Back";
accessCount = new Integer(accessCount.intValue() + 1);
}
// Use setAttribute insteadof putValue in version 2.2.
//session就是一个篮子,可以往里面放东西。"accessCount"是对象的引用。AccessCount是值。
session.setAttribute("accessCount", accessCount);
out.println("<html><head><title>Session追踪</title></head>"
+ "<BODYBGCOLOR=\"#FDF5E6\">\n" + "<H1ALIGN=\"CENTER\">"
+ heading + "</H1>\n"
+ "<H2>Informationon Your Session:</H2>\n"
+ "<TABLEBORDER=1 ALIGN=\"CENTER\">\n"
+ "<TRBGCOLOR=\"#FFAD00\">\n" + " <TH>Info Type<TH>Value\n"
+ "<TR>\n" + " <TD>ID\n" + " <TD>" + session.getId()+ "\n"
+ "<TR>\n" + " <TD>Creation Time\n" + " <TD>"
//得到session对象的创建时间
+ new Date(session.getCreationTime()) + "\n" + "<TR>\n"
+ " <TD>Time of Last Access\n" + " <TD>"
//得到session对象的最后访问时间
+ new Date(session.getLastAccessedTime()) + "\n" + "<TR>\n"
+ " <TD>Number of Previous Accesses\n" + " <TD>"
+ accessCount + "\n" + "</TABLE>\n" + "</BODY></HTML>");
}
/**HandleGETandPOSTrequestsidentically.*/
publicvoid doPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
doGet(request, response);
}
}
在客户端把cookie禁掉的情况下,session将无法正常工作(因为没有办法把ID写过去),每次都创建新的session对象,也就是每次都创建新的ID, 这个时候就要采取URL重写的方式来实现session。函数为response.encodeURL()。它的功能是:
1.转码,中文乱码问题。
2.URL后面加入SessionId
如果cookie没有被禁掉,就是显示当前servlet的URL地址。
如果cookie被禁掉,这个sessionID就会加入到这个字符串当中。那么通过这种URL重写的方式,服务器希望往客户端上写的sessionID就可以被读取到,服务器就不会每次都重新分配一个新的sessionID,在浏览器窗口没有被关闭的期间,这个sessionID一直有效。
1. SessionInfoServlet
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
/**
*用于演示ServletAPI中的Session管理机制
*/
publicclass SessionInfoServlet extends HttpServlet
{
/**
*BuildsanHTMLdocumentcontainingsessioninformationand
*returnsittotheclient.
*/
publicvoid doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException
{
//getcurrent session or, if necessary, create a new one
HttpSession mySession = request.getSession(true);
//MIMEtype to return is HTML
response.setContentType("text/html");
//get ahandle to the output stream
PrintWriter out = response.getWriter();
//generateHTML document
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Session Info Servlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<H3>Session Information</H3>");
out.println("New Session: " +mySession.isNew());
out.println("<BR>Session ID: " + mySession.getId());
out.println("<BR>Session Creation Time: " +
newjava.util.Date(mySession.getCreationTime()));
out.println("<BR>Session Last Accessed Time: " +
newjava.util.Date(mySession.getLastAccessedTime()));
out.println("<H3>Request Information</H3>");
out.println("Session ID from Request: " +
//从客户端带过来的sessionID
request.getRequestedSessionId());
out.println("<BR>Session ID via Cookie: " +
//sessionID是不是从cookie取过来
request.isRequestedSessionIdFromCookie());
out.println("<BR>Session ID via rewritten URL: " +
//sessionID是不是从地址栏取过来
request.isRequestedSessionIdFromURL());
out.println("<BR>Valid Session ID: " +
//sessionID是不是合法有效的
request.isRequestedSessionIdValid());
out.println("</BODY></HTML>");
out.close(); //close output stream
}
/**
*Returnsabriefdescriptionofthisservlet.
*
*@returnBriefdescriptionofservlet
*/
public String getServletInfo()
{
return"Servlet returns session information.";
}
}
2. URLSession
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
import java.util.*;
//Session追踪
publicclass URLSession extends HttpServlet {
publicvoid doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(true);
out.println("<html><head><title>Session追踪</title></head>"
+ "<BODY>\n"
+ "sessionid:" + session.getId() + "<br>"
+ "fromurl:" + request.isRequestedSessionIdFromURL() + "<br>"
+ "from cookie:" + request.isRequestedSessionIdFromCookie() + "<br>"
//得到当前访问的servlet的URL地址
+ "<ahref=" +response.encodeURL(request.getRequestURL().toString()) +">test</a>"
+ "</BODY></HTML>");
}
/**HandleGETandPOSTrequestsidentically.*/
publicvoid doPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
doGet(request, response);
}
}
response.encodeURL()和response.encodeUrl()问题。
注意用大写的这个方法,小写的是过去的版本。做事严谨起见,为了防止客户端禁止cookie,一般采用URL重写的方式来对付session问题。
Session总结:
session的实质就是在服务器的一块内存(存key-value)
每个sesion和客户端窗口对应(子窗口)(通过客户端和服务器有对应独一无二的SessionID
客户端向服务器端发送SessionID的时候两种方式:
cookie(内存cookie) 浏览器禁掉cookie,就不能使用cookie实现的session
rewritten URL.如果想安全的使用session(不论客户端是否禁止cookie),只能使用URL重写(大大增加编程负担),所以很多网站要求客户端打开cookie.
Cookie | session |
存储在客户端 | 存储在服务器端 |
两种类型 l 有声明周期 l 无声明周期 | 两种实现方式 l 依赖于cookie l url重写 |
父路径不能访问子路径的cookie | 同一个session的窗口共享一个session |
典型应用: l 3个月不用再登陆 l 购物车(http://www.china-pub.com/) | 典型应用: l 用户登陆 l 购物车也可以用session实现。· |
不可靠 | 可靠 |
8. Application:
用于保存整webapp的声明周期内都可以访问的数据,在API中表现为servletContext。这是指servlet的运行环境,怎么和运行环境打交道,servletContext是比session还大的篮子,一个webapp下面所有的servlet访问同一个servletContext。session是对一个客户端有效的,servletContext是对所有的客户端都有效的。所以servletContext可以用来做页面的访问次数计数器。servletContext是通过HttpServlet的getServletContext来获取的。通过servletContext的get/setAttribute方法取得设置属性。
1. TestServletContext
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.util.Date;
publicclass TestServletContext extends HttpServlet {
@Override
protectedvoid doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException{
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
//得到servlet的上下文,是指servlet的运行环境,怎么和运行环境打交道。
ServletContext application = this.getServletContext();
//application是比session还大的篮子,一个webapp下面所有的servlet访问同一个application
//session是对一个客户端有效的,application是对所有的servlet有效的。
Integer accessCount = (Integer) application.getAttribute("accessCount");
if (accessCount == null) {
accessCount = new Integer(0);
} else {
accessCount = new Integer(accessCount.intValue() + 1);
}
// Use setAttribute insteadof putValue in version 2.2.
application.setAttribute("accessCount", accessCount);
out.println("<html><head><title>Session追踪</title></head>"
+ "<BODYBGCOLOR=\"#FDF5E6\">\n" + "<H1ALIGN=\"CENTER\">"
+ accessCount + "\n" + "</TABLE>\n" + "</BODY></HTML>"
+ "</H1>\n");
}
}
9. Servlet连接数据库 学习完数据库再补充
拷贝数据库驱动的jar包到apache-tomcat-6.0.14\webapps\Test\WEB-INF\lib文件夹
确认数据库已经启动
用户名、密码应该正确
Tips:在Servlet和JSP当中尽量不要用成员变量。因为多个线程客户端公用的是同一个对象的同一个成员标量。可能出现不可预知的问题。