1.Servlet的定义
servlet(server applet) 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序)。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
更多的是配合动态资源来做。 当然静态资源也需要使用到servlet,只不过是Tomcat里面已经定义好了一个 DefaultServlet
tomcat是servlet的一个容器
访问静态还是动态都是要servlet的
2.servlet的简易访问模型
上面的是静态资源,直接访问的,而servlet先拿到服务器的请求,分析请求后处理把结果从库里取出来翻译成html代码(静态资源)在发送给客户端
3.Servlet入门实例
step1. 创建一个动态JavaWeb项目,src目录下创建一个servlet类-----HelloServlet,实现接口 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 HelloServlet implements Servlet{ //只被调用一次,第一次请求Servlet时,创建Servlet的实例,调用构造器 public HelloServlet() { System.out.println("构造器 HelloServelt()..."); } //该方法用于初始化Servlet,就是把该Servlet装载入内存 //只被调用一次,在创建好实例后立即被调用 @Override public void init(ServletConfig config) throws ServletException { System.out.println("初始化方法 init()..."); } //被多次调用,每次请求都会调用service方法。实际用于响应请求的 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("执行方法主体 service()..."); } //只被调用一次,在当前Servlet所在的WEB应用被卸载前调用,用于释放当前Servlet所占用的资源 @Override public void destroy() { System.out.println("servlet 销毁时调用方法 destroy()..."); } @Override//可以先忽略,不常用 public ServletConfig getServletConfig() { return null; } @Override//可以先忽略不常用 public String getServletInfo() { return null; } }
快捷键的使用ctrl+1添加未实现的方法
web.xml中ctrl选中全限定名就会自动跳转到HelloServlet里
step2.在 web.xml 文件中配置上面创建的 HelloServlet 映射关系(给servlet这个动态资源一个访问路径,才可以访问)
<!--给创建的 Servlet 配置映射关系 -->
<!注册servlet到项目中 -->
<servlet>
<!--servlet-name给要注册的servlet起名字,与类名一样最好 -->
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.ys.servlet.HelloServlet</servlet-class>
<!--servlet的完整名称-->
</servlet>
<servlet-mapping>
<!--当前那个servlet分配路径,与上面的那个name是有区别 -->
<servlet-name>helloServlet</servlet-name>
<!-- 与上面配置的 servlet-name 名字要对应,一个servlet可以有多个 servlet-mapping -->
<url-pattern>/hello</url-pattern>
<!--访问路径(相对于项目的路径)-->
</servlet-mapping>
step3.把项目部署到tomcat上
右键->Add an的Remove->选择HelloServlet->finish
启动tomcat
输入访问路径http://localhost/HelloServlet/hello
4.Servlet生命周期
我们通过上面的实例,可以看到也就是只有第一次才会执行 构造器和 init() 方法,后面每次点击都只调用 service() 方法。那这是为什么呢?
上面这幅图可以这样理解:
1、客户端向 Web 服务器发送请求,服务器查询 web.xml 文件配置。根据请求信息找到对应的 Servlet。
2、Servlet 引擎检查是否已经装载并创建了该 Servlet 的实例对象,如果有,则直接执行Y,否则执行N,
3、Web 服务器加载 Servlet,并调用 Servlet 构造器(只会调用一次),创建 Servlet 的实例对象。并调用 init() 方法,完成 Servlet 实例对象的初始化(只会调用一次)。
4、Web 服务器把接收到的 http 请求封装成 ServletRequest 对象,并创建一个 响应消息的 ServletResponse 对象,作为 service() 方法的参数传入。(每一次访问都会调用一次该方法)
5、执行 service() 方法,并将处理信息封装到 ServletResponse 对象中返回
6、浏览器拆除 ServletResponse 对象,形成 http 响应格式,返回给客户端。
7、Web 应用程序停止或者重新启动之前,Servlet 引擎将卸载 Servlet实例,并在卸载之前调用 destory() 方法
5.tomcat容器等级
6.servlet相关对象-servletconfig(接口)
在Servlet 的配置文件中,可以用一个或多个<init-param>标签为servlet配置一些初始化参数。
当servlet配置了初始化参数之后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给Servlet。进而,程序员通过Servlet对象得到当前servlet的初始化参数信息。
获取ServletConfig中初始化信息步骤:
1 . 创建私有变量:
private ServletConfig config = null;(扩大作用域,原来的只是作为参数传递,通过全局变量就最终可以返回这个对象)
2、重写init方法,令 this.config = config,从而获取ServletConfig对象
3、获取<init-param>中的配置信息
/获取初始化参数 String value1 = this.config.getInitParameter("x1"); //获得配置文档中<inti-param>标签下name对应的value String value2 = this.config.getInitParameter("x2"); //获取所有初始化参数 Enumeration e = this.config.getInitParameterNames(); while(e.hasMoreElements()){ String name = (String) e.nextElement(); String value = this.config.getInitParameter(name); System.out.println(name+"="+value); }
4、开发中ServletConfig的作用有:
获取字符集编码:
String charset = this.config.getInitParameter("charset");
获得数据库连接信息:
String url = this.config.getInitParameter("url"); String username = this.config.getInitParameter("username"); String password = this.config.getInitParameter("password");
获得配置文件:
String configFile = this.config.getInitParameter("config");
7.GenericServlet讲解(优化了解)
实现了Servlet接口,并帮我们做了一些常用操作
1.init方法 妥善的保存config对象并实现getServletInfo,getServletConfig,
2.增加一个空参init方法,供开发人员初始化,为了防止开发人员重写 原生init方法
3.service方法空实现=> 声明成抽象(强制开发人员实现该方法)
4.destory方法空实现
5.实现了servletConfig接口. 接口中的方法直接调用config实现类实现.
public abstract class Genericservlet implements servlet,implements servletconfig{
................................................
}
目的:不实现接口,而是继承GenericServlet这个类,从而达到优化。
其中的service()方法:接受请求处理响应。
这个方法是用户自己实现的,所以定义为抽象方法
比如说在service方法中获取servletconfig信息:
但如果想要省略getServletConfig这一步骤
只需要在父类中
但这样还不如直接在父类实现Servletconfig接口
此外,如果想要实现在子类中调用init()方法,但重写父类的init()方法会导致父类的init()用不成
this.config=confg就会用不上
这个函数也就用不上,从而实现的servletconfig接口的方法就会用不上
public Servletconfig getServletConfig()
{
return config;}
怎末办呢
在父类的init()方法中调用this.init();
然后实现
public void init()
{
}这样服务器在初始化的时候就会调用inti()方法,在里面又会调用空参的init(),这两个就绑定了,然后在子类中重写inti()方法。这样this.config=arg0就会起作用。
8.HttpServlet(优化plus)
servlet在最初设计的时候是想兼容所有协议的,ServletRequest中的requset对象算是一个父类
比如上面的servlet是想兼容所有请求的,所以把他们的共同特点抽取出来为一个接口servletRequest
但最常用的是第一个,http是子类,所以他的方法更多,全程HttpServletRequest
优化1,我们开发的项目都是基于http协议,而且传过来的servletRequset实际就是HttpServletRequest
强转request和response==》http
优化二:根据请求方式不同(所有请求方式有7中,但常用的get和post两种),调用不通的方法,一个servlet两用
继续继承Mygnericservlet
在service中
9 .Severlet创建的三个方法
有了上面的讲解,这下实现servlet的三个方法会更容易理解
方式一
实现javax.servlet.Servlet接口
就是我们上面写的 实现接口 Servlet
方式二 :继承javax.servet.GenericServlet类(适配器模式)
由于实现接口我们需要实现里面所有的方法,里面有一些方法我们可能并不想实现,那么我们就继承 GenericServlet 类
import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet extends GenericServlet{ //只被调用一次,第一次请求Servlet时,创建Servlet的实例,调用构造器 public HelloServlet() { System.out.println("构造器 HelloServelt()..."); } //该方法用于初始化Servlet,就是把该Servlet装载入内存 //只被调用一次,在创建好实例后立即被调用 @Override public void init(ServletConfig config) throws ServletException { System.out.println("初始化方法 init()..."); } //被多次调用,每次请求都会调用service方法。实际用于响应请求的 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("执行方法主体 service()..."); } //只被调用一次,在当前Servlet所在的WEB应用被卸载前调用,用于释放当前Servlet所占用的资源 @Override public void destroy() { System.out.println("servlet 销毁时调用方法 destroy()..."); } }
方式三 (常用)
继承javax.servlet.http.HttpServlet类(模板方法设计模式)
import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloServlet extends HttpServlet{ //只被调用一次,第一次请求Servlet时,创建Servlet的实例,调用构造器 public HelloServlet() { System.out.println("构造器 HelloServelt()..."); } //该方法用于初始化Servlet,就是把该Servlet装载入内存 //只被调用一次,在创建好实例后立即被调用 @Override public void init(ServletConfig config) throws ServletException { System.out.println("初始化方法 init()..."); } //处理 post 请求 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } //处理get请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } //只被调用一次,在当前Servlet所在的WEB应用被卸载前调用,用于释放当前Servlet所占用的资源 @Override public void destroy() { System.out.println("servlet 销毁时调用方法 destroy()..."); } }
其实上面三种方法,后面两种都是对 Servlet 类的封装,我们可以看 API,其实 HttpServlet 是继承 GenericServlet的。
而 GenericServlet 又是实现 Servlet 接口的
10.Servlet的线程安全
所谓的线程安全问题就是多线程访问共享资源的问题
我们通过 Servlet 的生命周期可以知道,Servlet 类的构造器只会在第一次访问的时候调用,后面的请求都不会再重新创建 Servlet 实例。即 Servlet 是单例,那么既然是单例的,那就要注意多线程访问所造成的安全问题。如下:
import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet extends GenericServlet{ //多线程共享资源 private int i = 0; public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { i++; //为了使多线程访问安全问题更加突出,我们增加一个延时程序 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } }
我们用两个浏览器,输入 http://localhost:8080/HelloServlet/hello,然后一起访问,不断刷新,结果如下:
结果分析:显然,我们用两个浏览器访问,便相当于两个线程,第一个访问,已经执行了 i++,但是还没来得及打印 i 的值,就马上就睡眠了;接着第二个浏览也来访问,执行 i++,那么i的值相当于增加加了两次1,然后这两个浏览器输出最终结果。这便造成了多线程访问共享资源造成冲突。
那么在 Servlet 中如何处理呢?
第一种方法:使用同步代码块(不推荐)
import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet extends GenericServlet{ //多线程共享资源 private int i = 0; public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { synchronized (this) { i++; //为了使多线程访问安全问题更加突出,我们增加一个延时程序 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } } }
分析:这种办法虽然能解决多线程同步问题,但是如果 延时程序特别长,那么会造成访问假死的现象。即第一个线程访问结果没有出来,第二个线程就会一直卡死,出不来结果
第二种办法:实现接口 SingleThreadModel(不推荐)
import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.SingleThreadModel; public class HelloServlet extends GenericServlet implements SingleThreadModel{ //多线程共享资源 private int i = 0; public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { i++; //为了使多线程访问安全问题更加突出,我们增加一个延时程序 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } }
分析:SingleThreadModel 接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。但是,如果一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销,在现在的Servlet开发中基本看不到SingleThreadModel的使用,这种方式了解即可,尽量避免使用。就相当于每次来一个浏览器请求的时候就会创建一个实例,
继承这个SingleThreadModel后,tomcat中就会出现栈这样的一个结构,加入第三请求进来了访问Aservlet,服务器会先访问栈,看有,就把他拿过来用完后在放回去,访问的二手servlet,并不可以解决实际问题,第四个进来访问Aservlet时它还被占用的话它就会在创建一个servlet,这样引起大量开销。
第三种办法:避免使用实例变量(推荐)使用局部变量,但生命周期短,用完就销毁
线程安全问题很大一部分是由于实例变量造成的,那么我们只要在 Servlet 里面不定义任何的实例变量,那么就不会有线程安全的问题。因为在 Java 内存模型中,方法中的临时变量是在栈上分配空间,而且每个线程都有自己的私有栈空间,不会造成线程安全问题。
import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet extends GenericServlet{ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { int i = 0; i++; //为了使多线程访问安全问题更加突出,我们增加一个延时程序 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } }
11.servlet中的细节问题
1.load-on-startup的使用
修改servlet的初始化时机
使用方法:在wen.xml中添加
<load-on-startup> 0 </load-on-startup>
其中填写整数,数字越小优先级越高
2.路径的写法:
1.相对路径<url-pattern>/hello</url-pattern>
2.后缀名匹配*.do
<url-pattern>*.do</url-pattern>
http://localhost:8081/HelloServlet/abc.do照样可以访问。
3.defaultservlet
当我们的项目处理不了请求的时候,服务器里面defaultservlet来处理.
404....
12.相关对象-ServletContext对象
1.定义
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。
这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
通过servletconfig中===》》》getServletContext获得
2.作用
一.封装了web.xml中的配置
实现步骤:
1.在web.xml中配置全局参数
<context-param> <param-name>param1</param-name> <param-value>value1</param-value> </context-param> <context-param> <param-name>param2</param-name> <param-value>value2</param-value> </context-param>
2. 在动态资源servlet里面使用servletcontext读取全局参数代码
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用servletContext读取全局配置参数数据 //核心方法 /*getServletContext().getInitParameter(name);//根据指定的参数名获取参数值 getServletContext().getInitParameterNames();//获取所有参数名称列表*/ //打印所有参数 //1.先获取所有全局配置参数名称 Enumeration<String> enumeration = getServletContext().getInitParameterNames(); //2.遍历迭代器 while(enumeration.hasMoreElements()){ //获取每个元素的参数名字 String parameName = enumeration.nextElement(); //根据参数名字获取参数值 String parameValue = getServletContext().getInitParameter(parameName); //打印 System.out.println(parameName+"="+parameValue); } }
2.servlet技术中三大域对象之一
在域对象中的作用
ServletContext对应着Application应用域
利用了一个项目中只有一个ServletContext的特点,在ServletContext中放置了一个map用作数据通信
这个Map就是所谓域。
关于域操作有四个
setAttribute
getAttribute
removeAttribute
getAttributeNames
以后的域中都会有着四个属性
演示1:Aservlet和BServlet之间的通信表白,如何通信呢===》静态变量
Constant类
public class constant { //静态变量随着类的加载而加载,而且在jvm中只加载一次 public static String str; }
Aservlet继承httpServlet
在doget方法中
Constant.str="i love you ";
Bservlet中继承httpServlet
在doget方法中
String str=constant.str; reponse.getWriter.str();
演示2:使用servletContext完成通信
在Aservlet中
//1.获得ServletContext域对象 ServletContext sc=getServletContext(); //2.操作map sc.setAttribute("bag","CK");
在Bservlet中
//.获得ServletContext域对象 ServletContext sc=getServletContext(); //操作map String bag =(String) sc.getAttribute("bag"); //输出到客户端 response.getWriter().print(bag);
3.获取项目资源
1.getServletContext().getRealPath(path),根据相对路径获取服务器上资源的绝对路径
假如获取xxx,xml的信息
/ ====>代表项目根目录下
webROOT下
里面的path写==》/WEB-INF/xxx.xml等
如果放在src写,因为里面放的是java文件
eclispe是不会编译的,但会把编译好的java文件放在classes下
所以path==>?WEB-INF/classes/xxx.xml
2.getServletContext().getResourceAsStream(path),根据相对路径获取服务器上资源的输入字节流
3.
getServletContext().getContextPath();
作用:获取当前工程名字
4.通过类加载器获取文件的路径(处于classes目录下的文件)
类.class.getClassLoader().getReource("文件路径").getPath()
类.class.getClassLoader().getReourceAsStream("文件路径")
3.servlet技术中对象的范围
servlet==>项目启动期间只有一个servlet
request==>项目启动期间,他的数量取决于请求的数量
response==>同上
servletConfig==>一个servlet实例对应一个servletConfig对象
servletContext==>整个项目只有一个实例存在
4. 获取中文数据
> 客户端提交数据给服务器端,如果数据中带有中文的话,有可能会出现乱码情况,那么可以参照以下方法解决。
* 如果是GET方式
1. 代码转码
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("userName="+username+"==password="+password);
//get请求过来的数据,在url地址栏上就已经经过编码了,所以我们取到的就是乱码,
//tomcat收到了这批数据,getParameter 默认使用ISO-8859-1去解码
//先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串
username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
System.out.println("userName="+username+"==password="+password);
直接在tomcat里面做配置,以后get请求过来的数据永远都是用UTF-8编码。
2. 可以在tomcat里面做设置处理 conf/server.xml 加上URIEncoding="utf-8"
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
* 如果是POST方式这个说的是设置请求体里面的文字编码。 get方式,用这行,有用吗? ---> 没用
request.setCharacterEncoding("UTF-8");
这行设置一定要写在getParameter之前。
13.案例一:
案例应用实现步骤分析
- 步骤一:设计一个登录页面.
- 步骤二:在登录页面上点击登录按钮.提交到Servlet.
- 步骤三:编写Servlet.在Servlet中接收参数.
- 步骤四:调用业务层去数据库进行查询.
- 步骤五:根据处理结果作出响应.
代码实现:
- 引入jar包(mysql,c3p0,dbutils)
- 创建包和类
- 创建一个工具类JDBCUtils
- 编写Servlet,Service,DAO
web项目思路整理
(Html—Servlet—Service—Dao)
- HTML
请求触发
页面加载时触发
$(function(){Ajax请求})
为指定元素加载事件时触发
$(“元素选择器”).事件名称(function(){Ajax请求})
请求格式
$.请求方式(“请求路径”,{属性名:属性值...},function(data){回调函数},响应值类型)
请求方式主要为get和post两种,区别在主要目的为提交还是获得数据
响应数据类型一般为json,可以省略
写入数据
数据获取
data.xx data对象中需含有getXx方法
数据写入
$("元素选择器").html("html标签语句") 语句中通过字符串拼接写入获取的数据
- Servlet
接收请求参数
设置获取请求数据的格式
request.setCharacterEncoding("utf-8"); 可以编写过滤器设置项目中所有Servlet的请求数据的格式
获取参数,根据参数的数量及需要调用的方法决定是否封装为对象
创建Service对象,调用Service中的方法处理数据设置响应数据类型并回写数据
resp.setContentType("application/json;charset=utf-8"); 设置响应格式
objectMapper.writeValue(writer,obj)/objectMapper.writeValueAsString(obj)
使用ObjectMapper将数据转换为json格式,根据需要使用字符流或者字节流回写数据
- Service
对传入的数据进行处理
创建Dao对象,调用Dao中的方法查询或修改数据库中的数据
核心逻辑编写
根据不同的情况将处理好的数据封装成对象返回给Servlet层
- Dao
编写SQL语句查询或修改数据库中的数据,根据需求封装成对象或者集合并返回给Service层
- 核心思路
HTML负责发送请求数据和接收响应数据
Servlet负责接受请求数据和回写响应数据,进行一些简单的逻辑判断确定回写的数据
Service负责核心逻辑的编写及对数据的处理和封装
Dao负责对数据库数据的查询和修改
案例二:
需求
网站登录成功后,隔5秒钟页面自动跳转到成功的页面.
技术分析
Refresh的响应头
HttpServletResponse的操作响应头的方法:
* addHeader(String name,String value); --针对一个key对应多个value头的设置
* addDateHeader(String name,long value);
* addIntHeader(String name,int value);
* setHeader(String name,String value); --针对一个key对应一个value
* setDateHeader(String name,long value);
* setIntHeader(String name,int value);
步骤分析:
步骤一:在登录成功后的代码的地方设置响应头
步骤二:编写一个成功后的跳转的页面.
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>登录成功!页面将在5秒后跳转</h1>");
response.setHeader("Refresh", "5;url=/WEB09/loginSucc.html");
补充:
可以通过html页面中的一个标签设置头信息<meta>标签.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Refresh" content="5;url=/WEB09/succ.html">
<script type="text/javascript" src="/WEB09/js/jquery-1.11.3.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
$(function(){
setInterval("changeTime()", 1000);
});
var i = 5;
function changeTime(){
// 获得id为s1的元素:
i--;
$("#s1").html(i);
}
</script>
</head>
<body>
<h1>登录成功!!!页面将在<span id="s1">5</span>秒后跳转!</h1>
</body>
</html>
案例三:统计一下网站被登录的总次数
技术分析
【ServletContext*****】
ServletContext :Servlet中全部的内容ServletContext都了解.一个WEB应用只有一个ServletContext对象.服务器启动的时候,服务器为每个WEB工程创建一个属于自己项目的ServletContext对象.服务器关闭的时候或者项目从服务器中移除ServletContext才会被销毁.如果将值保存在ServletContext中.值就有一个作用的范围.所以这个对象称为”域对象”.
* 保存全局性信息和数据:
* 网站的访问次数:
* 聊天室:
* 在Servlet中获得ServletContext:
* ServletContext getServletContext();
* 操作这个对象的方法:
* void setAttribute(String name,Object value);
* Object getAttribute(String name);
* void removeAttribute(String name);
步骤分析:
步骤一:编写一个Servlet中的init方法.在init方法中初始化一个被登录次数0.将这个值存入到ServletContext域中.配置Servlet的load-on-startup.
步骤二:在登录成功代码中获得原来的次数+1.存回到ServletContext域中.
步骤三:在5秒后跳转的Servlet中,从ServletContext域中获得次数,并且显示到页面上.
代码实现:
配置SErvlet为启动时加载:
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.itheima.servlet.demo2.UserServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
在Servlet的init方法中初始化次数为0
@Override
public void init() throws ServletException {
// super.init();
// 获得ServletContext对象.初始化一个值为0.
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("count", 0);
}
在登录成功的代码中获得原来的次数并且+1,存回到SErvletContext域中。
// 登录成功的时候 获得原来的次数 + 1
Integer count = (Integer) this.getServletContext().getAttribute("count");
// 存回到ServletContext域中
this.getServletContext().setAttribute("count", ++count);
在CountServlet中获得次数并且显示:
response.setContentType("text/html;charset=UTF-8");
// 获得次数:
Integer count = (Integer) this.getServletContext().getAttribute("count");
response.getWriter().println("<h1>您是第"+count+"位登录成功的用户!</h1>");