Servlet技术
什么是servlet
- servlet是JavaEE的规范之一。规范就是接口。
- servlet是JavaEE三大组件之一。三大组件分别是:servlet程序、Filter过滤器、Listener监听器。
- servlet是运行在服务器上的一个Java小程序,它可以接受客户端发送过来的请求,并相应数据给客户端。
手动实现Servlet程序
- 编写一个类去实现Servlet接口
- 实现service方法,处理请求,并响应接口
- 到web.xml中去配置servlet程序的访问地址
service方法相关代码:
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
/**
* service是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("我被访问了!");
}
}
web.xmldee相关配置:
<?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.demo.HelloServlet</servlet-class>
</servlet>
<!-- servlet-mapping标签给Servlet程序配置访问地址 -->
<servlet-mapping>
<!-- 告诉服务器,我们当前配置的地址给哪个Servlet程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置访问地址
“/” 表示在服务器解析时,表示的地址为:http://ip:port/工程路径
“/hello” 表示地址为:http://ip:port/hello,可以随意改动
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
注意:
-
在配置
<url-pattern>标签时不能漏掉“/”
,否则运行报错非法地址Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> hello in servlet mapping
-
servlet-name 配置的值不存在(没配置或者说两个servlet-name名不一致):
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name HelloServlets
-
servlet-class 标签的全类名配置错误:
url地址到Servlet的访问
Servlet的生命周期
相关代码:
package com.example.demo;
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1.构造器");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.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("3.service 我被访问了!");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4.destroy销毁");
}
}
-
执行Servlet构造器方法
-
执行init初始化方法
第一、二步,是在第一次访问,的时候创建 Servlet
-
执行 service 方法
第三步,每次访问都会调用。
-
执行 destroy 销毁方法
第四步,在 web工程停止的时候调用。
GET和POST请求分发处理
在src->main->webapp下创建html文件,并简单写下get和post请求方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/demo/hello" method="post">
<input type="submit" value="OK">
</form>
</body>
</html>
运行代码:
public class HelloServlet implements Servlet {
/**
* service是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 类型转换(因为它有 getMethod()方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 获取请求的方式
String method = httpServletRequest.getMethod();
if ("get".equalsIgnoreCase(method)){
doGet();
}else if ("post".equalsIgnoreCase(method)){
doPost();
}
}
//请求get
public void doGet(){
System.out.println("GET");
}
//请求post
public void doPost(){
System.out.println("POST");
}
通过继承 HttpServlet 实现 Servlet 程序
一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。
- 编写一个类去继承HTTPServlet类
- 根据业务需要重写doGet或者doPost方法
- 到web.xml文件中的配置servlet程序的访问地址
代码展示:
同样创建一个home2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/demo/hello2" method="get">
<input type="submit" value="OK">
</form>
</body>
</html>
继承HttpServlet:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet的get请求");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost的post请求");
}
}
IDEA自动生成HttpServlet:
Servlet 类的继承体系
Servletconfig类
- servlet程序的配置信息类
- Servlet程序和ServletConfig对象都是由TomCat负责创建,我们负责使用
- Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象(比如你创建了两个java文件,名字分别为
h2
和h1
,我们只在web.xml
中配置servlet-name:h1
的ServletConfig信息,运行h1的程序初始化我们可以得到值,但是当我们运行h2的程序时得到的值为null)
作用:
- 可以获取servlet程序的别名
servlet-name
的值 - 获取初始化参数init-param
- 获取ServletContext对象
web.xml相关配置:
<servlet>
......
<init-param>
<!-- 参数名 -->
<param-name>root</param-name>
<!-- 参数值 -->
<param-value>123456</param-value>
</init-param>
<init-param>
<!-- 参数名 -->
<param-name>username</param-name>
<!-- 参数值 -->
<param-value>ll123456</param-value>
</init-param>
</servlet>
Servlet代码:
public class HelloServlet implements Servlet {
......
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//获取servlet-name别名
System.out.println("HelloServlet的别名servlet-name是" + servletConfig.getServletName());
//获取初始化init-param参数
System.out.println("root的值是:" + servletConfig.getInitParameter("root") );
System.out.println("username的值是:" + servletConfig.getInitParameter("username") );
//获取ServletContext对象
System.out.println("ServletContext对象" + servletConfig.getServletContext());
......
}
}
**注意:**重写init()方法必须加上super.init(config);
,否则会出现空指针异常
ServletContext类
什么是域对象?
域对象,是可以像Map一样存取数据的对象,叫域对象。这里的域是指存取数据的操作范围
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
ServletContext的四个作用
- 获取 web.xml 中配置的上下文参数 context-para
- 获取当前的工程路径,格式: /工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像 Map 一样存取数据
代码实例:
public class ContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletConfig().getServletContext();
//获取 web.xml 中配置的上下文参数 context-para
System.out.println("username的值为:" + servletContext.getInitParameter("username"));
System.out.println("username2的值为:" + servletContext.getInitParameter("username2"));
System.out.println("username3的值为:" + servletContext.getInitParameter("username3"));
//获取当前的工程路径,格式: /工程路径
System.out.println("获取当前工程路径:" + servletContext.getContextPath());
//获取工程部署后在服务器硬盘上的绝对路径
System.out.println("获取工程部署后在服务器硬盘上的绝对路径" + servletContext.getRealPath("/"));
System.out.println("获取工程部署的css绝对路径" + servletContext.getRealPath("/css"));
}
}
web.xml中的配置:
<!-- context-param是上下文参数(它属于整个web工程) -->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<context-param>
<param-name>username2</param-name>
<param-value>context2</param-value>
</context-param>
像Map一样存取数据:
代码实例:
public class ContextServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
//保存数据之前
System.out.println("保存之前ContextServlet2中key的值:" + context.getAttribute("key"));
//保存数据之后
context.setAttribute("key","value");
System.out.println("保存之后ContextServlet2中key的值:" + context.getAttribute("key"));
}
}
总结:
-
ServletContext是一个接口,它表示Servlet上下文对象
-
一个web工程,只有一个Servletcontext对象实例
-
Servletcontext对象是一个域对象
-
ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁(和静态变量存储相似之处)
-
在上面文件的基础上,我们重新创建一个ContextServlet3.java,只写
ServletContext context = getServletContext(); System.out.println("保存之前ContextServlet3中key的值:" + context.getAttribute("key"));
public class ContextServlet3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = getServletContext(); System.out.println("保存之前ContextServlet3中key的值:" + context.getAttribute("key")); } }
-
重新启动
-
先在网址中输入ContextServlet2中存取数据的地址
http://localhost:8080/demo/context2
,idea显示key值为value。 -
然后在网址中输入Contextservlet3的数据地址
http://localhost:8080/demo/context3
,会发现即使Contextservlet3.java没有存取数据也能的到key值为value
-
评论区