文章目录
Servlet ①
1. 概念
什么是Servlet? 是JavaEE规范之一,规范就是接口。是JavaWeb三大组件之一。
是运行在Web服务器上的一个java小程序,可以 接受客户端发送来的请求,并响应数据给客户端
三大组件:Servlet
程序,Filter
过滤器,Listener
监听器。
2. 实现Servlet
-
创建一个动态的Web工程
-
编写一个类去实现
Servlet
接口 -
实现
service()
方法,处理请求并响应数据 -
到
web.xml
去配置servlet
程序的访问地址
HelloServlet.java
public class HelloServlet implements Servlet {
public HelloServlet() {System.out.println("1.构造器方法!");}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init方法");
}
/**
* service方法是专门用来处理请求和响应的
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.service -> Hello Servlet 被访问了");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod(); //获取请求方式 POST/GET
if ("GET".equals(method)) {
// 业务逻辑
doGet();
} else if ("POST".equals(method)) {
// 业务逻辑
doPost();
}
}
public void doGet() {System.out.println("get请求");}
public void doPost() {System.out.println("post请求");}
@Override
public ServletConfig getServletConfig() {return null;}
@Override
public String getServletInfo() {return null;}
@Override
public void destroy() {System.out.println("4.destroy方法");}
}
web.xml
配置文件
-
<servlet>
:给Tomcat服务器配置servlet程序-
<servlet-name>
:给servlet程序起一个别名,一般是类名 -
<servlet-class>
:指定servlet程序的全类名,加上包名
-
-
<servlet-mapping>
:给servlet程序配置访问地址,就是在浏览器里面输入什么才执行servlet程序<servlet-name>
:和上面那个意义不同,作用:告诉服务器当前配置的地址给那个servlet程序使用<url-pattern>
:配置访问地址 (注意要以斜杠开头)
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.sutong.service.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<!-- url-pattern标签:配置访问地址
/hello
'/':在服务器解析的时候,表示地址为 http://ip:port/工程路径 (工程路径是自己配置的, 我的是/dynamicobject)
'hello':代表地址为: http://ip:port/工程路径/hello
当启动tomcat时,idea会帮我们自动访问http://localhost:8080/dynamicobject/这个url,
当我们在后面加上hello时,那个Servlet程序的service方法就会被调用到了,
hello只是这Servlet程序的代名词而已。
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
3. Servlet生命周期
-
Ⅰ执行 Servlet 构造器方法
-
Ⅱ 执行 init 初始化方法
前两个只是在第一次访问的时候创建Servlet程序会调用,刷新网页,重新进入网页都不会被调用了
-
Ⅲ 执行service 方法
每次访问都会被调用,刷新/重新进入
-
Ⅳ 执行 destroy 销毁方法
在web工程停止的时候才会执行
4. 另一种实现Servlet
-
以前我们是实现 Servlet接口,实现的service方法:
@Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("3.service -> Hello Servlet 被访问了"); // ServletRequest 这个类不可以直接使用来获得提交方式, // 它的子类HttpServletRequest有方法可以用,即getMethod() HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; String method = httpServletRequest.getMethod(); //获取请求方式 POST/GET if ("GET".equals(method)) { // 这里面的代码可能很多,包装成方法 doGet(); // 自己写的 } else if ("POST".equals(method)) { // 这里面的代码可能很多 doPost(); } }
-
在实际中我们很少自己直接实现
Servlet
接口,我们可以直接继承/扩展Servlet
接口的实现类 ⭐⭐一般都是继承
HttpServlet
类来实现Servlet
程序 (HttpServlet
实现了service()
方法,实现了请求的分发处理)- Ⅰ 编写一个类去继承
HttpServlet
类 - Ⅱ 根据业务需求重写
doGet() / doPost()
方法 - Ⅲ 去
web.xml
配置Servlet
程序的访问地址
public class HelloServlet02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get请求"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post请求"); } } // 最后记得配置 web.xml文件,和上面一样
- Ⅰ 编写一个类去继承
-
使用 IDEA 创建
Servlet
程序选择包名 | 右键 | New | Create New Servlet
记得把下面的Create Java EE 6 annotated class去掉勾选,勾选上会使用高版本的注解功能,就不是使用web.xml文件配置了,创建完直接配置 servlet-mapping即可
5. Servlet的继承体系
javax.Servlet接口
只是负责定义Servlet
程序的访问规范
↓ (实现 )
GenericServlet抽象类
实现了Servlet接口,做了很多空实现。持有ServletConfig
类的一个引用,并对ServletConfig
的使用做了一些方法)
↓ (继承)
HttpServlet抽象类
重点实现了service()
方法,实现了请求的分发处理,先是req.getMethod(),根据请求发送调用对应方法,如果我们不重写doGet(),doPost() 方法,不重写就调用本类的话会抛异常method_get_not_supported/method_post_not_supported
,即不支持Get/Post请求
↓ (继承)
我们自己写的Servlet程序
根据业务的业务需要重写doGet() / doPost()
方法,重写后就是支持了
6. ServletConfig类
从类名上看是 Servlet 程序的配置信息类。
作用:
-
获取
ServletContext
对象 (下面讲) -
获取
Servlet
程序的别名,即web.xml里面的,servlet
标签里servlet-name
标签里的值 -
获取初始化参数
init-param
,即web.xml里面的,servlet
标签里的init-param
标签的值怎么配置servlet初始化参数??,形式:参数名-值 (如下)
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.sutong.service.HelloServlet</servlet-class> <!-- init-param标签:初始化参数,里面类似键值对,可以多对--> <init-param> <!-- 参数名--> <param-name>username</param-name> <!-- 参数值--> <param-value>root</param-value> </init-param> <!-- 例子--> <init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/bjpowernode</param-value> </init-param> </servlet>
Servlet
程序和ServletConfig
对象都是由Tomcat
负责创建,我们负责使用。Servlet
程序默认是第一次访问的时候创建,ServletConfig
是每个Servlet
程序创建时就创建一个对应的ServletConfig
对象,即一个Servlet
程序对应一个ServletConfig
(所以:
ServletConfig
对象只能获取自己servlet
标签里面的初始化参数)⭐使用:
1.实现
Servlet
接口中的使用// 1.HelloServlet类 implements Servlet // 实现Servlet接口init方法会ServletConfig参数 @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("HelloServlet程序的别名是: " + servletConfig.getServletName()); System.out.println("初始化参数username = " + servletConfig.getInitParameter("username")); System.out.println("初始化参数url = " + servletConfig.getInitParameter("url")); System.out.println(servletConfig.getServletContext()); }
2.继承
HttpServlet
类中的使用HttpServlet的父类GenericServlet包装了ServletConfig的使用
// 2.HelloServlet02类 extends HttpServlet // 直接使用,不需要.了,例如: getServletName() public void test01() { System.out.println(getServletName()); System.out.println(getInitParameter("username")); // 这个获取不到HelloServlet程序的初始化参数 // 因为HelloServlet02程序的ServletConfig对象和HelloServlet程序的ServletConfig对象不是一个 } // 注意: 如果我们想要重写init方法,第一句一定要加上super.init(config),否则直接用的话就会空指针异常 // 因为GenericServlet类(HttpServlet类继承了GenericServlet类)底层, // 在init方法里面对ServletConfig对象的使用进行了保存/封装, @Override public void init(ServletConfig config) throws ServletException { super.init(config); System.out.println("自己重写了init方法..."); }
7. ServletContext对象
-
ServletContext
是一个接口,它表示 Servlet 上下文对象 -
一 个web工程,只会有一个
ServletContext
对象实例 -
ServletContext
对象是一个域对象域对象:是可以像Map 一样存取数据的对象,这里的域指的是存取数据的操作范围 - 即整个Web工程
存数据 取数据 删除数据 Map put() get() remove() 域对象 setAttribute() getAttribute() removeAttribute()
ServletContext
作用:
- 获取 web.xml 中配置的上下文参数
context-param
- 获取当前的工程路径。 格式:
/工程路径
- 获取工程部署后在服务器上的绝对路径
- 像Map一样存储数据
<!-- 上下文参数,注意是配置在servlet标签外面!!,
因为一个工程只有一个ServletContext对象,属于整个web工程-->
<context-param>
<!-- 键值对,K-V,可以多组-->
<param-name>name</param-name>
<param-value>context</param-value>
</context-param>
使用:
public class HelloServlet02 extends HttpServlet {
// ...
public void test02() {
ServletContext context = getServletContext();
// getInitParameter()获得context-param标签里面的内容
// 注意这个方法名字虽然和ServletConfig类中的一样,但作用不同
System.out.println("name对应的值为:" + context.getInitParameter("name")); // context
System.out.println("当前工程路径:" + context.getContextPath()); // /dynamicobject
// D:\JAVA练习\JavaWeb\dynamicobject\out\artifacts\dynamicobject_war_exploded\
System.out.println("工程部署的绝对路径:" + context.getRealPath("/"));
// D:\JAVA练习\JavaWeb\dynamicobject\out\artifacts\dynamicobject_war_exploded\css\1.css
System.out.println("工程中1.css的绝对路径" + context.getRealPath("/css/1.css"));
// context.getRealPath("/"); // 即文件部署路径
// 而idea中的路径,是文件真实路径
String contentType = context.getMimeType("path"); // 传入文件路径,可以得到对应的是Mime类型
}
// 注意ServletContext对象整个工程只有一个,在web工程部署启动时创建,在web工程停止的时候销毁
public void test03() {
ServletContext context = getServletContext();
context.setAttribute("key1", "value1");
System.out.println("Context中获取域数据key1 = " + context.getAttribute("key1"));
}
}
工程部署的绝对路径时,为什么传入一个斜杠?
因为
/
会被服务器解析为http://ip:port/工程路径
,这个路径对应我们在idea上写的工程中的web文件夹,部署是本质是把web目录的副本和src编译成的字节码文件放一起,然后在tomcat/conf/Catalina/localhost 在这个目录建立一个xml文件,来部署的。