a) 什么是Servlet
1、Servlet 是JavaEE 规范之一。规范就是接口
2、Servlet 就JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
3、Servlet 是运行在服务器上的一个java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
a) 手动实现Servlet 程序
1、编写一个类去实现Servlet 接口
2、实现service 方法,处理请求,并响应数据
package com.softeem.servlet; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; //创建Servlet类时: //1.我们定义类时都会以xxxServlet方法命名 //2.需要实现一个接口[Servlet] 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 方法是专门用来处理请求和响应的 @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("每次请求我时,都会执行service() Hello Servlet被访问了"); HttpServletRequest request = (HttpServletRequest)servletRequest; String method = request.getMethod(); if (method.equals("POST")){ this.doPost(); }else{ this.doGet(); } } @Override public String getServletInfo() { return null; } @Override public void destroy() { System.out.println("我是web服务器停止时执行destroy()"); } public void doGet(){ System.out.println("get请求"); } public void doPost(){ System.out.println("post请求"); } }
3、到web.xml 中去配置servlet 程序的访问地址
<?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.softeem.servlet.HelloServlet</servlet-class> </servlet> <!-- servlet-mapping 标签给servlet 程序配置访问地址 --> <servlet-mapping> <!-- 告诉服务器,我当前配置的地址是给哪个Servlet程序使用--> <servlet-name>HelloServlet</servlet-name> <url-pattern>/HelloServlet</url-pattern> </servlet-mapping> </web-app>
Servlet 的生命周期
1、执行Servlet 构造器方法
2、执行init 初始化方法
第一、二步,是在第一次访问,的时候创建Servlet 程序会调用。
3、执行service 方法
第三步,每次访问都会调用。
4、执行destroy 销毁方法
第四步,在web 工程停止的时候调用。
GET 和POST 请求的分发处理
获取请求的方式:
- HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
- // 获取请求的方式
- String method = httpServletRequest.getMethod();
新建一个html文件在web文件夹下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <base href="http://localhost:8080/javaWeb01"> </head> <body> <h1>我是一个测试网页</h1> <form action="HelloServlet" method="post"> <input type="submit" value="提交"> </form> </body> </html>
一个表单提交网页,点击按钮会跳到HelloServlet类中的doPost方法"post"
通过继承HttpServlet 实现Servlet 程序
实现Servlet接口,需要实现里面的所有方法。一般在实际项目开发中,都是使用继承HttpServlet实现Servlet程序。
1、编写一个类去继承HttpServlet 类
HttpServlet 类是一个抽象类,但里面没有抽象方法,主要目的只是为了不让实例化
2、根据业务需要重写doGet 或doPost 方法
3、到web.xml 中的配置Servlet 程序的访问地址(现在使用注解的方法配置Servlet程序的访问地址)
package com.softeem.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name="HelloServlet2", value = {"/HelloServlet2", "/ss"}) 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"); } }
编写一个网页
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="HelloServlet2" method="post"> <input type="submit" value="提交"> </form> <hr> <a href="HelloServlet2">跳转到HelloServlet2</a> </body> </html>
html中的from表单 提交方式有两种:
1、post
2、get
html中的a链接是使用的get方法提交。
除了form表单能够进行post提交...其他的元素都是采用get提交方式。
如果直接通过地址栏输入Servlet,这样也是get的提交
创建Servlet
Servlet 类的继承体系
Servlet接口,只是负责定义Servlet程序的访问规范。
GenericServlet类实现了Servlet接口。做了很多空实现。并持有一个ServletConfig类的引用。并对ServletConfig的使用做一些方法。
HttpServlet抽取类实现了service()方法,并实现了请求的分发处理。
ServletConfig 类
Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个Servlet 程序创建时,就创建一个对应的ServletConfig 对象。
service方法处理
service方法就是进行请求分发的,它会就我们的请求分发给doPost方法或者是doGet方法,然后我们去这两个方法中处理业务逻辑,但是这样麻烦,所以选择直接重写service方法...不需要它去请求分发了,我直接让service方法处理请求的业务
init()方法与init(ServletConfig config)方法的区别
重写init方法里面一定要调用父类的init(ServletConfig)操作,该类会调用init(),这样在两个方法同时存在的情况下才都会执行。否则只会执行重写后的init(ServletConfig)
public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { }
super.init(ServletConfig)一定是super,this.init(ServletConfig)会出现空指针异常。
package com.softeem.servlet; import javax.servlet.ServletConfig; 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 HelloServlet4 extends HttpServlet { @Override public void init() throws ServletException { System.out.println("------------------init()开始---------------------------------"); //此方法里面没有ServletConfig参数,但是Servlet接口中的init方法将config赋值给了全局变量config ServletConfig config = super.getServletConfig(); System.out.println("HelloServlet 程序的别名是:" + config.getServletName()); System.out.println("初始化参数 username 的值是;" + config.getInitParameter("username")); System.out.println("初始化参数 url 的值是;" + config.getInitParameter("url")); System.out.println(config.getServletContext()); System.out.println("------------------init()结束---------------------------------"); } @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("2 init 初始化方法"); //可以获取Servlet 程序的别名servlet-name的值 也就是配置文件上的名字 System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName()); //获取初始化参数init-param System.out.println("初始化参数 username 的值是;" + servletConfig.getInitParameter("username")); System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url")); //获取ServletContext 对象 System.out.println(servletConfig.getServletContext()); super.init(servletConfig); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("HelloServlet4.service"); } }
带参和不带参实际都是一样的,不带参要多加一行代码获取ServletConfig。ServletConfig config = super.getServletConfig();
获取Servlet 程序的别名servlet-name的值:config.getServletName()
获取初始化参数init-param:config.getInitParameter("")
获取ServletContext 对象:config.getServletContext()
//注解配置 @WebServlet(name = "HelloServlet5", value = "/HelloServlet5", initParams = { @WebInitParam(name="username",value = "root"), @WebInitParam(name="url", value = "jdbc:mysql://localhost:3306/test"), @WebInitParam(name = "password", value = "021211") })
1. ServletContext 类
a) 什么是ServletContext?
1、ServletContext 是一个接口,它表示Servlet 上下文对象
2、一个web 工程,只有一个ServletContext 对象实例。
3、ServletContext 对象是一个域对象。
4、ServletContext 是在web 工程部署启动的时候创建。在web 工程停止的时候销毁。
什么是域对象?
域对象,是可以像Map 一样存取数据的对象,叫域对象。这里的域指的是存取数据的操作范围,整个web 工程。
a) ServletContext 类的四个作用
1、获取web.xml 中配置的上下文参数context-param
<!--context-param 是上下文参数(它属于整个web 工程)--> <context-param> <param-name>email</param-name> <param-value>2023@qq.com</param-value> </context-param> <!--context-param 是上下文参数(它属于整个web 工程)--> <context-param> <param-name>phone</param-name> <param-value>15172788750</param-value> </context-param>
@WebServlet("/ContextServlet") public class ContextServlet1 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletConfig config = getServletConfig(); //获取ServletContext对象 ServletContext context = getServletContext(); //可以只用一句代码,如下,是GenericServlet类中自己封装了一个getServletContext()方法,内部就是return this.getServletConfig.getServletContext(); //ServletContext servletContext = this.getServletContext(); String email = context.getInitParameter("email"); System.out.println("context-param 参数 email 的值是:" + email); String phone = context.getInitParameter("phone"); System.out.println("context-param 参数 phone 的值是:" + phone); } }
2、获取当前的工程路径,格式: /工程路径
.getContextPath()
获取工程下css目录的绝对路径是:.getRealPath("/css")
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); System.out.println( "当前工程路径:" + servletContext.getContextPath() ); /** * / 斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到IDEA 代码的web 目录<br/> */ System.out.println(" 工 程 部 署 的 路 径 是 :" + servletContext.getRealPath("/")); System.out.println("工程下 css 目录的绝对路径是:" + servletContext.getRealPath("/css")); System.out.println("工程下 imgs 目录 1.jpg 的绝对路径是:" + servletContext.getRealPath("/imgs/1.jpg")); }
3、获取工程部署后在服务器硬盘上的绝对路径
.getRealPath("/")
4、像Map 一样存取数据
@WebServlet("/ContextServlet1") public class ContextServlet1 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println(servletContext); System.out.println("保存之前:Context1获取username的值是:"+servletContext.getAttribute("username")); //null servletContext.setAttribute("username","ss"); //设置username值等于ss System.out.println("Context1中获取数据 username 的值是:"+servletContext.getAttribute("username")); //ss } }
@WebServlet("/ContextServlet1") public class ContextServlet1 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println(servletContext); System.out.println("保存之前:Context1获取username的值是:"+servletContext.getAttribute("username")); //null servletContext.setAttribute("username","ss"); //设置username值等于ss System.out.println("Context1中获取数据 username 的值是:"+servletContext.getAttribute("username")); //ss } }
当ServletContext对象中保存了username属性ss后在其它的Servlet类中,在去ServletContext对象中的属性username也能获取值ss
ServletContext类它是一个全局作用域,所以说只要在它里面保存了数据,可以在任何地方去获取它保存的数据,除非你主动除掉保存的数据,否则这些数据一直存在