java web-servlet(上)

目录

什么是Servlet

Servlet工作模式

Servlet API

Servlet工作原理

servlet接口中的方法

使用IDEA开发一个带有servlet的web

Servlet生命周期

GenericServlet

ServletRequset接口 

ServletResponse接口

ServletConfig

ServletContext(应用域)


什么是Servlet


Java编写的服务器程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。

狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的

Servlet工作模式


  • 客户端发送请求至服务器
  • 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
  • 服务器将响应返回客户端

Servlet API


 Servlet API 包含以下4个Java包:

1.javax.servlet   其中包含定义servlet和servlet容器之间契约的类和接口。

2.javax.servlet.http   其中包含定义HTTP Servlet 和Servlet容器之间的关系。

3.javax.servlet.annotation   其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。

4.javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。
 

Servlet工作原理


 用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个对象。

 对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。

servlet接口中的方法


init(ServletConfig config)

ServletConfig getServletConfig()

service(ServletRequest req,ServletResponse res)

String getServletInfo()

destroy( )


使用IDEA开发一个带有servlet的web


第一步:基础搭建

1.创建一个新工程

2.创建一个新模块

2.1模块右击---->Add Framework Support..(添加框架支持)------>选择Web Application

(一个符合Servlet规范的webpp目录结构。)

第二步:编写Servlet

1.编写Servlet

1.1这个时候发现Servlet.class文件没有。怎么办?

File --> Project Structrue --> Modules---->Dependeencies--->添加Library或者JAR

2.实现jakarta.servlet.Servlet接口中的5个方法。

3.在Servlet当中的service方法中编写业务代码(我们这里连接数据库了。)

4.在WEB-INF目录下新建了一个子目录:lib 并且将连接数据库的驱动jar包放到lib目录下。

第三步:在web.xml文件中完成StudentServlet类的注册

<?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>studentServlet</servlet-name>
        <servlet-class>com.bjpowernode.Student</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>studentServlet</servlet-name>
        <url-pattern>/servlet/student</url-pattern>
    </servlet-mapping>
</web-app>

第四步:给一个html页面,在HTML页面中编写一个超链接

  • student.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--这里的项目名是 /xmm ,无法动态获取,先写死-->
    <a href="/xmm/servlet/student">student list</a>
    </body>
    </html>

    第五步:让IDEA工具去关联Tomcat服务器。

    1.Add Configuration

    2.左上角加号,点击Tomcat Server --> local

    3.Deployment(点击这个用来部署webapp),继续点击加号,部署即可。修改 Application context为:/xmm

    第六步:启动tom服务器,浏览器输入地址

    打开浏览器,在浏览器地址栏上输入:http://localhost:8080/xmm/student.html

    注意:前端发送请求要加项目名

Servlet生命周期


1.网站中所有的Servlet接口实现类的实例对象,只能由Http服务器负责创建。

开发人员不能手动创建Servlet接口实现类的实例对象

2.在默认的情况下,用户第一次请求的时候,自动创建Servlet接口实现类对象。

(调用无参构造方法)

3.关于Servlet类中方法的调用次数?

  • 构造方法只执行一次。
  • init方法只执行一次
  • service方法:用户发送一次请求则执行一次,发送N次请求则执行N次。
  • destroy方法只执行一次

init():  执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。

service(): 第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。

destroy(): 当要销毁Servlet时,Servlet容器就会调用这个方法

getServletInfo():  这个方法会返回Servlet的一段描述,可以返回一段字符串。

getServletConfig():  这个方法会返回由Servlet容器传给init( )方法的ServletConfig对象。

说明:

  • 用户在发送第一次请求的时候Servlet对象被实例化(AServlet的构造方法被执行了。并且执行的是无参数构造方法。)
  • AServlet对象被创建出来之后,Tomcat服务器马上调用了AServlet对象的init方法。
  • 用户发送第一次请求的时候,init方法执行之后,Tomcat服务器马上调用AServlet对象的service方法。
  • 用户在发送第二次,或者第三次,或者第四次请求的时候,Servlet对象并没有新建,还是使用之前创建好的Servlet对象,直接调用该Servlet对象的service方法.

GenericServlet


  1. MyServlet直接实现接口,会将该接口中所有方法实现
    public class MyServlet implements Servlet {
    
        @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 {
    
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }

    2.我们进行改进

    我们让抽象类GenericServlet把不需要的方法实现即可,让service变成抽象类。

    public abstract class GenericServlet  implements Servlet {
        //ServletConfig servletConfig形参,我们不知道传进来的是什么
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
    
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        @Override
        public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    public class MyServlet  extends GenericServlet{
        
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
        }
    }
    

    1.思考第一个问题MyServlet还能使用GenericServlet类中的init方法吗?

         可以。会执行GenericServlet类中的init方法。

    2.思考第二个问题:init方法是谁调用的?

         Tomcat服务器调用的。

    3.思考第三个问题:init方法中的ServletConfig对象是谁创建的?是谁传过来的?

         都是Tomcat干的。

    4.Tomcat服务器先创建了ServletConfig对象,然后调用init方法,将ServletConfig对象传给了          init方法。

    package javax.servlet;
    
    import java.io.IOException;
    import java.util.Enumeration;
    
    public abstract class GenericServlet implements Servlet, ServletConfig,
            java.io.Serializable {
        
        //版本号
        private static final long serialVersionUID = 1L;
    	
        private transient ServletConfig config;
    
        /*
            此构造方法啥也不做,因为Servlet的所有初始化任务都是由init方法完成的。
        */
        public GenericServlet() {
            // NOOP
        }
    
    
        @Override
        public void destroy() {
            // NOOP by default
        }
    
      
        @Override
        public String getInitParameter(String name) {
            return getServletConfig().getInitParameter(name);
        }
    
      
        @Override
        public Enumeration<String> getInitParameterNames() {
            return getServletConfig().getInitParameterNames();
        }
    
        
        @Override
        public ServletConfig getServletConfig() {
            /*通过该方法,可以让子类调用父类私有属性*/
            return config;
        }
    
     
        @Override
        public ServletContext getServletContext() {
            return getServletConfig().getServletContext();
        }
    
     
        @Override
        public String getServletInfo() {
            return "";
        }
    
    
        @Override
        public void init(ServletConfig config) throws ServletException {
            /*该方法是形参,tomcat将实参传进来,然后通过this.config=config
              把局部变量变为全局变量。*/
            this.config = config;
          //Tomcat首先调用init()有参方法,然后调用init()无参方法。
            this.init();
        }
    
       /*目的是让子类重写init()方法的无参构造方法。*/
        public void init() throws ServletException {
            // NOOP by default
        }
    
     
        public void log(String msg) {
            getServletContext().log(getServletName() + ": " + msg);
        }
    
    
        public void log(String message, Throwable t) {
            getServletContext().log(getServletName() + ": " + message, t);
        }
    
    
        @Override
        public abstract void service(ServletRequest req, ServletResponse res)
                throws ServletException, IOException;
    
     
        @Override
        public String getServletName() {
            return config.getServletName();
        }
    }
    
    package GenericServlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class MyServlet  extends GenericServlet{
        //我们需要在MyServlet中重写init方法
        //子类重写第二个(无参的)就可
        public void  init(){
            System.out.println("MyServlet init() method execute!");
        }
    
    
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            //我想在MyServlet子类中使用Servlet对象怎么办?
            ServletConfig config=this.getServletConfig();
        }
    }
    
    

ServletRequset接口 


Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象,并把这个对象传递给Servlet的Sevice( )方法。其中,ServletRequest对象内封装了关于这个请求的许多详细信息。

ServletResponse接口


  javax.servlet.ServletResponse接口表示一个Servlet响应,在调用Servlet的Service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给Service( )方法。ServletResponse隐藏了向浏览器发送响应的复杂过程。
 

ServletConfig


  • 什么是ServletConfig?
    • ServletConfig是一个接口。是Servlet规范中的一员。
    • ServletConfig对象中封装了标签中的配置信息。(web.xml文件中servlet的配置信息)
  • 一个Servlet对应一个ServletConfig对象。
  • Servlet对象是Tomcat服务器创建,并且ServletConfig对象也是Tomcat服务器创建。并且默认
  • 情况下,他们都是在用户发送第一次请求的时候创建。
  • Tomcat服务器调用Servlet对象的init方法的时候需要传一个ServletConfig对象的参数给init方法。
  • ServletConfig接口的实现类是Tomcat服务器给实现的。(Tomcat服务器说的就是WEB服务器。)
  • ServletConfig接口有哪些常用的方法?
    public String getInitParameter(String name); // 通过初始化参数的name获取value
    public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name
    public ServletContext getServletContext(); // 获取ServletContext对象
    public String getServletName(); // 获取Servlet的name

    以上方法在Servlet类当中,都可以使用this去调用。因为GenericServlet实现了ServletConfig接口。

ServletContext(应用域)


  • 一个ServletContext对象通常对应的是一个web.xml文件。
  • 只要在同一个webapp当中,只要在同一个应用当中,所有的Servlet对象都是共享同一个ServletContext对象的。
  • ServletContext对象在服务器启动阶段创建,在服务器关闭的时候销毁。这就是ServletContext对象的生命周期。ServletContext对象是应用级对象。
  • ServletContext是一个接口,Tomcat服务器对ServletContext接口进行了实现。
  • ServletContext对象的创建也是Tomcat服务器来完成的。启动webapp的时候创建的 。

ServletContext接口中有哪些常用的方法?

public String getInitParameter(String name); // 通过初始化参数的name获取value
public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name
<!--以上两个方法是ServletContext对象的方法,这个方法获取的是什么信息?是以下的配置信息-->
<context-param>
    <param-name>pageSize</param-name>
    <param-value>10</param-value>
</context-param>
<context-param>
    <param-name>startIndex</param-name>
    <param-value>0</param-value>
</context-param>
<!--注意:以上的配置信息属于应用级的配置信息,一般一个项目中共享的配置信息会放到以上的标签当中。-->
<!--如果你的配置信息只是想给某一个servlet作为参考,那么你配置到servlet标签当中即可,使用ServletConfig对象来获取。-->
// 获取应用的根路径(非常重要),因为在java源代码当中有一些地方可能会需要应用的根路径,这个方法可以动态获取应用的根路径
// 在java源码当中,不要将应用的根路径写死,因为你永远都不知道这个应用在最终部署的时候,起一个什么名字。
public String getContextPath();
//String contextPath = application.getContextPath();
// 获取文件的绝对路径(真实路径)
public String getRealPath(String path);
// 通过ServletContext对象也是可以记录日志的
public void log(String message);
public void log(String message, Throwable t);
// 这些日志信息记录到哪里了?
// localhost.2021-11-05.log

// Tomcat服务器的logs目录下都有哪些日志文件?
//catalina.2021-11-05.log 服务器端的java程序运行的控制台信息。
//localhost.2021-11-05.log ServletContext对象的log方法记录的日志信息存储到这个文件中。
//localhost_access_log.2021-11-05.txt 访问日志
// ServletContext对象还有另一个名字:应用域(后面还有其他域,例如:请求域、会话域)

// 如果所有的用户共享一份数据,并且这个数据很少的被修改,并且这个数据量很少,
// 可以将这些数据放到ServletContext这个应用域中

// 存(怎么向ServletContext应用域中存数据)
public void setAttribute(String name, Object value); // map.put(k, v)
// 取(怎么从ServletContext应用域中取数据)
public Object getAttribute(String name); // Object v = map.get(k)
// 删(怎么删除ServletContext应用域中的数据)
public void removeAttribute(String name); // map.remove(k)

注意:

以后我们编写Servlet类的时候,实际上是不会去直接继承GenericServlet类的,因为我们是B/S结构的系统,这种系统是基于HTTP超文本传输协议的,在Servlet规范当中,提供了一个类叫做HttpServlet,它是专门为HTTP协议准备的一个Servlet类。我们编写的Servlet类要继承HttpServlet。(HttpServlet是HTTP协议专用的。)使用HttpServlet处理HTTP协议更便捷。但是你需要直到它的继承结构:

jakarta.servlet.Servlet(接口)【爷爷】
jakarta.servlet.GenericServlet implements Servlet(抽象类)【儿子】
jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)【孙子】

我们以后编写的Servlet要继承HttpServlet类。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值