本文被 系统学习JavaWeb 收录点击订阅专栏
文章目录
1 走进Servlet
1.1 Servlet简介
Servlet是什么?
- Servlet是JavaEE规范之一,规范就是接口
- Servlet是JavaWeb的三大组件之一,三大组件分别是:Servlet程序、Filter过滤器、Listener监听器
- Servlet是运行在服务器上的一个java小程序,可以接收客户端发来的请求,并响应数据给客户端
如何实现Servlet程序呢?
- 编写一个类去实现Servlet接口
- 实现service方法,处理请求,并响应数据
- 到web.xml中配置servlet程序的访问地址
1.2 第一个Servlet程序
下面来完成一个简单的Servlet程序,当访问到则在控制台打印提示信息
HelloServlet.java:
import javax.servlet.*;
import java.io.IOException;
/**
* @author 兴趣使然黄小黄
* @version 1.0
*/
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被访问了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--servlet标签给Tomcat配置Servlet程序-->
<servlet>
<!--servlet-name标签Servlet程序起别名 一般是类名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class是Servlet程序的全类名-->
<servlet-class>com.example.servlet_test.HelloServlet</servlet-class>
</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>
</web-app>
配置完成后,可以通过 http://ip:port/工程路径/hello
访问,成功访问后,控制台打印了如下信息:
1.3 Servlet程序如何定位到url地址
以上面的案例:http://localhost:8080/工程路径/hello
为例:
先通过ip定位定位到了服务器,而后通过服务器端口找到Tomcat,再通过工程路径确认访问的工程,而后由资源路径访问到 web.xml 配置文件 中的 url,后确认了访问的HelloServlet类。
1.4 Servlet的生命周期方法
Servlet程序的生命周期方法调用顺序如下:
- 执行Servlet构造器方法;
- 执行init初始化方法;
- 执行service方法;
- 执行destroy销毁方法。
其中第一、二步,是在第一次访问的时候创建Servlet程序会调用。第三步每次访问都会调用。第四步只有在web工程停止的时候调用。
案例如下:
修改HelloServlet.java如下
import javax.servlet.*;
import java.io.IOException;
/**
* @author 兴趣使然黄小黄
* @version 1.0
*/
public class HelloServlet implements Servlet {
public HelloServlet(){
System.out.println("构造方法被调用");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init方法被调用");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service方法被调用");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy方法被调用");
}
}
当运行程序后,进行一次刷新页面后退出程序时,控制台打印信息如下:
补充
除了生命周期方法外,Servlet接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet可使用前一种方法获取任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如:作者、版权、版本等。
1.5 Servlet请求的分发处理
表单的提交方式分为POST和GET两种请求方式,但是service方法只有一个,如何实现分发处理呢?
首先在webapp文件夹下创建一个页面,以get方式提交表单给资源文件hello:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Servlet_Test/hello" method="get">
<input type="submit"/>
</form>
</body>
</html>
HelloServlet中的service方法修改如下:
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//向下转型
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
//请求分发处理
String post = "POST";
String get = "GET";
if(post.equals(method)){
System.out.println("POST方式");
}else if (get.equals(method)){
System.out.println("GET方式");
}
}
getMethod方法可以返回一个String值,用于判断是POST请求还是GET请求,运行结果如下:
该例子中,简单介绍了如何判断请求方式,并打印。实际中,如果分发处理的代码都写在service方法中,会显得过于臃肿。
因此,在实际开发中,分发处理的具体操作会单独写成方法,供service调用。例如:doGet()、doPost()方法。
1.6 通过继承HttpServlet类实现Servlet程序
在实际开发中,我们很少通过实现Servlet方法的方式去实现Servlet程序,更多的是采用继承子类的方式来实现。大致步骤如下:
- 编写一个类去继承 HttpServlet 类;
- 根据业务需要重写 doGet 和 doPost 方法(分发处理的具体方法);
- 到web.xml中配置Servlet程序的访问地址。
需要注意的是,在HttpServlet类中,已经帮我们分发处理完毕了
案例代码如下:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 兴趣使然黄小黄
* @version 1.0
* 通过继承的方式实现Servlet
*/
public class HelloServlet2 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("do Get具体操作");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("do Post具体操作");
}
}
除了自己重写以外,在实际开发中有一种更加便捷的方式:
使用IDEA菜单生成Servlet程序
创建的时候可以选择取消注解,会自动配置xml文件,只需要手动添加mapping即可:
2 Servlet体系
2.1 Servlet继承体系
- Servlet接口: 负责定义Servlet程序的访问规范;
- GenericServlet类: 实现了Servlet接口,做了很多空实现。持有一个ServletConfig类的空引用,并对ServletConfig的使用做了些方法;
- HttpService抽象类: 实现了service方法,并实现了请求的分发处理。GET和POST请求的方式分别对应doGet与doPost方法。
- 自定Servlet程序: 根据自己的需要去重写doGet与doPost方法即可。
2.2 ServletConfig类的使用
ServletConfig类是Servlet程序的信息类。
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们只负责使用。
Servlet程序默认第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。
ServletConfig的作用简介:
- 可以获取Servlet程序的别名servlet-name的值;
- 获取初始化参数init-param的值;
- 获取ServletContext对象。
下面通过案例来展示基本使用:
修改web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.servlet_test.HelloServlet</servlet-class>
<!--配置初始化参数-->
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
HelloServlet.java中的init方法:
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init方法被调用");
//1.获取Servlet程序的别名 servlet-name 的值
String servletName = servletConfig.getServletName();
System.out.println("servlet-name: " + servletName);
//2.获取初始化参数init-param的值
String url = servletConfig.getInitParameter("url");
System.out.println("url的值: " + url);
}
2.3 ServletContext类的使用
- ServletContext是一个接口,表示Servlet上下文。
- 一个web工程只有一个ServletContext对象实例。
- ServletContext对象是一个 域对象。
什么是域对象?
域对象是可以像Map一样存取数据的对象。域是指存取数据的操作范围。
Map与域对象横向比较
种类 | 存数据 | 取数据 | 删除数据 |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
ServletContext的作用
- 获取 web.xml 中配置的上下文参数 context-param
- 获取当前的工程路径,格式:/工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像Map一样存取数据
演示案例新建一个ContextServlet类,配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--context属于整个web工程-->
<context-param>
<param-name>username</param-name>
<param-value>黄小黄</param-value>
</context-param>
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>com.example.servlet_test.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
ContextServlet.java
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 兴趣使然黄小黄
* @version 1.0
*/
public class ContextServlet extends HttpServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
super.service(req, res);
//获取context上下文参数
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println("context参数username= " + username);
//获取当前的工程路径
System.out.println("当前工程路径= " + context.getContextPath());
//获取工程部署后在服务器上的绝对路径
/*
* / 被服务器解析地址:http://ip:port/工程名/
*/
System.out.println("工程部署路径= " + context.getRealPath("/"));
}
}