1.什么是Servlet
-
是javaEE的规范之一,规范接口
-
Servlet是JavaWeb三大组件之一
-
Servlet是运行在Web服务器中的Java小程序,可以接收客户端发送过来的请求,并响应数据给客户端
2.实现Servlet程序
-
实现Servlet接口
-
实现Servlet中的service方法:用于处理请求,并响应数据
-
到web.xml中配置
根据上面步骤实现一个简单的Servlet小程序
- 第一步:实现Servlet接口
pom.xml导入依赖//实现Servlet接口 package com.carl.servlet; import javax.servlet.*; import java.io.IOException; /** * @author :Carl_蔡先生 * @version :JDK1.8 * @description:Servlet是javax包下的一个接口,需要导入第三方jar包,使用Maven和在tomcat中直接导入都可以 * Servlet被调用时会默认执行service方法 * @date :2021/9/30 14:17 * @month_name :9月 * @week : **/ public class MyServlet implements Servlet { }
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
- 第二步:实现service方法
@Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("你好"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { }
- 第三步:配置web.xml文件
<servlet> <!--给servlet程序起别名--> <servlet-name>HelloServlet</servlet-name> <!--servlet-class是Servlet程序的全类名--> <servlet-class>com.carl.servlet.MyServlet</servlet-class> </servlet> <!--servlet-mapping标签是给Servlet程序配置访问地址的--> <servlet-mapping> <!--servlet-name标签的作用是告诉服务器,当前配置的地址是哪个Servlet程序->与上面的<servlet-name>内容一致--> <servlet-name>HelloServlet</servlet-name> <!--url-pattern标签配置访问地址 /下级路径 http://localhost:8080/ServletWeb/Carl --> <url-pattern>/Carl</url-pattern> </servlet-mapping>
注意事项:
- 如图所示的映射名称必须一致
报错:
- 如图所示处的url必须加
/
报错: - servlet-class标签的全类名配置错误:从src目录的下一级开始
报错:在浏览器处报错,服务器启动正常
3.Web如何通过URL地址解析Servlet
- 浏览器通过URL访问指定主机下Tomcat程序中的工程,步骤如图所示
2. 加载Servlet,并调用service()方法
4.Servlet的生命周期
-
执行Servlet构造器方法
-
执行init()初始化方法
1、2、只有在第一次访问的时候创建Servlet程序时会调用(即启动Tomcat后,通过资源路径触发web.xml创建Servlet类的实例时被调用)
http://localhost:8080/ServletWeb/Carl
-
执行service方法(只要tomcat不重启,每次访问都会被调用)
-
执行destory方法(在web工程停止时被调用)
5.区分get请求和post请求
Servlet通过service方法的请求参数ServletRequest的子类对象HttpServletRequest,调用getMethod方法获取当前浏览器请求为get还是post。
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("你好");
//将service方法中的servletRequest参数强制转换为HttpServletRequest,因为这个类由getMethod()方法
HttpServletRequest hsr=(HttpServletRequest) servletRequest;
String method = hsr.getMethod();
System.out.println(method);
if ("GET".equals(method)) {
System.out.println("get请求");
}else{
System.out.println("post请求");
}
}
-
我们需要调用的是HttpServletRequest对象的getMethod方法,所以需要强制转换
-
因为service方法主要用于接收浏览器的请求,因此这也是为什么上述生命周期中所说,每次调用tomcat服务都会触发service的调用
而当判断中存在大量的执行语句,就可以封装到方法中,只需要调用方法即可public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("你好"); //将service方法中的servletRequest参数强制转换为HttpServletRequest,因为这个类由getMethod()方法 HttpServletRequest hsr=(HttpServletRequest) servletRequest; String method = hsr.getMethod(); System.out.println(method); if ("GET".equals(method)) { doGet(); }else{ doPost(); } } public void doGet(){ System.out.println("get请求"); } public void doPost(){ System.out.println("post请求"); }
6.GenericServlet和HttpServlet
如何解决继承Servlet接口时,需要实现所有的方法,但是实际开发中不是所有的方法都需要被实现
Servlet有两个扩展的子类:GenericServlet
和HttpServlet
GenericServlet是一个普通的servlet;
HttpServlet是一个专门用于通过Http接收和响应web客户端请求的Servlet,重新实现了service方法,并实现了请求方法的分发处理
在GenericServlet类的doGet和doPost方法中都是负责抛出异常(抛出一个不支持Get/Post请求的异常)
//必须重写service方法
public class MyGenericServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
}
HttpServlet需要重写doGet和doPost方法,根据表单的返回类型决定是重写doGet()还是重写doPost()方法
public class MyHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("MyHttpServlet->doGet()");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("MyHttpServlet->doPost");
}
}
doGet()方法和doPost()方法中如果存在super()方法则无法获取http的get或post方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("MyHttpServlet->doGet()");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("MyHttpServlet->doPost");
}
在IDEA中快捷创建Servlet
使用注解的方式生成Servlet类
7.ServeltConfig和ServletContext
ServletConfig和ServletContext是Tomcat负责创建的,不需要自己创建
7.1ServletConfig
ServletConfig是Servlet程序的配置信息类
作用:
-
可以获取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程序起别名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class是Servlet程序的全类名-->
<servlet-class>com.carl.servlet.MyServlet</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/javamysql</param-value>
</init-param>
<init-param>
<param-name>driverClassName</param-name>
<param-value>com.mysql.cj.jdbc.Driver</param-value>
</init-param>
</servlet>
<!--servlet-mapping标签是给Servlet程序配置访问地址的-->
<servlet-mapping>
<!--servlet-name标签的作用是告诉服务器,当前配置的地址是哪个Servlet程序->与上面的<servlet-name>内容一致-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern标签配置访问地址
/下级路径
http://localhost:8080/ServletWeb/Carl
-->
<url-pattern>/Carl</url-pattern>
</servlet-mapping>
</web-app>
获取web.xml中的信息
@Override
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext servletContext = servletConfig.getServletContext();
String servletName = servletConfig.getServletName();
String url = servletConfig.getInitParameter("url");
String username = servletConfig.getInitParameter("username");
String password = servletConfig.getInitParameter("password");
String driverClassName = servletConfig.getInitParameter("driverClassName");
System.out.println("Servlet被init:[servlet的ServletContext=>"+servletContext +";\n"
+"Servlet的别名=>"+servletName+"initParam=>url="+url+"\n"
+"username="+username+"\n"
+"password="+password+"\n"
+"driverClassName="+driverClassName+"\n"
+"]");
}
也可以在其他方法中使用ServletConfig,需要使用静态方法getServletConfig()获取
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
ServletContext servletContext = servletConfig.getServletContext();
String servletName = servletConfig.getServletName();
String url = servletConfig.getInitParameter("url");
String username = servletConfig.getInitParameter("username");
String password = servletConfig.getInitParameter("password");
String driverClassName = servletConfig.getInitParameter("driverClassName");
System.out.println("Servlet被init:[servlet的ServletContext=>"+servletContext +";\n"
+"Servlet的别名=>"+servletName+"initParam=>url="+url+"\n"
+"username="+username+"\n"
+"password="+password+"\n"
+"driverClassName="+driverClassName+"\n"
+"]");
}
注意事项:如果在init以外的方法中获取ServletConfig实例对象
-
实现Servlet接口,在service()方法中使用ServletConfig实例对象
private transient ServletConfig servletConfig; public void init(ServletConfig config) throws ServletException { this.servletConfig = config; }
-
继承HttpServlet和GenericServlet类,只需要在重写的init方法中调用父类的init()方法即可,或者不重写init()方法也可以
@Override public void init(ServletConfig config) throws ServletException { super.init(config); }
如果没有按照上面两种方法解决问题,仅仅只是使用了ServletConfig实例,就会报错NullPointException
原因:ServletConfig是随着Servlet的创建而一起创建的,因此需要通过init()方法内部调用时,传入一个ServletConfig实例,当子类重写init方法后,很显然只会调用子类的init()方法,所以,要么自己在init方法中赋值,要么调用父类的init方法去赋值
7.2ServletContext
ServletContext是一个接口,针对每一个Web工程创建的一个域对象,该对象工程中全局唯一且共享,因此也叫全局共享对象
作用:
- 获取web.xml中配置的上下文参数context-param(全局参数)
//获取context-param全局参数 //获取web.xml中<param-name>对应的<param-value>值 String namespace = context.getInitParameter("namespace");//Carl //获取所有的<param-name>标签内容 Enumeration<String> initParameterNames = context.getInitParameterNames(); System.out.println(namespace); while(initParameterNames.hasMoreElements()){ String s = initParameterNames.nextElement(); System.out.println(s); }
- 获取当前的工程路径名称
//获取当前工程路径 String contextPath = context.getContextPath(); System.out.println(contextPath);///ServletWeb
- 获取工程部署后在服务器硬盘上的绝对路径(工程目录下的资源文件)
//获取绝对路径 String realPath = context.getRealPath("/"); System.out.println(realPath);//E:\文档\Java_WorkSpace\ServletWeb\out\artifacts\ServletWeb\ String realPath1 = context.getRealPath("/html"); System.out.println(realPath1);//E:\文档\Java_WorkSpace\ServletWeb\out\artifacts\ServletWeb\html
- 像Map一样存取数据
//存储数据 context.setAttribute("root", "root123"); //获取数据 Object root = context.getAttribute("root"); System.out.println(root);//root123 //删除数据 context.removeAttribute("root"); Object root1 = context.getAttribute("root"); System.out.println(root1);//null