一、什么是Servlet
Servlet全称Java Servlet,是JavaWeb的三大组件(Servlet、Filter、Listener)之一。Servlet是用Java编写的服务器端程序,直白来说,一个servlet就是一个Java类,运行在 Web 服务器或应用服务器上,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层,其作用就是接收请求数据、处理请求、响应请求。
二、什么时候需要用Servlet
大致了解了Servlet是什么,那什么时候需要用Servlet呢?大家要知道,网页分为静态网页和动态网页,静态网页就是纯HTML格式设计出的网页,而动态网页是通过动态网站技术生成的网页,是基本的html语法规范与Java、VB、VC等高级程序设计语言、数据库编程等多种技术的融合,以实现对网站内容和风格的高效、动态和交互式的管理。
对于静态网页,我们只能“观赏”,“看”,而不能过多操作,而动态网页可以实现用户和网页的交互,比如我们最常碰到的登录页面,当我们把账号密码输进去的时候,Servlet接收网页传过来的账号密码数据,然后再去获取数据库中的数据,将两者核对校验,决定是否允许登录,这个过程就发生在servlet中。简言之,Servlet就用在网页需要处理数据和业务逻辑的时候。
三、浏览器访问MyServlet时序图
四、实现Servlet方式
如何实现一个Servlet?有三种方式,如下:
1、实现javax.servlet.Servlet接口
package com.iss.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyServlet implements Servlet{
public void destroy() {
// TODO Auto-generated method stub
}
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
public void init(ServletConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
2、继承javax.servlet.GenericServlet类
package com.iss.servlet;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyServlet extends GenericServlet{
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
3、继承javax.servlet.HttpServlet类
package com.iss.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
以上为实现Servlet的三种方式,常用继承javax.servlet.HttpServlet类的方式。在实现一个新的Servlet之后,我们需在项目的WebRoot目录下找到WEB-INF目录中的web.xml文件,在这个文件里配置Servlet,每创建一个servlet,就需在此文件下配置相应信息,配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>MyFirstServlet</servlet-name>
<servlet-class>com.iss.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyFirstServlet</servlet-name>
<url-pattern>/newServlet</url-pattern>
</servlet-mapping>
</web-app>
如上代码,配置一个servlet最基本的就是需要在web.xml增加一对servlet标签和一对servlet-mapping标签及标签内的内容。若想访问一个servlet,发出的请求要先去找该servlet的访问路径url-pattern,通过url-pattern的内容找到servlet-name的内容,再根据此servlet-name的内容找到了servlet标签下的servlet-class的内容即想访问的Servlet路径。
举个例子:想在浏览器找到上边代码中的MyServlet,在浏览器输入“http://localhost:8080/web02/newServlet”,其中web02是项目名。
注:在配置servlet时,有一个配置servlet启动时加载的操作load-on-startup,servlet启动时加载是说servlet正常是当有访问时才开始实例化servlet对象,通过load-on-startup,我们可以让Tomcat等服务器在启动时就可以实例化对应的servlet对象,如下代码:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.iss.servlet.MyServlet</servlet-class>
<!-- 里面的数字从0~7,数字越小,优先级越高 -->
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
五、Servlet的生命周期
Servlet的生命周期指的是一个对象从创建到销毁的过程,具体如下:
对象创建:调用默认的无参构造器(只调用一次)
对象初始化:调用void init(ServletConfig arg0)方法(只调用一次)
提供服务:调用service(ServletRequest arg0,ServletResponse arg1)方法(每次响应客户的请求都会调用)
对象销毁:void destroy()临死前调用一次
特点:
Servlet对象是单例的,一个类只有一个对象,但可以有很多个不同的Servlet类;
Servlet是线程不安全的,多个线程访问同一个Servlet对象时要避免线程安全问题的,方法不要使用全局变量,也就是避免多个线程对同一个资源进行操作,使用局部变量可以解决。
六、如何理解ServletContext和ServletConfig
1、ServletContext:用于保存全局性数据和信息,一个web项目只有一个ServletContext对象,当一个项目在服务器中启动时,服务器会自动为该项目创建一个ServletContext对象,它保存着一个项目中所有servlet的信息,当服务器关闭或者项目从服务器中移除时,ServletContext自动销毁。一些常见方法如下:
getServletContext():获取该项目的ServletContext
void setAttribute(String name,Object value); 设置某个属性值
Object getAttribute(String name); 获取某个属性
void removeAttribute(String name); 删除某个属性
2、ServletConfig:存储相应servlet的配置信息,每一个servlet对象都有一个ServletConfig对象,一对一的关系。
3、两者区别
每一个项目对应一个唯一的ServletContext,包含项目所有servlet的内容;每一个servlet对应一个唯一的ServletConfig,包含该servlet的所有配置信息,类似于全局变量和局部变量的概念,作用域不一样。
4、案例(统计网站被登录的总次数)
此案例用到了上边所说的ServletContext存储全局性数据的概念,将登陆次数保存在ServletContext对象中(key,value),每登录一次,将登录次数加一
package com.iss.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
Object num = servletContext.getAttribute("count");
int count = num==null?1:((Integer)num+1);
servletContext.setAttribute("count", count);
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("你是第"+count+"个访问此网站的用户");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}