目录
一、servlet概念及相关接口简介
1.1、什么是servlet?
1.2、什么是Servlet容器
1.3、 相关接口
1.4、servet 执行过程
1. 4.1、 编写一个servlet继承HttpServlet类
1.4.2、重写doGet()和doPost()方法
1.4.3、把servlet程序交给Tomcat运行
1.4.4、 访问URL : http://localhost:8082/project06/Demo01
1.5、servlet路径映射
1.5.1、匹配ur-pattern
1.5.2、注意
1.6、缺省servlet
二、servlet生命周期(重点)
2.1、servlet生命周期的四个重要方法
2.2、伪代码演示servlet生命周期
三、Servlet自动加载
四、Servlet线程安全
五、servletConfig对象
5.1、作用
5.2、创建与获得
5.3、servlet初始化参数配置
六、ServletContext对象
6.1、创建于得到Context
6.2、自己可以这样设计设计
6.3、Sun公司设计
6.4、ServletContext对象的核心API(作用)
七、所有域对象
7.1、转发
7.2、重定向
7.3、转发
基于Java技术的web组件,基于java与第三方平台的无关类,是 Spring MVC、Struts、WebWork、SiteMesh等框架的基础,
一般被web服务器编译、加载,运行,生成动态资源的内容
如何开发一个servlet
步骤
new = > servlet类
servlet程序的class码拷贝的WEB-INF/classes目录部署项目
配置web.xml文件
ServletDemo01
cn.itcase.servlet.ServletDemo01
ServletDemo01
/Demo01
前提条件:必须启动Tomcat服务器,首先加载webapps下的web.xml文件
http:// http协议:浏览器与服务器之间的数据传输规范
localhost:访问本地文件 在本地的hosts文件中查找是否存在该域名对应的IP地址 127.0.0.1
8082:Tomcat的端口号
/project06:到webapps下查找project06的项目
/Demo01:资源名称(URI)
1. 在project06的web.xml中查找是否有匹配的url-pattern的内容(/Demo01)
2.如果匹配到了url-pattern,则使用当前的servlet-name的名称到web.xml文件中查询是否有相同的servlet配置
3.如果找到,则取出对应的servlet配置信息中的servlet-class内容:
ServletDemo01
/Demo01
|
匹配url-name |
浏览器输入 |
精准匹配(完整的url地址) |
/ServletDemo01 |
http://localhost:8082/project06/ServletDemo01 |
/itcase/Demo01 |
http://localhost:8082/project06/itcase/Demo01 |
|
模糊匹配 |
/* |
http://localhost:8082/project06/任意路径 |
/itcast/* |
http://localhost:8082/day10/itcast/任意路径 |
|
*.后缀名 http://localhost:8082/project06/任意路径.do *.action http://localhost:8082/project06/任意路径.action *.html(伪静态) |
1.url-pattern要么以 /开头,要么以*开头
2.不能同时使用两种模糊匹配 /itcase/*.html
3.当输入的url有多个servlet匹配时
精确匹配优先
以后缀名结尾的模糊url-pattern优先级最低
servlet省略路径 格式:
servlet省略路径是Tomcat内置的一个路径该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件
浏览器输入(URL) http://localhost:8080/day10/index.html 如何读取资源
1. 到当前project06应用下的web.xml文件查找是否有匹配的url-pattern
2.如果没有匹配的url-pattern,则交给tomcat的内置的DefaultServlet处理
3.DefaultServlet程序到project06应用的根目录下查找是存在一个名称为index.html的静态文件。
4.如果找到该文件,则读取该文件内容,返回给浏览器
5.如果找不到该文件,则返回404错误页面
总结:先找动态资源在找静态资源
servlet的生命周期:什么时候创建,什么时候调用什么方法,什么时候销毁
servelt生命周期由serlvet容器控制(Tomcat)
package cn.itcase.test;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
public class FlistServlet extends HttpServlet {
/*
* 1.构造方法
* 创建对象的时候调用
* 默认情况下第一次访问servlet时候创建servlet对象 只调用1次
* 证明servlet在Tomcat(servlet容器)是单实例
*
* 单实例:一个对象的实例,在一个应用生命周期中只生成一次,所有的请求(方法调用)都由这个实例处理
* 多实例:一个对象在应用里生成多个实例,所有的请求可能有不同的实例进行处理
*
* 实例:就是某个类的一个对象 类是抽象的,对象是实在的,所以叫实例
* 实例变量 也叫 成员变量 、实例域、实例字段
* 实例方法 也叫 成员方法
*
*
*
* */
public FlistServlet(){
System.out.println("1.创建servlet对象");
}
/*2.init()方法
* 创建完servlet对象后调用,只调用一次
*
* */
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("2.init()方法被调用");
}
/*3.service()方法
* 每次发送请求时调用 调用n次
*/
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
System.out.println("3.service方法被调用");
}
/*4.destory()方法
* 销毁servlet对象的时候调用 。停止服务器或者重新部署web应用时销毁servlet对象
* 只调用一次
*
*/
@Override
public void destroy() {
System.out.println("4.destory()方法被调用");
}
}
tomcat内部代码运行:
1.通过映射找到servlet-class内容:(字符串)cn.itcase.FilstServlet
2.通过反射构造FilstServlet对象
2.1 得到字节码对象
Class clazz = class.forName("cn.itcase.FilstServlet");
2.2调用无参数的构造方法来构造对象
Object bjo =clazz.newInstance(); 1.servelt的构造方法被调用
3.创建ServletConfig对象,通过反射调用init()方法
3.1得到方法对象
Method m = clazz.getDeclareMehtod("init",ServletConfig.class);
3.2 调用方法
m.invoke(obj,config); 2.servlet的init方法被调用
4.创建request。response对象,通过反射调用service方法
4.1得到方法对象
method m = clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
4.2调用方法
m.invoke(obj,request,response); 3.servlet的service方法被调用
5.当tomcat服务器停止或web应用重新部署,通过放射调用destroy方法
5.1得到方法对象
Method m = clazz.getDeclareMethod("destroy",null);
5.2调用方法
m.invoke(obj,null); 4.servlet的destory方法被调用
默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢
把servlet创建对象提前到加载web应用
在servlet的配置信息中,加上一个
FlistDemo01
cn.itcast.FilstDemo01
1 注意: 整数值越大,创建优先级越低!!
有参数与无参数的init方法
有参数的init方法: 该方法是servlet的生命周期方法,一定会被tomcat服务器调用
无参数的init方法:该方法是servlet的编写初始化代码的方法。是Sun公司设计出来专门给开发者进行覆盖,然后在里面编写servlet的初始逻辑代码的方法。
注意:如果要编写初始代码,不需要覆盖有参数的init方法
servlet对象在tomcat服务器是单实例多线程的。
因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。
解决办法:
1.把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)
2.建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里),以避免因为同步而导致并发效率降低。
package cn.itcase.thread;
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 ThreadDemo extends HttpServlet {
static int count = 1; //成员变量 共享信息
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html;charest=utf-8");
synchronized(ThreadDemo.class){//锁对象必须唯一,建议使用该类字节码对象
resp.getWriter().write("您现在是当前网站的第:"+ count + "个访客");
count++;
}
}
}
Servlet学习:
HttpServletRequest 请求对象:获取请求信息
HttpServletResponse 响应对象: 设置响应对象
ServletConfig对象 servlet配置对象
ServletContext对象; servlet的上下文对象
ServletConfig对象: 主要是用于加载servlet的初始化参数。在一个web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)
创建时机: 在创建完servlet对象之后,在调用init方法之前创建
得到对象: 直接从有参数的init方法中得到
ConfigDemo
cn.itcase.config.ConfigDemo
path
D:\a.txt
package cn.itcase.config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值
java.util.Enumeration getInitParameterNames() 获取所有参数
ServletContext getServletContext() 得到servlet上下文对象
java.lang.String getServletName() 得到servlet的名称
* */
public class ConfigDemo extends HttpServlet {
/*
* tomcat服务器把这些参数会在加载web应用的时候, 封装到ServletConfig对象中
*
* tomcat服务器调用init方法传入ServletConfig对象 private ServletConfig config;
*
* @Override public void init(ServletConfig config) throws ServletException
* { this.config = config; //引用父类成员变量 }
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//编码格式
response.setContentType("text/html");
//输出
PrintWriter out = response.getWriter();
//根据参数名获取参数值
String path = this.getServletConfig().getInitParameter("path");
File file = new File(path);
// 读取内容
BufferedReader br = new BufferedReader(new FileReader(file));
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
// 查询当前servlet的所有初始化参数
Enumeration enums = this.getServletConfig()
.getInitParameterNames();
while (enums.hasMoreElements()) {
String paramName = enums.nextElement();
String paramValue = this.getServletConfig().getInitParameter(
paramName);
System.out.println(paramName + "=" + paramValue);
}
//得到servlet名称
String servletName = this.getServletConfig().getServletName();
System.out.println(servletName);
}
}
ServletContext对象 ,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一 个ServletContext对象
创建时机:加载web应用时创建ServletContext对象。
得到对象: 从ServletConfig对象的getServletContext方法得到
创建ServletConfig对象
public void init( ServletConfig config,ServletContext context ){ 多了一个参数
得到ServletConfig对象
得到ServletContext对象;
}
package cn.itcase.content;
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 ContextDemo03 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
//1.获得文本域对象
ServletContext context = this.getServletContext();
//2.把数据保存到域对象中
context.setAttribute("student", new Student("jack",20));
}
}
class Student{
private String Name;
private int Age;
public Student(String Name, int Age) {
super();
this.Name = Name;
this.Age = Age;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
@Override
public String toString() {
return "student [Name=" + Name + ", Age=" + Age + "]";
}
}
package cn.itcase.content;
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;
/*
1.创建ServletContext对象 ServletContext context = new ServletContext()
2. 创建ServletConfig对象 ServetConfig config = new ServletConfig();
config.setServletContxt(context);
lass ServletConfig{
ServletContext context;
public ServletContext getServletContxt(){
return contxt;
}
}
public void init( ServletConfig config ){
得到ServletConfig对象
从ServletConfig对象中得到ServletContext对象
SerlvetContext context = config.getServletContext();
}
*/
public class ContextDemo04 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
// 1.得到域对象 域对象可以理解为web.xml文件
ServletContext context = this.getServletContext();
// 2.从域对象中取出数据
Student student = (Student) context.getAttribute("student");
System.out.println(student);
}
}
package cn.itcase.content;
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;
/*java.lang.String getContextPath() --得到当前web应用的路径
java.lang.String getInitParameter(java.lang.String name) --得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) --域对象有关的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(类似于重定向)
java.lang.String getRealPath(java.lang.String path) --得到web应用的资源文件
java.io.InputStream getResourceAsStream(java.lang.String path) */
public class Demo01 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
//1.得到servletContext(对象域)的几种方式
//方式一:
//ServletContext context = this.getServletConfig().getServletContext();
//方式二:推荐使用这种方式
ServletContext context = this.getServletContext();
//2.得到web应用路径 project02
String contextPath = context.getContextPath();
System.out.println(contextPath);
//3.案例:应用请求重定向
response.sendRedirect(contextPath + "/index.html");
}
}
域对象:作用是用于保存数据,获取数据。可以在不同的动态资源之间共享数据
注意:servletContext域对象:作用范围在整个web应用中有效
HttpServletRequet 域对象 ServletContext域对象 HttpSession 域对象 PageContext域对象
RequestDispatcher getRequestDispatcher(java.lang.String path)
package cn.itcase.forwrad;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo02 extends HttpServlet {
/*
重定向
1.地址栏会改变,变成重定向到地址。
2.重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站。
3.不能再重定向的过程,把数据保存到request中。
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//保存数据到request域对象
request.setAttribute("name","rose");
//重定向
response.sendRedirect("project02/GetDataServlet");
}
}
package cn.itcase.forwrad;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Dmeo01 extends HttpServlet {
/*
转发 RequestDispatcher getRequestDispatcher(java.lang.String path)
1.地址栏不会改变
2.转发只能转发到当前web应用内的资源
3.可以在转发过程中,可以把数据保存到request域对象中
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
/*保存数据到域对象*/
request.setAttribute("name", "rose");
/*转发
* 注意:不能转发到当前web应用以外的资源
*/
this.getServletContext().getRequestDispatcher("/GetDateServlet").forward(request, response);
}
}
package cn.itcase.forwrad;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GetDateServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取文本域中的对象
String name = (String)request.getAttribute("name");
System.out.println("name="+name);
/*
保存数据:void setAttribute(java.lang.String name, java.lang.Object object)
获取数据: java.lang.Object getAttribute(java.lang.String name)
删除数据: void removeAttribute(java.lang.String name
* */
}
}
结论:如果要使用request域对象进行数据共享,只能用转发技术