一、简介 最近看源码,涉及servlet这一块。借此对servlet及相关源码等知识进行回顾和介绍。通常说的servlet开发其实是一种开发动态网页的解决方案,它包含实现javax.servlet.Servlet接口的servlet程序和解析servlet程序的servlet引擎(即是servlet容器,如tomcat等)。servlet程序是在服务器端运行的。 二、servlet结构 一个servlet是一个在web服务器运行的小程序。 2.1 servlet依赖包 servlet开发依赖包为javax.servlet-api.jar,通常servlet容器中会有(如tomcat),因此打包一般在编译器使用。 <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>compile</scope> </dependency> 2.2 servlet流程 graph TB request -->|请求| servletContainer(servlet容器/引擎) servletContainer -->|调用| servletApi(servlet api) servlet程序 -->|实现| servletApi servlet引擎和servlet程序通过servlet api通信,流程为:servlet程序实现servlet api接口,外界请求到servlet容器时,servlet容器通过servlet引擎,调用servlet api,实现对servlet程序的调用。 2.3 servlet注册 servlet程序是在web.xml中注册的,包含servlet名称、servlet实现类、servlet请求地址,格式如下 <servlet> <servlet-name>servletName</servlet-name> <servlet-class>servlet实现类</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletName</servlet-name> <url-pattern>servlet匹配地址</url-pattern> </servlet-mapping> 2.3.1 servlet注册位置 通常servlet是在应用程序的web.xml中注册,但其实在servlet容器中(如tomcat), 在conf/web.xml还有个全局的注册(所有应用程序均可使用,控制全局的跳转)。 2.3.2 servlet匹配地址 servlet请求地址可以是固定的一个,也可采用通配符来匹配多个地址,不过采用通配符只能有两种格式: *.扩展名,此时 *前面不能有分割符 / ,这种方式的匹配优先级最低,如: *.html 匹配.html结尾的地址; 以分割符/开头并以*结尾的,如: /stu/ *,匹配所有/stu/开头的地址; servlet匹配地址采用最具体原则,地址匹配越具体,越优先容易匹配,其中 *.扩展名 模式的匹配优先级最低。 2.3.3 缺省servlet 缺省servlet位于servlet容器中的conf/web.xml中,如果servlet匹配地址为/,则该servlet为缺省servlet,当外界请求地址找不到servlet匹配地址时,就会走缺省servlet。通常访问静态资源(如图片、html等)时,走的就是缺省servlet,即此时不在需要单独配置servlet。 <servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <!--load-on-startup值为0或正数时,值越小,越早被加载,为负数时,则由容器决定加载时机--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> 2.4 servlet类加载 servlet类加载并非完全的双亲委派模式,略有不同,改为当前类加载器优先,目的是对不同web应用间相互隔离(比如不同web应用依赖不同版本的同类jar包,需要相互隔离),这里以tomcat中类加载为例,其类加载器有: graph BT system --- bootstrap common --- system webapp1 --- common webapp2 --- common webappx --- common 2.4.1 bootstrap bootstrap类加载器(包含jvm加载器和ExtClassLoader)用于加载jvm核心包(rt.jar)和系统扩展目录下的包(<java_home>/jre/lib/ext)。 2.4.2 sytem system类加载器(通常为AppClassLoader)加载classpath环境变量设置的指定目录中的类。实际使用(tomcat启动脚本,$CATALINA_HOME/bin/catalina.sh)中会忽略原有环境变量的设置,而改为加载$CATALINA_HOME/bin/bootstrap.jar、$CATALINA_HOME/bin/tomcat-juli.jar、commons-daemon.jar等jar包。 2.4.3 cmmon common类加载器加载tomcat内部类和所用webapp 共享的类($CATALINA_HOME/lib). 2.4.4 webapp webapp类加载器用于加载当前webapp应用程序下的/Web-INF/classes和/Web-INF/lib目录中的class文件和jar包。webapp类加载器仅对当前web应用程序可见。 2.4.5 完整类加载流程 当有类加载需求时,优先在当前应用程序的webapp类加载器加载,若没有,再使用双亲委派,委托common类加载器,commont类加载器接着委托system类加载器,若system类加载器失败,才由common类加载器加载,若common类加载器还是加载失败,则抛异常。 2.5 servlet生命周期 2.5.1 servlet初始化 一个servlet在其生命周期中只会初始化一次,同一个servlet也只会有一个实例。但servlet内的service(HttpServletRequest req, HttpServletResponse resp)方法会被多次调用,每次请求会新生成HttpServletRequest和HttpServletResponse实例。同一个servlet只有一个servlet对象,因此需要注意多线程安全问题。 2.5.2 servlet创建多个实例 servlet实现javax.servlet.SingleThreadModel接口后,可创建多个servlet实例(构成servlet实例池,每次请求使用一个)来处理请求,此时每个请求单独对用一个servlet实例(显然不存在并发引起的问题),当然该接口已经标记为@deprecated(过时),不在推荐使用,而推荐使用多线程同步来处理问题。使用示例如下: import javax.servlet.SingleThreadModel; import javax.servlet.http.HttpServlet; public class SingleServlet extends HttpServlet implements SingleThreadModel { } 三、servlet主要类 servlet主要类图如下: 接下来将分别介绍。 3.1 ServletContext类 每个web应用程序都是一个独立的Servlet容器,都有一个ServletContext对象。ServletContext定义了一组和servlet容器通信的方法(比如获取servlet容器初始化参数,这样就不需要在应用程序中写死,而是一个变量),ServletContext对象存在于ServletConfig对象中,当每个Servlet初始化时,ServletContext会随着ServletConfig提供给每个Servlet。 package javax.servlet; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.EnumSet; import java.util.EventListener; import java.util.Map; import java.util.Set; import javax.servlet.descriptor.JspConfigDescriptor; //ServletContext定义了一组和servlet容器通信的方法,每个web应用程序都有独立的ServletContext, //在每个Servlet初始化时,会随着ServletConfig提供给每个Servlet public interface ServletContext { //返回web应用程序的context路径,也就是在<tomcat_home>/conf/server.xml中context元素path的值 public String getContextPath(); //返回指定路径(容器中其他web应用程序的ServletContext,路径必须以/开头)的ServletContext,没有或没权限则返回null public ServletContext getContext(String uripath); //返回Servlet api的主版本,如3.0则返回3 public int getMajorVersion(); //返回Servlet api的次版本,如3.0则返回0 public int getMinorVersion(); //返回servlet容器支持的servlet主版本 public int getEffectiveMajorVersion(); //返回servlet容器支持的servlet次版本 public int getEffectiveMinorVersion(); //返回指定文件的mime类型(如text/html、image/gif) public String getMimeType(String file); //返回指定路径下的所有资源地址(文件或目录,不递归获取) public Set<String> getResourcePaths(String path); //返回给定地址的url,地址必须以/开头并会被解析为相对当前context root路径, 或者 public URL getResource(String path) throws MalformedURLException; //返回指定资源的InputStream public InputStream getResourceAsStream(String path); //返回RequestDispatcher对象,作为对给定路径资源的包装。 //RequestDispatcher可用于forward请求或者在response响应中包含动态或静态资源 public RequestDispatcher getRequestDispatcher(String path); //返回作为对给定名称servlet包装的RequestDispatcher public RequestDispatcher getNamedDispatcher(String name); //在servlet日志文件中记录信息 public void log(String msg); //在servlet日志文件中记录信息,包含堆栈信息 public void log(String message, Throwable throwable); //返回给定虚拟地址的真实完整地址,如:/index.html返回http://localhost:8080/index.html public String getRealPath(String path); //返回运行的servlet的servlet容器名称和版本信息 public String getServerInfo(); //返回指定名称的context初始化参数 public String getInitParameter(String name); //返回context初始化参数名称集合 public Enumeration<String> getInitParameterNames(); //在ServletContext中设置context初始化参数,若已经存在指定名称的context初始化参数,则失败,返回false(@since Servlet 3.0) public boolean setInitParameter(String name, String value); //返回在servlet容器中给定名称的属性值 public Object getAttribute(String name); //返回ServletContest中属性名称集合 public Enumeration<String> getAttributeNames(); //在ServletContext中设置属性值,如果已经存在则覆盖 public void setAttribute(String name, Object object); //在ServletContext中移除属性 public void removeAttribute(String name); //返回应用名称,即display-name值 public String getServletContextName(); //在ServletContext中添加servlet(@since Servlet 3.0) public ServletRegistration.Dynamic addServlet( String servletName, String className); //在ServletContext中添加servlet实例(@since Servlet 3.0) public ServletRegistration.Dynamic addServlet( String servletName, Servlet servlet); //在ServletContext中添加servlet(@since Servlet 3.0) public ServletRegistration.Dynamic addServlet(String servletName, Class <? extends Servlet> servletClass); //根据类实例实例化servlet public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException; //获取指定名称的servlet注册信息ServletRegistration(@since Servlet 3.0) public ServletRegistration getServletRegistration(String servletName); //以map形式获取所有ServletRegistration对象 public Map<String, ? extends ServletRegistration> getServletRegistrations(); //在servlet context中添加Filter(@since Servlet 3.0) public FilterRegistration.Dynamic addFilter( String filterName, String className); //在servlet context中添加Filter实例(@since Servlet 3.0) public FilterRegistration.Dynamic addFilter( String filterName, Filter filter); //在servlet context中添加Filter(@since Servlet 3.0) public FilterRegistration.Dynamic addFilter(String filterName, Class <? extends Filter> filterClass); //根据类实例实例化Filter public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException; //返回给定名称的Filter注册信息FilterRegistration (@since Servlet 3.0) public FilterRegistration getFilterRegistration(String filterName); //以map形式返回所用的Filter注册信息FilterRegistration (@since Servlet 3.0) public Map<String, ? extends FilterRegistration> getFilterRegistrations(); //返回SessionCookieConfig对象 public SessionCookieConfig getSessionCookieConfig(); //设置session跟踪方式(@since Servlet 3.0) public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes); //返回默认session跟踪方式(@since Servlet 3.0) public Set<SessionTrackingMode> getDefaultSessionTrackingModes(); //返回有效的session跟踪方式(@since Servlet 3.0) public Set<SessionTrackingMode> getEffectiveSessionTrackingModes(); //添加监听器EventListener public void addListener(String className); //添加监听器EventListener public <T extends EventListener> void addListener(T t); //添加监听器EventListener public void addListener(Class <? extends EventListener> listenerClass); //根据类名实例化监听器EventListener public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException; //获取在web.xml和web-fragment.xml中的jsp config public JspConfigDescriptor getJspConfigDescriptor(); //获取加载ServletContext的类加载器 public ClassLoader getClassLoader(); //声明角色(在isUserInRole使用) public void declareRoles(String... roleNames); //获取ServletContext部署在逻辑主机上的配置的名称 public String getVirtualServerName(); } 3.2 ServletConfig接口 ServletConfig为servlet配置对象,用于在servlet容器初始化servlet时传递信息。接口定义如下: package javax.servlet; import java.util.Enumeration; //servlet配置对象,用于在servlet容器初始化servlet时传递信息 public interface ServletConfig { //返回当前servlet实例的名称 public String getServletName(); //返回ServletContext的引用 public ServletContext getServletContext(); //返回ServletContext的引用 public String getInitParameter(String name); //返回当前servlet实例所有的初始化参数名称 public Enumeration<String> getInitParameterNames(); } 示例(仅列出关键代码): web.xml中servlet配置如下: <servlet> <servlet-name>stuServlet</servlet-name> <servlet-class>servlet.StuServlet</servlet-class> <init-param> <param-name>stuId</param-name> <param-value>001</param-value> </init-param> <init-param> <param-name>stuName</param-name> <param-value>apple</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>stuServlet</servlet-name> <url-pattern>/stuServlet</url-pattern> </servlet-mapping> StuServlet.java package servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Enumeration; public class StuServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /**************** ServletConfig ******************/ ServletConfig servletConfig = getServletConfig(); //返回当前servlet实例的名称 String servletName = servletConfig.getServletName(); //stuServlet //返回ServletContext的引用 ServletContext servletContextFromConfig = servletConfig.getServletContext(); //返回当前servlet实例指定名称的初始化参数值 String stuId = servletConfig.getInitParameter("stuId"); //001 //返回当前servlet实例所有的初始化参数名称 Enumeration<String> initParamNames = servletConfig.getInitParameterNames(); //stuId,stuName } } 3.3 Servlet接口 servlet是在web server端运行的java小程序,是所有Servlet需要实现的接口,定义了所有servlet必须实现的方法,方法包含服务请求、从服务中移除servlet以及servlet的整个生命周期(init、service、destroy)。接收和响应来自web客户端的请求。接口定义如下: package javax.servlet; import java.io.IOException; //Servlet接口定义了所有Servlet必须实现的方法 public interface Servlet { //servlet初始化时调用的初始化方法,只会被调用一次,且在接收任意请求前完成初始化 public void init(ServletConfig config) throws ServletException; //返回ServletConfig的引用 public ServletConfig getServletConfig(); //由servlet容器调用,对请求进行响应,需要注意多线程调用的情况(对临界资源的访问) public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; //返回关于servlet的信息(如作者、版本号、版权等) public String getServletInfo(); //servlet容器调用,表示从容器中移除servlet,只会被调用一次,,此时调用service方法的所有线程都退出或超时了 public void destroy(); } 3.4 GenericServlet抽象类 GenericServlet抽象类是对Servlet接口和ServletConfig接口的默认实现,类定义如下: public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { //具体实现方法在此略过,同实现接口一样 } 3.5 HttpServlet类 HttpServlet提供了抽象类,用于子类创建http servlet。同时子类必须重写doGet、doPost、doPut、doDelete、init、destory中至少一个方法,用于管理servlet生命周期中持有的资源。通常不需要重写public service方法,对于doOption和doTrace方法也不需要重写。servlet通常在多线程中运行,需要考虑临界资源的同步访问。HttpServlet类定义如下: package javax.servlet.http; import java.io.IOException; import java.io.PrintWriter; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Enumeration; import java.util.Locale; import java.util.ResourceBundle; import javax.servlet.*; //HttpServlet提供了抽象类,用于子类创建http servlet public abstract class HttpServlet extends GenericServlet { //由server(通过service方法调用)调用,用于处理get请求(也支持head请求)。使用时需要重写该方法 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //返回HttpServletRequest对象最近修改时间,时间为子1970年1月1日到现在的毫秒数。如果不知道,则返回负数 protected long getLastModified(HttpServletRequest req) {} //接收来自service方法的head请求并处理(重写只需要设置response headers) protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //由server(通过service方法调用)调用,用于处理post请求。可一次性发送无长度限制的数据 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //由server(通过service方法调用)调用,用于处理put请求。客户端可放置文件到服务器 protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //由server(通过service方法调用)调用,用于处理delete请求。用于从服务器上删除文件 protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //由server(通过service方法调用)调用,用于处理option请求 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //由server(通过service方法调用)调用,用于处理trace请求。通常用于debug protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{} //接收来自公开方法service(ServletRequest req, ServletResponse res)的请求,并分发给doXX方法处理 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) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less 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 { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // 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); } } //将请求发给protected service处理,通常该方法不需要重写 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException{} } 3.6 ServletRequest接口 ServletRequest接口定义了一个包含用户请求信息的对象给servlet的service方法。ServletRequest提供的数据包括参数名称和值、属性、输入流。接口定义如下: package javax.servlet; import java.io.*; import java.util.*; //定义了一个包含用户请求信息的对象给servlet的service方法。ServletRequest提供的数据包括参数名称和值、属性、输入流 public interface ServletRequest { //获取属性信息,没有则返回null public Object getAttribute(String name); //返回属性名称集合 public Enumeration<String> getAttributeNames(); //返回请求body的字符编码,如果没有指定则返回null public String getCharacterEncoding(); //设置请求body的字符编码,且设置必须在读取参数或读取使用getReader()操作前,否则不生效 public void setCharacterEncoding(String env) throws UnsupportedEncodingException; //返回请求body的字节长度,或者当长度不确定或超出了int的最大长度,则返回-1 public int getContentLength(); //返回请求body的字节长度,或者当长度不确定,则返回-1 public long getContentLengthLong(); //返回请求body的mine type,如果不确定,则返回null public String getContentType(); //获取请求bode的数据二进制流的ServletInputStream public ServletInputStream getInputStream() throws IOException; //返回指定参数的值,当参数有多个值时,则返回读取到的第一个值。对于请求body中的数据,则不能使用该方法,应该使用getInputStream或getReader public String getParameter(String name); //返回参数名称集合,没有则返回空集合 public Enumeration<String> getParameterNames(); //返回指定参数的值数组,没有则返回null public String[] getParameterValues(String name); //返回参数map,key为参数名称,value为参数值 public Map<String, String[]> getParameterMap(); //返回请求使用的协议版本号,如:HTTP/1.1 public String getProtocol(); //返回请求使用的schema,如:http、https、ftp public String getScheme(); //返回请求发送的服务器主机名称,即是Host头中:前面值 public String getServerName(); //返回请求发送的端口号,即是Host头中:后面的值 public int getServerPort(); //以BufferedReader方式读取请求体body中字符数据 public BufferedReader getReader() throws IOException; //返回客户端或最后一个发出请求的代理的ip public String getRemoteAddr(); 返回客户端或最后发出请求的代理的完整合规的名称 public String getRemoteHost(); //在request中设置属性 public void setAttribute(String name, Object o); //移除request中的属性 public void removeAttribute(String name); //返回客户端将接收内容的方言(如zh_CN) public Locale getLocale(); //返回客户端将接收内容的方言集合(如zh_CN、zh) public Enumeration<Locale> getLocales(); //请求是使用安全通道(如https) public boolean isSecure(); //返回RequestDispatcher对象,它作为对给定路径上资源的包装,它可用于请求重定向或在相应中包含静态或动态资源 public RequestDispatcher getRequestDispatcher(String path); //返回客户端或发请求的最后代理的端口号 public int getRemotePort(); //返回接收请求的接口的ip主机名(如:ip6-localhost) public String getLocalName(); //返回接收请求的接口的ip地址 public String getLocalAddr(); //返回接收请求的接口的端口号 public int getLocalPort(); //获取最后发出的ServletRequest的ServletContext public ServletContext getServletContext(); //将请求转为异步模式,同时初始化它的AsyncContext(包含有ServletRequest和ServletResonse),并返回AsyncContext public AsyncContext startAsync() throws IllegalStateException; public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException; //检查请求是否已经装为异步模式 public boolean isAsyncStarted(); //检查请求是否支持异步模式 public boolean isAsyncSupported(); //获取AsyncContext public AsyncContext getAsyncContext(); //返回DispatcherType(如:REQUEST) public DispatcherType getDispatcherType(); } 3.7 HttpServletRequest接口 HttpServletRequest继承自ServletRequest接口,提供了关于http servlet请求信息。接口定于如下: package javax.servlet.http; import java.io.IOException; import java.util.*; import javax.servlet.ServletException; import javax.servlet.ServletRequest; //HttpServletRequest继承自ServletRequest接口,提供了关于http servlet请求信息。 public interface HttpServletRequest extends ServletRequest { //基本验证标识符 public static final String BASIC_AUTH = "BASIC"; //表单验证标识符 public static final String FORM_AUTH = "FORM"; //客户端验证标识符 public static final String CLIENT_CERT_AUTH = "CLIENT_CERT"; //验证标识符 public static final String DIGEST_AUTH = "DIGEST"; //返回用于保护servlet的验证模式名称,值为BASIC_AUTH,FORM_AUTH, CLIENT_CERT_AUTH, DIGEST_AUTH中之一或特别指定的值,没有则返回null public String getAuthType(); //返回当前请求客户端发送的所有Cookie对象组成的数组 public Cookie[] getCookies(); //返回header值为时间的自1970年1月1日(GMT)至今的毫秒值(header如:If-Modified-Since),没有则返回-1 public long getDateHeader(String name); //返回指定header的值,没有则返回null public String getHeader(String name); //返回指定header的值集合(有些相同header有多个不同值,如Accept-Language),没有则返回null public Enumeration<String> getHeaders(String name); //返回所有header的名称集合,没有则返回null public Enumeration<String> getHeaderNames(); //以int方式获取header值,没有则返回-1 public int getIntHeader(String name); //返回请求的方法 public String getMethod(); //返回关联当前请求的额外地址信息(起于servlet地址止于参数,并以/结尾),如:servlet匹配地址为/teacher/*,请求为/teacher/one.jsp,则额外地址为/one.jsp public String getPathInfo(); //返回额外地址信息(参考getPathInfo方法)的真实资源地址 public String getPathTranslated(); //返回web应用程序的路径 public String getContextPath(); //返回在地址后的参数串 public String getQueryString(); //返回登录用户名 public String getRemoteUser(); //检查user是否在权限role中 public boolean isUserInRole(String role); //返回当前授权用户的Principal对象 public java.security.Principal getUserPrincipal(); //返回请求指定的sessionId public String getRequestedSessionId(); //返回URI地址(URL的一部分,不包含参数,如:/teacher/one.jsp) public String getRequestURI(); //返回URL地址(不包含参数部分,如:http://localhost:8080/teacher/one.jsp) public StringBuffer getRequestURL(); //返回Servlet请求地址,不包含额外地址信息(如:servlet匹配地址为/teacher/*,请求为/teacher/one.jsp,则返回为/teacher) public String getServletPath(); //返回HttpSession,参数create表示没有时是否要创建HttpSession,true:要 false:不要 public HttpSession getSession(boolean create); //返回HttpSession,若没有则直接新建一个 public HttpSession getSession(); //修改Session,创建新一个的session id public String changeSessionId(); //检测当前session是否合法 public boolean isRequestedSessionIdValid(); //检测请求的session id是否来自于cookie public boolean isRequestedSessionIdFromCookie(); //检测请求的session id是否来自于url public boolean isRequestedSessionIdFromURL(); //基于容器的安全策略授权请求的用户 public boolean authenticate(HttpServletResponse response) throws IOException,ServletException; //基于容器的登录机制验证登录 public void login(String username, String password) throws ServletException; //退出登录 public void logout() throws ServletException; //对于multipart/form-data类型,返回所有的Part集合 public Collection<Part> getParts() throws IOException, ServletException; //返回指定名称的Part public Part getPart(String name) throws IOException, ServletException; //返回HttpUpgradeHandler实例用于升级 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException; } 3.8 ServletResponse接口 ServletResponse为servlet用于响应客户端的对象,接口定义如下: package javax.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Locale; //ServletResponse为servlet用于响应客户端的对象 public interface ServletResponse { //返回相应的MIME字符编码(可通过setCharacterEncoding、setContentType、setLocale方法确定),若没有指定,则返回ISO-8859-1,参考RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt) public String getCharacterEncoding(); //返回相应的MIME body的content-type(只能通过方法setContentType设置,且在response提交之前),没有则为null public String getContentType(); //返回ServletOutputStream,适合在response中写二进制数据 public ServletOutputStream getOutputStream() throws IOException; //返回PrintWriter,能够向客户端发送文本字符,默认编码为ISO-8859-1 public PrintWriter getWriter() throws IOException; //设置response响应的字符编码,会覆盖方法setContentType或setLocale的设置,设置需在getWriter或response提交之前,否则不生效 public void setCharacterEncoding(String charset); //设置response响应内容body的长度,即是设置Content-Length的header值 public void setContentLength(int len); //设置response响应内容body的长度,即是设置Content-Length的header值(@since Servlet 3.1) public void setContentLengthLong(long len); //设置response的content type,包含内容类型和字符编码,如:text/html;charset=UTF-8 public void setContentType(String type); //设置response body的buffer大小,在实际发送内容前,更大的buffer可以写更多的内容,不过小buffer能让客户端更快收到数据 public void setBufferSize(int size); //获取response body的buffer大小 public int getBufferSize(); //强制刷新buffer,即是提交response public void flushBuffer() throws IOException; //清空buffer中的内容(不清空status code、headers) public void resetBuffer(); //检测response是否提交 public boolean isCommitted(); //清空buffer中的内容(同时清空status code、headers) public void reset(); //设置response的方言 public void setLocale(Locale loc); //获取response的方言 public Locale getLocale(); } 3.9 HttpServletResponse HttpServletResponse继承ServletResponse接口,提供在发送响应response时,提供http功能,如访问http的headers和cookies,接口定义如下: package javax.servlet.http; import java.io.IOException; import java.util.Collection; import javax.servlet.ServletResponse; //继承ServletResponse接口,提供在发送响应response时,提供http功能,如访问http的headers和cookies public interface HttpServletResponse extends ServletResponse { //添加cookie public void addCookie(Cookie cookie); //检测是否含有指定名称的header public boolean containsHeader(String name); //编码指定url(包含session id, 根据浏览器是否支持来决定session id是否放到url) public String encodeURL(String url); //编码在sendRedirect方法中的指定url(根据浏览器是否支持来决定session id是否放到url) public String encodeRedirectURL(String url); //发送错误,包含status和指定消息 public void sendError(int sc, String msg) throws IOException; //发送错误,包含status public void sendError(int sc) throws IOException; //使用指定url发送临时重定向给客户端,此时code为302。地址在发送给客户端前,servlet会将地址转为绝对地址, //地址没有以/开头,会解析为相对当前地址, //地址以一个/开头,会解析为相对servlet容器root地址, //地址以两个/(即//)开头,会解析为网络地址 public void sendRedirect(String location) throws IOException; //以date类型设置header,如果已经存在则覆盖 public void setDateHeader(String name, long date); //以date类型添加header,相同header可以存在多个值 public void addDateHeader(String name, long date); //设置header,如果已经存在则覆盖 public void setHeader(String name, String value); //添加header,相同header可以存在多个值 public void addHeader(String name, String value); //设置header,如果已经存在则覆盖 public void setIntHeader(String name, int value); //添加header,相同header可以存在多个值 public void addIntHeader(String name, int value); //设置status(当没有错误时,有错误时不生效) public void setStatus(int sc); //获取response当前status public int getStatus(); //获取response中指定名称的header(@since Servlet 3.0) public String getHeader(String name); //获取response中指定名称的header集合(@since Servlet 3.0) public Collection<String> getHeaders(String name); //获取response中的header名称集合 public Collection<String> getHeaderNames(); //后续还有响应status定义,在此略过,详情请查看源码 } 四、备注 更多基于源码的关于Servlet,在后续逐步介绍。