首页 > 代码库 > Servlet基础

Servlet基础

Servlet基础

Jsp的本质即为Servlet,jsp页面部署到web容器中后会被编译为Servlet。Servlet使用输出流输出html标签,开发过程复杂且难以进行设计。

Servlet是一个完整的java类,jsp是对Servlet的简化。Servlet中没有jsp的内置对象,jsp内置对象需要Servlet显式创建。 在MVC架构中,Servlet已不再作为视图仅仅作为控制器使用。

这里介绍了Servlet开发中所涉及的基础知识以及局部应用范例,Servlet作为控制器的应用介绍请见《Servlet作为控制器》。

1. Hello World

(1) 在IDEA中建立一个Java Enterprise项目 -> Web Application,选择Java EE版本和Sever, 然后在Src目录下建立一个新的Servlet。

 

 

技术分享
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.io.PrintWriter;

 

public class FirstServlet extends HttpServlet {

 

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

    throws IOException, ServletException

    {

        response.setContentType("text/html");

        PrintWriter out = response.getWriter();

        out.println("<html>");

        out.println("<head>");

        out.println("<title>Hello World!</title>");

        out.println("</head>");

        out.println("<body>");

        out.println("<h1>Hello World!</h1>");

        out.println("</body>");

        out.println("</html>");

    }

}

 

 protected void doPost(HttpServletRequest request, HttpServletResponse response) 

throws ServletException, IOException 

{

 

}
技术分享

 

 

 

Servlet接口定义了两个默认实现类,分别为:GenericServlet、HttpServlet。

HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。

HttpServlet在实现Servlet接口时,重写了service方法,该方法内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,在编写Servlet时,通常只需要重写doGet或doPost方法,而不要去重写service方法。此外,还可以根据需要重写doPut和doDelete方法,但这两种请求使用并不频繁。

通常,无需重写init和destory方法;若要在初始化Servlet时需要初始化某些资源(建立数据库连接),则可重写init(ServletConfig config)方法,并在重写的第一行使用 super.init(config);调用HttpServlet的init方法。注意,是重写init()方法,无需定义构造器。若要在Servlet销毁前完成某些资源的回收(如关闭数据库连接),则需重写destory方法。

 

(2)编写web.xml配置文件

IDEA会自动完成大部分配置,只需完成<servlet-mapping>配置:

 

 

技术分享
<?xml version="1.0" encoding="UTF-8"?>

<web-app 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"

           version="3.0">

 

    <servlet>

        <servlet-name>FirstServlet</servlet-name>

        <servlet-class>FirstServlet</servlet-class>

    </servlet>

    <servlet-mapping>

        <servlet-name>FirstServlet</servlet-name>

        <url-pattern>/demo</url-pattern>

    </servlet-mapping>

</web-app>

 
技术分享

 

 

 

(3) 部署到Tomcat 

将源码目录里包含index.jsp的web目录拷贝到tomcat的webapps目录下,重命名为应用的名字:servlet-demo。

在idea中编译工程后,在out目录下有编译好的.class文件, 我们将项目产出目录out\production\ServletDemo下的.class文件拷贝到webapps\WEB-INF\classes目录中。classes的目录结构必须与包一致。WEB-INF\lib目录下也可以部署.jar包。

 

(4) 启动Tomcat,在http://localhost:8080/servlet-demo/demo路径下访问Servlet

2. Servlet原理与配置

Servlet是运行于服务器端的程序,用于处理和响应客户端的请求,Servlet运行过程:

(1)装载并创建该Servlet的一个实例对象。 

(2)调用Servlet实例对象的init()方法。

(3)创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。

(4)WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。 

 

Servlet容器的创建与销毁由Web容器控制,大部分Servlet实例在客户端第一次请求Servlet时创建。另外一些Servlet在Web应用启动时创建,即load-on-startup Servlet,它们通常是提供后台服务或,或者需要拦截很多请求的Servlet。

load-on-startup可以在web.xml的<servlet>元素的<load-on-stratup>子元素中进行配置,或通过@WebServlet Annotation的loadOnStartup属性指定。它们都接受一个无符号整型值(>= 0)作为参数,表示Servlet加载的顺序,值越小越先被加载。<load-on-startup>1</load-on-startup>或@WebServlet(loadOnStartup=1) class ...。

配置Servlet

配置Servlet时还可以增加额外的配置参数。配置参数可以实现更好的可移植性,避免将配置信息写死在源代码中。为Servlet配置参数可以使用web.xml的<servlet>元素的<init-param .../>子元素来指定,或者使用@WebServlet(initParams = )来指定。

JSP内置对象的config就是ServletConfig。ServletConfig的 getInitParameter(String name)方法用于获取初始化参数。

 

使用initParams配置数据库连接池:

 

技术分享
  @WebServlet(
  initParams = {
    @WebInitParam(name = "driver", value = "http://www.mamicode.com/com.mysqi.jdbc.Driver"),
    @WebInitParam(name = "url", value = "http://www.mamicode.com/jdbc:mysqi://localhost/test"),
    @WebInitParam(name = "user", value = "http://www.mamicode.com/username"),
    @WebInitParam(name = "pass", value = "http://www.mamicode.com/passwd2333"),
  })
  class FirstServlet extends HttpServlet {
  
  public void init(ServletConfig config) {
    super.init(config);
    try {
      String driver = config.getInitParamter("driver");
      String url = config.getInitParamter("url");
      String user = config.getInitParamter("user");
      String pass = config.getInitParamter("pass");
  
      Class.forName(driver);
      Connection connect = DriverManager.getConnection(url, user, pass);
    }
    catch (Exception e) {
        e.PrintStackTrace();
    }
   }
   
}
技术分享

 

 

用Properties文件进行配置

不过更常用的方法是通过.properties文件进行配置设置。Properties类继承自Hashtable类并且实现了Map接口,是一种使用字符串键值对进行保存的属性集。

 

load(InputStream inStream)可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象。

 

技术分享
Properties pro = new Properties();

FileInputStream in = new FileInputStream("a.properties");

pro.load(in);

in.close();

 
技术分享

 

 

store(OutputStream out, String comments)将类对象的属性集写入输出流中。

 

FileOutputStream oFile = new FileOutputStream(file, "a.properties");

pro.store(oFile, "Comment");

oFile.close();

 

 

如果comments不为空,保存后的属性文件第一行会是#comments,表示注释信息;如果为空则没有注释信息。注释信息后面是属性文件的当前保存时间信息。

 

getProperty(String key)方法用于得到属性值,setProperties(String key, String value)方法则用来设置属性值。

3. 请求与响应HttpServletRequest和HttpServletReponse

HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。HttpServletRequest使用键-值对的方式封装包括请求的地址,请求的参数,提交的数据,cookie以及客户端的ip甚至客户端操作系统都包含在其内的信息。除了这些信息外,控制器在转发请求的时候可以使用setAttribute(String, Object)方法来添加/设定信息。

HttpServletresponse继承自ServletRequest,主要封装了Http响应头,cookies,状态码和响应数据。

HttpServletRequest与HttpServletResponse类都提供了一系列setter和getter方法用于设置和取得响应属性。

详细的说明见《Servlet的Request与Response》。

4. 会话管理Session与Cookie

(1) Session

session对象代表了浏览器/客户端与服务器之间的一次会话,这个过程可以是连续的也可以出现中断。实际上,HttpSession对象是一个容器,存储了会话过程中request/response对象。

当服务器端执行HttpSession session =  request.getSession();时session对象才被创建,如果JSP没有显式地使用 <% @page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这一条语句,这也是JSP中隐含的 session对象的来源。

连续一定时间服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间时session对象将会被关闭;服务器端调用HttpSession.invalidate()或服务器程序停止也会关闭session。

session对象存放在服务器端内存中,不会因为浏览器的行为(浏览器关闭,关闭网页)而关闭。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。

session对象拥有一个ID作为唯一标识,session.getId()实例方法可以得到这个ID。在session有效期间,浏览器再次发送请求时会将这个唯一标识添加到请求头中,从而继续会话。session也以键值对的方式保存属性,与request的属性不同的是在session有效期间属性一直有效。

session常用的方法包括:

public void setAttribute(String name,Object value)

以键值对的方式将属性值写入session.

public object getAttribute(String name)

取得name的属性值,如果属性不存在则返回null

public void removeAttribute(String name)

从会话中删除name属性,如果不存在不会执行,也不会抛出异常.

public Enumeration getAttributeNames()

返回和会话有关的枚举值

public void invalidate()

使会话失效,同时删除属性对象

public Boolean isNew()

用于检测当前客户是否为新的会话

public long getCreationTime()

返回会话创建时间

public long getLastAccessedTime()

返回在会话时间内web容器接收到客户最后发出的请求的时间

public int getMaxInactiveInterval()

返回在会话期间内客户请求的最长时间为秒

public void setMaxInactiveInterval(int seconds)

允许客户客户请求的最长时间

ServletContext getServletContext()

返回当前会话的上下文环境,ServletContext对象可以使Servlet与web容器进行通信

public String getId()

返回会话期间的识别号

(2)Cookie

与Session类似Cookies也是一种保存访问历史,以进行会话管理的技术(如自动登录)。Cookies是存储在客户端的文本文件,相对于Session一般具有更长的生存期。一个Cookie本身就是一个键值对,这些键值对的集合通过Cookie数组来管理。

javax.servlet.http.Cookie类封装了Cookie, Cookie[] cookies = request.getCookies();可以得到随客户端请求一同发送的cookie数组。

Cookie cookie = new Cookie(String name, String value);建立新的Cookie。response.addCookie(cookie);将其加入response中发送到客户端,更新客户端的Cookie数组。

 

Cookie提供了一系列API来进行设置:

public String getName()

实例方法,取得Cookie的名字

public String getValue()

实例方法,取得Cookie的值

public void setValue(String newValue)

实例方法,设置Cookie的值

 

public void setMaxAge(int expiry)

实例方法,获取/设置Cookie过期之前的时间,以秒计。如果不设置该值,则Cookie只在当前会话内有效,即在用户关闭浏览器之前有效,而且这些Cookie不会保存到磁盘上。若生存时间为负值,代表浏览器关闭Cookie即消失。生存时间为0,代表删除Cookie,生存时间为正数,代表Cookie存在的秒数。

public int getMaxAge()

实例方法,得到Cookie的 最大生存时间。

 

public void setPath(String uri)

设置cookie的有效路径,比如把cookie的有效路径设置为"/xdp",那么浏览器访问"xdp"目录下的web资源时,都会带上cookie,再比如把cookie的有效路径设置为"/xdp/gacl",那么浏览器只有在访问"xdp"目录下的"gacl"这个目录里面的web资源时才会带上cookie一起访问,而当访问"xdp"目录下的web资源时,浏览器是不带cookie。

public String getPath()

实例方法,得到Cookie的路径。

 

public void setDomain(String pattern)

获取/设置Cookie适用的域。一般地,Cookie只返回给与发送它的服务器名字完全相同的服务器。使用这里的方法可以指示浏览器把Cookie返回给同一域内的其他服务器。注意域必须以点开始(例如.sitename.com),非国家类的域(如.com,.edu,.gov)必须包含两个点,国家类的域(如.com.cn,.edu.uk)必须包含三个点。

public String getDomain()

实例方法,得到Cookie的适用的域。

5. 上下文Servlet Context

上下文(context)是一系列属性的集合,Servlet中存在不同作用域的上下文存储不同作用域下的属性配置。

Servlet中的上下文可以分为四级作用域:

1. PageContext-Page级上下文,JSP页面被请求时创建,请求被转发或返回response时销毁。

2. Request - 当收到客户端请求时创建,返回response时销毁。

3. SessionContext -  会话级上下文

4. ServletContext -  Web应用级上下文,可在不同Servlet之间交互

(1) ServletContext

ServletContext,是一个全局的储存信息的空间,服务器开始时被创建,服务器关闭时被销毁。ServletContext用于设置应用程序中所有Servlet共有的信息,Web容器负责提供servlet容器内ServletContext接口的实现。  由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。

ServletContext context = this.getServletContext();获取ServletContext对象

context.setAttribute(String,Object ); 设置属性

context.getAttribute("name");获得属性

removeAttribute(String name)移除属性

java.util.Enumeration<java.lang.String> getAttributeNames()

得到全部属性名

 

获取WEB应用的初始化参数:

getInitParameter(String)

 

Servlet基础