1、什么是Serlvet
Servlet 是JavaEE 规范之一。规范就是接口
Servlet 就JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
Servlet 是运行在服务器上的一个java 小程序,Serlvet通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
1.1 手写一个Serlvet类
step1 编写一个类去实现Servlet 接口
step2 实现service 方法,处理请求,并响应数据(其他重写的方法按出来就是假装重写了,不是必须要写的)
step3 到web.xml 中去配置servlet 程序的访问地址
说明:web.xml是服务器tomcat的配置文件,如果不写好配置,tomcat就不知道有serlvet程序
用idea创建好一个web工程,默认首页是index.jsp,随便来两句。
在src目录下,创建一个servlet类 比如src/xx/selvet HelloSerlvet
public class HelloServlet implements Servlet {
//service 方法是专门用来处理请求和响应的
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被访问了");
}
}
配置web.xml 在工程根目录\web\WEB-INF\web.xml
<servlet>
<!--servlet-name 标签Servlet 程序起一个别名(一般是类名) --><!--取好名字以后,IDEA识别不到这个名字,会提示?,自动处理方式就是生成下面的 <servlet-mapping>-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是Servlet 程序的全类名(从包开始写到类)-->
<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>
<!--有了serlvet程序,但是在哪里呢? servlet-mapping 标签给servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签 的作用是告诉服务器,我当前配置的地址给哪个Servlet 程序使用--><!--servlet-name标签 里面的名字和上面的servlet-name名字是一样的-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern标签 配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
exp:/hello 表示地址为:http://ip:port/工程路径/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
特别说明:<url-pattern>标签里面的路径可以自己随便写,但是一般的约定是要和类名多少有点关系,方便识别。这个就是浏览器URL访问这个路径后,会跳转去的对应类。
关于工程路径:
一切就绪以后,启动Tomcat,进入默认访问页面。然后修改地址栏为http://ip:port/工程路径/hello ,即可访问到刚刚写的servlet
1.2 访问原理:
1.3 Servlet 生命周期
执行servlet构造器的方法(第一次访问调用)
执行init初始化方法(第一次访问调用)
执行Service方法(每次访问都调用)
执行destory销毁方法(web工程 停止的时候执行)
exp:
public class HelloServlet implements Servlet{
//step1 执行serlvet构造器方法 只有在第一次访问的时候,serlvet会调用构造器
public HelloServlet(){
System.out.println("1 构造器方法");
}
//step2 inint初始化方法 只有在第一次访问的时候,serlvet会调用构初始化方法
@Override
public void init(){
System.out.println("2 init初始化");
}
//step3 调用Service方法,每次访问都会调用
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 Hello Servlet 被访问了");
//step 4 在web工程停止时调用
@Override
public void destroy(){
System.out.println("4 destroy销毁方法");
}
}
1.4 Get 和 Post 请求分发处理
Service根本不会管前端发来的啥请求,都会响应。因此,我们需要让Service能够分辨get和post,并分别处理他们的请求
(1)前端页面
<body>
<form action="http://localhost:8080/06_servlet/hello" method="get">
<input type="submit">
</form>
</body>
(2)服务端
通过SerlvetRequest 的getMethod()方法获取前端到底提交的是 post 还是 get。 SerlvetRequest没有get.Method()方法,但他的子类HTTPServletRequest有getMethod()可以获取前端发来的post或者 get
public class HelloServlet implements Servlet {
/**
* service 方法是专门用来处理请求和响应的
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 service === Hello Servlet 被访问了");
// 类型转换(因为它有getMethod()方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 获取请求的方式
String method = httpServletRequest.getMethod();
if ("GET".equals(method)) {
doGet();
} else if ("POST".equals(method)) {
doPost();
}
/**
* 做get 请求的操作
*/
public void doGet(){
System.out.println("get 请求");
System.out.println("get 请求");
}
/**
* 做post 请求的操作
*/
public void doPost(){
System.out.println("post 请求");
System.out.println("post 请求");
}
}
1.5 通过继承HttpServlet 实现Servlet 程序
Servlet接口的实现类都有 FacesServlet, GenericServlet, HttpServlet,一般在实际项目开发中,都是使用继承HttpServlet 类的方式去实现Servlet 程序。
1.4是自己编写一个实现Servlet接口的类
开发步骤:
1、编写一个类去继承HttpServlet 类
2、根据业务需要重写doGet 或doPost 方法
3、到web.xml 中的配置Servlet 程序的访问地址
(1)前端代码 访问/hello2 访问方法改成了 post
<body>
<form action="http://localhost:8080/06_servlet/hello2" method="post">
<input type="submit">
</form>
</body>
(2)配置文件
<servlet>
<!--servlet-name 标签Servlet 程序起一个别名(一般是类名) --><!--取好名字以后,IDEA识别不到这个名字,会提示?,自动处理方式就是生成下面的 <servlet-mapping>-->
<servlet-name>HelloServlet2</servlet-name>
<!--servlet-class 是Servlet 程序的全类名(从包开始写到类)-->
<servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
</servlet>
<!--有了serlvet程序,但是在哪里呢? servlet-mapping 标签给servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签 的作用是告诉服务器,我当前配置的地址给哪个Servlet 程序使用--><!--servlet-name标签 里面的名字和上面的servlet-name名字是一样的-->
<servlet-name>HelloServlet2</servlet-name>
<!--url-pattern标签 配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
exp:/hello 表示地址为:http://ip:port/工程路径/hello
-->
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
(3)服务端代码
public class HelloServlet2 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IoException{
System.out.println("HelloServlet2 的doGet方法");
}
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IoException{
System.out.println("HelloServlet2的doPost方法");
}
}
1.6 创建serlvet接口实现类的简便方法 用IDEA 直接new Servlet
找到想创建servlet的包,然后在包下 new—Create New Servlet
该方法的好处就是,创建的时候就可以帮你快速写web.xml配置文件了(servlet3.0以后有注解版,暂时先不勾,反正都是帮你自动写)
1.7 Serlvet类的继承体系
2、SerlvetConfig类
ServletConfig 类从类名上来看,就知道是Servlet 程序的配置信息类。
Servlet 程序和ServletConfig 对象都是由Tomcat 负责创建,我们负责使用。
Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个Servlet 程序创建时,就创建一个对应的ServletConfig 对象。
2.1 ServletConfig类的三大作用
① 可以获取Servlet 程序的别名servlet-name 的值
可以在web.xml配置文件中,获取到程序别名,通过getServletName()方法
② 获取初始化参数init-param
说明:可以在web.xml中用init-param标签配置多个键值对。配置之后,就可以用SerlvetConfig的方法获取到这些配置
通过getInitParameter(String key) 的方法
③ 获取ServletContext 对象
通过getServletContext()
2.2 exp:ServletConfig 演示
(1)web.xml配置文件
<!-- servlet 标签给Tomcat 配置Servlet 程序-->
<servlet>
<!--servlet-name 标签Servlet 程序起一个别名(一般是类名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是Servlet 程序的全类名-->
<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
<!--init-param 是初始化参数,想要serlvet实现类获取的,都可以写进去-->
<init-param>
<!--是参数名-->
<param-name>username</param-name>
<!--是参数值-->
<param-value>root</param-value>
</init-param>
<!--可以配置多个init-param,再来一个JDBC的-->
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
<!--servlet-mapping 标签给servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个Servlet 程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--
url-pattern 标签配置访问地址<br/>
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径<br/>
/hello 表示地址为:http://ip:port/工程路径/hello <br/>
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
(2)在serlvet实现类的方法中,通过ServletConfig对象获取值
特别注意:重写init()方法,一定要调用父类的init方法,这样其他方法中比如doGet()才有机会用getServletConfig()获取得到ServletConfig对象。
class HelloSerlvet extends HttpServlet{
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//重写init方法,一定要调用父类的init方法,这样其他方法中比如doGet()才有机会用 getServletConfig()获取得到ServletConfig对象
super.init(servletConfig);
System.out.println("2 init 初始化方法");
// 1、可以获取Servlet 程序的别名servlet-name 的值
System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName());
// 2、获取初始化参数init-param
System.out.println("初始化参数username 的值是;" +
servletConfig.getInitParameter("username"));
System.out.println("初始化参数url 的值是;" + servletConfig.getInitParameter("url"));
// 3、获取ServletContext 对象
System.out.println(servletConfig.getServletContext());
}
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp)throws
ServletException, IOException{
//如果上面没有super.init(servletConfig);这里就获取不到ServletConfig对象
ServletConfig servletConfig = getServletConfig(); //这个是父类的方法,直接用
}
}
3、servletContext类
3.1 什么是ServletContext
① ServletContext 是一个接口,它表示Servlet 上下文对象
② 一个web 工程,只有一个ServletContext 对象实例。
③ ServletContext 对象是一个域对象。
④ ServletContext 是在web 工程部署启动的时候创建。在web 工程停止的时候销毁。
说明:Web工程启动的时候 ServletContext自动创建 值为null。在任意serlvet实现类中设置值以后,该工程所有的serlvet实现类都有这个值
扩展:域对象
域对象,指可以像Map一样存取数据的对象,叫做域对象。这里域指的是存取数据的操作范围,整个WEB工程(不管工程里面多少个servlet实现类,就一个ServletContext)
存数据 | 取数据 | 删除数据 | |
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute(); |
3.2 ServletContext类的四个作用
① 获取web.xml 中配置的上下文参数context-param
说明:context-param是上下文参数,它属于整个web工程。context-param标签一般放在web.xml的前面,键值对形式存放,可以根据需要配置多组
② 获取当前的工程路径(其实是Tomcat里面的虚拟目录),格式: /工程路径
说明:
只获取到/06_serlvet。
③ 获取工程部署后在服务器硬盘上的绝对路径(磁盘路径)
说明:
会输出在本机的绝对路径。即 E:\IdeaProjects\JavaWeb\out\artifacts\06_servlet_war_exploded(文件夹名)\
工程路径根目录就从以上绝对路径开始
IDEA在创建该项目的时候,直接创建Tomcat副本,放到IDEA的项目文件夹里面去了
复习:Tomcat配置文件
<!-- <Context path="/abc" docBase="D:\book"/> 此时浏览器端口后面输入/abc就相当于进了 book目录 -->
<Context path=”浏览器要访问的目录---虚拟目录” docBase=”网站所在磁盘目录”/>
工程部署路径文件夹(磁盘路径)下的内容,刚好就对应 IDEA中 web工程下的内容(最终映射到Idea的web目录)
④ 像Map 一样存取数据
exp:演示 获取web.xml 中配置的上下文参数context-param
step1 用IDEA在相应的包下,快速创建一个serlvet(先不用注解版),自动生成配置文件(这里主要演示获取上下文参数,其他配置就不写了)
<!--context-param 是上下文参数(它属于整个web 工程)-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<!--context-param 可以配置多个上下文参数-->
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>
step2: 获取工程路径,和 绝对路径
Step3 演示像map一样存取数据
public class ContextServlet1 extends HttpServlet{
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
//获取ServletContext对象
//这个类的父类本来就有getServletContext()方法,就不用找ServletConfig去获取这个Context了
ServeletContext context = getServletContext();
System.out.println(context);
// 目前值为null
System.out.println("保存之前:Context1获取key1的值是"+context.getAttribute("key1"));
context.setAttribute("key1","value1");
//之后值为value1,其他Servlet实现类用这个context,值也为1,但需要浏览器先访问这个,来给context赋值。先访问其他serlvet,就不一定赋这个值了
System.out.println("Context1中获取域数据key1的值是"+context.getAttribute("key1"));
}
}
public class ContextServlet2 extends HttpServlet{
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
//获取ServletContext对象
//这个类的父类本来就有getServletContext()方法,就不用找ServletConfig去获取这个Context了
ServeletContext context = getServletContext();
System.out.println(context);
//如果浏览器先访问上面的 ContextServlet1,现在就有值了,就是value1
System.out.println("Context2 中获取域数据key1 的值是:"+ context.getAttribute("key1"));
}
}
说明:浏览器访问哪个serlvet接口实现类,就是先执行哪个serlvet接口实现类里面的doGet或者doPost方法,只要方法里面设置了ServletContext,其他的serlvet接口中的实现类,都被自动设置