一 servlet概述
狭义的Servlet指javax.servlet包中的一个接口,而广义的Servlet则是指实现了这个接口的类。一个Servlet应用有一个或多个Servlet程序。
Jsp是在传统的HTML代码中插入java程序段(Scriplet)与jsp标记(tag).
servlet应用需要在servlet容器中运行,典型容器如Jetty、Tomcat 运行servlet应用。在一个容器中可以同时运行Servlet与静态内容。
servlet API 主要由以下几个工具包:
1.javax.Servlet 其中包含Servlet和Servlet容器之间契约的类和接口
2.javax.Servlet.http 其中包含定义HTTP Servlet(采用了HTTP协议的Servlet)和Servlet容器之间契约的类和接口。
3.avax.servlet.annotation,其中包含标注Servlet、Filter、Listener的标注。它还为被标注元件定义元数据。
javax.servlet.descriptor,其中包含提供程序化登录web应用程序的配置信息的类型。
二 Servlet接口
其中的方法包括:
1.init(ServletConfig config) 当该Servlet被一次请求时,调用该方法,此后不再调用。参数传入的是Servlet的配置信息
2.service(ServletRequest req,ServletResponse res) 每当请求Servlet时,Servlet容器就会调用这个方法。编写代码时,假设Servlet要在这里 被请求。第一次请求Servlet时,Servlet容器调用init方法和Service方法。后续的请求将只调用Service方法。
3.destroy() 当要销毁Servlet时,Servlet容器就会调用这个方法。当要卸载应用程序,或者当要关闭Servlet容器时,就会发生这种情况。一般会在这个方法中编写清除代码。
4. ServletConfig getServletConfig() 这个方法会返回由Servlet容器传给init方法的ServletConfig
5. String getServletInfo() 这个方法会返回Servlet的描述。
ServletRequest接口 封装请求数据
1. Object getAttribute(String name) 返回以name为名字的属性的值,如果不存在,返回null
2. Enumeration getAttributeNames(); 返回请求中所有可用的属性的名字。返回一个枚举集合
3. void removeAttribute(String name); 移除请求中名字为name的属性
4. void setAttribute(String key,Object val); 在请求中保存一个键值对。
5. getCharacterEncoding() 返回请求正文使用的字符编码的名字
6. int getContentLength() 以字节为单位,返回请求正文的长度。
7. String getContentType() 返回正文的MIME类型
8. ServletInputStream getInputStream()
9. BufferedReader getReader()
10.String getLocalAddr() 返回接收到请求的网络接口的IP地址。
11.String getRemoteAddr() 返回发送请求的客户端或最后一个代理服务器的IP地址
12. String getRemoteHost() 返回发送请求的客户端或者最后一个代理服务器的完整限定名
13. String getLocalName() 返回接收到请求的IP接口的主机名
14. int getLocalPort() 返回接收到请求的网络接口的IP端口号
15. int getRemotePort() 返回发送请求的客户端或最后一个代理服务器的IP源端口。
16 String getParameter(String name) 返回请求中name参数的值,如果name参数有多个值,该方法返回值列表中的第一个值。如果请求中没有找到该参数,返回null
17 Enumeration getParameterNames() 返回请求中包含的所有的参数的名字。
18 String[] getParameterValues(String name); 返回请求中name参数所有的值
19 String getProtocal() 返回请求使用的协议的名字和版本 例如: HTTP/1.1
20. RequestDispatcher getRequestDispatcher(String path) 返回RequestDispather对象,作为path所定位的资源的封装。
21. String getServerName() 返回请求发送到服务器的主机名
22 int getServerPort() 返回请求发送到服务器的端口号
23. setCharacterEncoding(String env) 覆盖在请求正文中所使用的字符编码的名字。(链接:http://www.jianshu.com/p/d718a5f4a850)
ServletResponse接口,用来封装响应数据
flushBuffer() 强制把任何在缓存中的内容发送到客户端
int getBufferSize() 返回实际用于响应的缓存的大小,如果没有使用缓存,这个方法返回0
String getCharacterEncoding() 返回响应中发送的正文所使用的字符编码(MIME字符集)
String getContentType()返回响应中发送的正文所使用的MIME类型
ServletOutputStream getOutputStream()
PrintWriter getWriter()
boolean isCommitted() 返回一个布尔值,指示是否已经提交了响应。
void reset() 清除在缓存中的任何数据,包括状态代码和消息报头。
void resetBuffer() 清除在缓存中的响应内容,保留状态代码和消息包头。
void setBufferSize(int size) 设置响应正文的缓存大小。
void setCharacterEncoding(String charset) 设置发送到客户端的响应的字符编码
void setContentLength(int len) 设置内容正文的长度
void setContentType(String type) 设置要发送到客户端的响应的内容类型。例如:"text/html;charset=UTF-8"
ServletConfig
Servlet容器使用ServletConfig对象在Servlet初始化期间向它传递配置信息,一个ServletConfig对象。
String getInitParameter(String name); 返回名字为name的初始化参数的值,初始化参数在web.xml配置文件中进行配置。
Enumeration getInitParameterNames() 返回Servlet所有初始化参数的名字的枚举集合。
ServletContext getServletContext() 返回Servlet上下文对象的引用。
String getServletName() 返回Servlet实例的名字,这个名字是web应用程序的部署描述符中指定。
编写一个Servlet实际上就是编写一个实现了javax.servlet.Servlet接口的类。
GenericServlet
如果要编写一个通用的Servlet,只需要从GenericServlet继承,并且实现抽象方法service();
String getInitParameter(String name)
Enumeration getInitParameterNames();
ServletContext getServletContext()
init(ServletConfig config)
HttpServlet
在绝大多数的网络应用中,都是客户端通过HTTP协议去访问服务器端的资源我们编写的Servlet也主要是应用于HTTP协议的请求和响应,为了快速开发应用于HTTP协议的Servlet类,sun公司在javax.servlet.http包中给我们提供了一个抽象类HttpServlet,它继承自GenericServlet类,用于创建适合WEB站点的HTTP Servlet
public void service(ServletRequest req,ServletResponse res);
protected void service(HttpServletRequest req,HttpServletResponse resp)
针对HTTP1.1定义的7种请求方法GET,POST,HEAD,PUT,DELETE,TRACE,OPTION,
HttpServlet提供了7个处理方法
doGet(HttpServletRequest req,HttpServletResponse resp)
doPost(HttpServletRequest req,HttpServletResponse resp)
......
当容器接受到一个针对HttpServlet对象的请求时,调用该对象中的方法顺序如下:
调用公共的service()方法
在公共的service()方法中,首先将参数类型转换为HttpServletRequest和HttpServletResponse,然后调用保护的service()方法,将转换后的对象作为参数传递进去
在保护的service方法中,首先调用HttpServletRequest对象的getMethod方法,获取HTTP请求方法的名称,然后根据请求方法的类型,调用相应的doXxx()方法
HttpServletRequest
继承自javax.servlet.servletRequest,在该接口中新增的方法如下:
String getContextPath() 返回请求URI中表示请求上下文的部分,上下文路径是请求URI的开始部分
Cookie[] getCookies() 返回客户端在此次请求中发送的所有的Cookie对象
String getHeader(String name) 返回名字为name的请求报头的值
Enumeration getHeaderNames() 返回此次请求中包含的所有的报头名字的枚举集合
Enumeration getHeaders(String name) 返回名字为name的请求报头的所有值的枚举集合
String getMethod() 返回此次请求所使用的HTTP方法的名字
String getServletPath() 返回请求URI中调用Servlet的部分
HttpSession getSession() 返回和此次请求相关联的Session
HttpSession getSession(boolean create) 返回此次请求相关联的Session,如果没有给客户端分配Session,并且create参数为true,则创建一个新的Session,如果为false,此次请求没有一个有效的HttpSession,返回null
HttpServletResponse
该接口继承ServletResponse,新增的方法入下
addCookie(Cookie cookie)
addHeader(String name,String value);
boolean containsHeader(String name)
encodeRedirectURL(String url)
使用SessionID 对于重定向的url编码,以便用于sendRedirect()方法中
encodeURL(String url) 使用SessionID 指定的url编码
sendRedirect(String location) 发送一个临时的重定向响应到客户端,让客户端访问新的url
(链接:http://www.jianshu.com/p/d718a5f4a850)
ServletConfig接口
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init方法传入一个ServletConfig对象。ServletConfig封装了通过@WebServlet注解或者部署描述符(关于@WebServlet注解和部署描述符的内容会在后面的文章中讲到)传给Servlet的配置信息。这样传入的每一条信息就叫一个初始参数。一个初始参数有key和value两个元素。可以使用getServletConfig来获取传递给Servlet的ServletConfig。
为了从Servlet内部获取到初始参数的值,要在Servlet容器传给Servlet的init方法的ServletConfig中调用getInitParameter方法。ServletConfig还提供了另一个很有用的方法:getServletContext。利用这个方法可以从Servlet内部获取ServletContext。
(链接:http://www.jianshu.com/p/136fb6bf9ed6)
4.ServletContext接口
ServletContext表示Servlet应用程序的上下文,且每一个应用程序只有一个上下文。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
通过在ServletConfig中调用getServletContext方法,可以获得ServletContext。有了ServletContext,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。ServletContext将对象保存在一个内部Map中。保存在ServletContext中的对象被称作属性。
链接:http://www.jianshu.com/p/136fb6bf9ed6
Cookie
Cookie是由Web服务器保存在用户浏览器上的小文本文件,它可以包含有关用户的信息。无论何时用户链接到服务器,Web站点都可以访问cookie信息。Cookie作为HTTP header的一部分,其传输由HTTP协议控制。此外,你还可以控制cookie的有效时间。
可以通过传递name和value两个参数给Cookie类的构造函数来创建一个cookie:
Cookie cookie = new Cookie(name, value);
创建完一个Cookie对象后,你可以使用setMaxAge方法设置maxAge属性,这个属性决定cookie何时过期。
要将cookie发送到浏览器,需要调用HttpServletResponse的add方法。
服务端若要读取浏览器提交的cookie,可以通过HttpServletRequest接口的getCookies方法,该方法返回一个Cookie数组,若没有cookies则返回null。你需要遍历整个数组来查询某个特定名称的cookie。
目前,还没有通过名称来获取cookie的方法来帮助简化工作。此外,也没有一个直接的方法来删除一个cookie,你只能创建一个同名的cookie,并将maxAge 属性设置为0,并添加到HttpServletResponse接口中,就像下面这样:
Cookie cookie = new Cookie("userName", "");
cookie.setMaxAge(0);
response.addCookie(cookie);
现在我们来编写一个使用cookie来帮助统计用户访问某一页面次数的Servlet:
package com.mc.hello;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
int count = 0;
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("VisitCount")) {
count = Integer.parseInt(cookie.getValue());
break;
}
}
}
count++;
out.print("这是你第" + count + "次访问这个页面");
Cookie cookie = new Cookie("VisitCount", "" + count);
response.addCookie(cookie);
}
}
在web.xml中的配置:
cookiecom.mc.hello.CookieDemoServletcookie/cookie
在浏览器地址栏中输入http://localhost:8080/HelloWorld/cookie即可看到如下页面:
显示访问次数的页面
每刷新一次这个页面,访问次数都会增加一次。但是当我们关闭浏览器,然后再次打开浏览器,并输入这个页面的URL时,页面上显示的访问次数还是一次。这是因为我们没有设置cookie的过期时间,当我们关闭浏览器的时候cookie就过期了。这里我们将这个cookie的过期时间设置为3分钟:
Cookie cookie = new Cookie("VisitCount", "" + count);
cookie.setMaxAge(3 * 60);
response.addCookie(cookie);
这样一来,3分钟之内,无论我们是否关闭浏览器,cookie都不会过期。
Session 接口
Session是另一种记录客户状态的机制,与Cookie将客户状态保存在客户端浏览器中的形式不同,Session将客户状态保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。客户端浏览器再次访问时只需要从该Session中查找该客户的状态即可。
HttpSession接口是Java对Session机制的实现规范,它位于javax.servlet.http包中。
HttpSession对象在用户第一次访问网站的时候自动被创建,你可以通过调用HttpServletRequest的getSession方法获取该对象。getSession有两个重载方法:
HttpSession getSession()
HttpSession getSession(boolean create)
没有参数的getSession方法会返回当前的HttpSession,若当前没有,则创建一个返回。getSession(false)返回当前HttpSession,如当前会话不存在,则返回null。getSession(true)与没有参数的getSession方法一致,也是返回当前HttpSession,若当前没有,则创建一个。
可以通过HttpSession的setAttribute方法将值放入HttpSession,该方法签名如下:
void setAttribute(String name, Object value)
调用setAttribute方法时,若传入的name参数此前已经使用过,则会用新值覆盖旧值。
通过调用HttpSession的getAttribute方法可以取回之前放入的对象,该方法的签名如下:
Object getAttribute(String name)
注意,所有保存在HttpSession的数据不会被发送到客户端。
可以通过调用HttpSession的getId方法来读取Session的ID。Servlet容器为每个HttpSession生成唯一的标识,并为这个标识创建一个名为JSESSIONID的cookie。在后续的请求中,浏览器会将标识提交给服务端,这样服务器就可以识别该请求是由哪个用户发起的。
下面是几种使Session失效的方法:
在项目的部署描述文件中进行设置:
1
该Session会在最后一次访问一分钟后失效
直接在应用服务器中设置。如果是tomcat,可以在tomcat目录下conf/web.xml中找到元素,tomcat默认设置是30分钟,只要修改这个值即可。
对HttpSession调用setMaxInactiveInterval方法来设定其超时时间:
void setMaxInactiveInterval(int seconds)
对HttpSession调用invalidate方法强制使会话过期。
下面我们编写程序来创建一个Session:
package com.mc.hello;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet(urlPatterns = { "/mysession" })
public class SessionDemoServlet extends HttpServlet {
private static final long serialVersionUID = 36L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
session.setAttribute("name", "maconn");
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
out.print(cookie.getName() + " = " + session.getId());
}
}
else
out.print("no cookie");
}
}
第一次打开页面,由于之前此时还不存在Session,也就不存在JSESSIONID对应的cookie,此时网页上会显示"no cookie"。再次刷新页面,就会看到Session对应的JSESSIONID。
链接:http://www.jianshu.com/p/95849fa7be53