四、Servlet介绍

2020-03-13  本文已影响0人  艾特小师叔

Servlet入门

前言:

在前面的学习过程中,JavaWeb开发,其实是利用网络和HTTP协议,将服务端的数据,发送给客户端,且可以接收客户端的请求,并且对这个请求作出响应。基于这个原理,早期制定了一套根据这样的逻辑与客户端进行交互的接口,而各个服务器,则根据这个接口作出具体的实现。这样,在服务器端,就运行了一套程序,一套用于接收客户端请求,向客户端作出响应程序,这个程序就被称之为Servlet。

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。根据这点,Servlet本身也是一套规范(接口),也是一个具体运行在服务端程序。

狭义的Servlet是指Java语言实现的一个接口。

广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

由于,Servlet生成Web内容,都是使用Java代码生成,所以,开发WEB异常的麻烦。基于这点,Java在Servlet的基础上,衍生出了JSP模板基础,作为Servlet技术的补充点。所以,JSP与Servlet关系,JSP源于Servlet.

注意:

Servlet是服务器实现的一套规范,其具体的API是在服务器中,所以一般不需要导入任何jar包,一般使用服务器中内置jar包。

1.如何使用Servlet

  1. 创建类实现Servlet接口,实现相关方法

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    /**
     * @ClassName: MyServlet 
     * @Description: 创建一个具体的Servlet
     *               1. 定义类实现Servlet接口
     *               2. 重写相关方法
     * @author: Mr.T
     * @date: 2020年2月11日 下午2:41:11
     */
    public class MyServlet implements Servlet{
     
     @Override
     public ServletConfig getServletConfig() {
         System.out.println("==========config==========");
         return null;
     }
     
     @Override
     public void init(ServletConfig arg0) throws ServletException {
         System.out.println("==========init==========");
     }
    
     @Override
     public String getServletInfo() {
         return null;
     }
    
     @Override
     public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
         System.out.println("==========service==========");
     }
     
     @Override
     public void destroy() {
         System.out.println("==========destroy==========");
     }
    
    }
    
    
  2. 注册Servlet,配置对外访问的地址

    程序是在服务器中运行的,如果创建类实现Servlet接口,此时只是创建了一个遵循Servlet规范的类。但是,Servlet本质是一个在服务器中运行的小程序。得通知服务器,我们创建了一个遵循Servlet规范的类,让服务器将这个类装载到Servlet容器中,所以需要进行配置。

    在tomcat中,tomcat会默认监视:web.xml.而web.xml,是一个xml文件。xml中标签和节点,可以根据xml约束dtd等进行限定。这样就可以在web.xml中进行相关程序的配置,tomcat就可以对web.xml中的配置信息进行解析。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
      <display-name>07servlet01</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      
      <!-- 注入servlet -->
      <servlet>
         <!-- servlet别名  方便使用 -->
         <servlet-name>chengfusheng</servlet-name>
         <!-- servlet本质上一个类,包名.类名    类的全路径 -->
         <servlet-class>com.sxt.controller.MyServlet</servlet-class>
         <!-- 
             以上配置是告诉服务器,有一个servlet 可以被使用,servlet的功能是接收客户端的数据 作出响应
              所以得配置一个网络地址,便于客户端进行访问
          -->
      </servlet>
      <!-- 配置网络映射地址  用于客户端访问-->
      <servlet-mapping>
         <servlet-name>chengfusheng</servlet-name>
         <url-pattern>/ergou.do</url-pattern>
      </servlet-mapping>
      
    </web-app>
    

    3.客户端访问Servlet

servlet01.png

2.Servelt被调用的流程

servlet被调用的原理.png
servlet调用顺序.png

3.Servlet的三种实现方式

方式一:直接实现Servlet接口,参看上面示例。

方式二:继承GenericServlet

/**
 * @ClassName: MyServlet02 
 * @Description: 实现Servlet的第二种方式
 * @author: Mr.T
 * @date: 2020年2月11日 下午4:02:12
 */
public class MyServlet02  extends GenericServlet{

    /**
     * 序列号
     *  servlet类主要用于与客户进行数据交互.一般需要将数据序列化进行传输。
     *  如果没有序列化号,1.安全性存在问题. 2.在实际使用中,很多框架,需要存在需要列号,会出现null的 问题。
     */
    private static final long serialVersionUID = -4448635233323484080L;
    
    /**
     *  service 方法  servlet 提供具体的服务的方法
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        
    }

}
<!-- 配置servlet -->
  <servlet>
    <servlet-name>suxiaoxiao</servlet-name>
    <servlet-class>com.sxt.controller.MyServlet02</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>suxiaoxiao</servlet-name>
    <url-pattern>/suxiaoxiao.do</url-pattern>
  </servlet-mapping>

方式三:继承HttpServlet

package com.sxt.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @ClassName: MyServlet03 
 * @Description: servlet的第三种方式  
 * @author: Mr.T
 * @date: 2020年2月11日 下午4:09:18
 */
public class MyServlet03 extends HttpServlet {

    private static final long serialVersionUID = -91495684423730465L;
    /**
     *  重写父类中的service
     *      此时 service中的参数:HttpServletRequest    HttpServletResponse  
     *  这个方法的功能是最强大的
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service");
        resp.getWriter().print("Hello HttpServlet");
    }
    

}

    <!-- 配置servlet -->
  <servlet>
    <servlet-name>myServlet03</servlet-name>
    <servlet-class>com.sxt.controller.MyServlet03</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>myServlet03</servlet-name>
    <url-pattern>/myServlet03.do</url-pattern>
  </servlet-mapping>

注意:

在实际使用中,Servlet一般使用第三种方式,因为第三种方式定制化更强。并且提供了专门根据客户端请求的方法的不同,提共了专门的处理方法。会根据客户端method的值的不同,进行相应的方法调用。

HttpServlet.png

4.Servlet的生命周期

servlet的生命周期,其实是指Servlet类的对象的生命周期,是指Servlet类对象的初始化,及Servlet类对象的销毁。

package com.sxt.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

/**
 * @ClassName: LifeCycleServlet 
 * @Description: 此Servlet类,用于演示Servlet的生命周期
 * @author: Mr.T
 * @date: 2020年2月11日 下午4:45:57
 */
public class LifeCycleServlet extends HttpServlet {
    
    private static final long serialVersionUID = -4411061286729536572L;

    /**
     *  当servlet 对象创建后  需要对属性进行初始化 可以调用 init 
     *  且  init 方法只会执行一次
     */
    @Override
    public void init() throws ServletException {
        System.out.println("==============init 出生了=============");
    }
    
    /**
     *  当有请求,访问当前servlet,那么将有service处理当前请求,每次请求都会调用service
     *  有多少次请求,那么service就会被调用多少次
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("=============service  开始打工=================");
    }
    /**
     *  destory 方法,当服务器停止,开始释放内存,此时调用destory 方法,且只会调用一次。
     */
    @Override
    public void destroy() {
        System.out.println("=================destory  悄悄的离开了=================");
    }   
}

注意:

1.生命周期

Servlet中的init方法,只会执行一次,当servlet对象被初始化后执行一次,进行对象属性值的初始化。

Servlet中的service方法,是处理具体的请求的方法,每次请求时都会执行。

Servlet中destory方法,是用于Servlet对象要被销毁时调用的方法。只会执行一次。可以将内存中的数据,在销毁前做一些处理。

2.Servlet生命周期引发的线程安全问题

在Servlet中,每个Servlet默认只会创建一个实例对象,Servlet是单例的。所以,Servlet是非线程安全的

在使用Servlet时,不要使用成员变量。

3.Servlet的初始化

默认Servlet是在第一被请求时,才会进行Servlet对象的创建,调用init方法,进行属性的初始化。

但是,可以通过在web.xml中配置Servlet的初始化时机,配置信息如下:

  <!-- 配置servlet -->
  <servlet>
    <servlet-name>LifeCycleServlet</servlet-name>
    <servlet-class>com.sxt.controller.LifeCycleServlet</servlet-class>
    <!-- 
        初始的参数 
        如果多组参数  使用 多个 init-param 标签
    -->
    <init-param>
        <param-name>key1</param-name>
        <param-value>value1</param-value>
    </init-param>
    <init-param>
        <param-name>key2</param-name>
        <param-value>value2</param-value>
    </init-param>
     <!-- 
        配置servlet的初始时机 
        只要值大于 0  那么,当服务器启动时就会进行该Servlet的初始化 就会创建该Servlet对象
        
    -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>LifeCycleServlet</servlet-name>
    <url-pattern>/lifeCycle.do</url-pattern>
  </servlet-mapping>
@Override
    public void init() throws ServletException {
        //获取Servlet配置对象
        ServletConfig servletConfig = this.getServletConfig();
        //通过ServletConfig 对象拿到配置参数
        System.out.println(servletConfig.getInitParameter("key1"));
        System.out.println(servletConfig.getInitParameter("key2"));
        System.out.println(this);
        System.out.println("==============init 出生了=============");
    }

5.Servlet使用

Servlet主要功能就是接受客户端的请求,对客户端作出响应。而这个功能由Servlet中的service方法实现,所以Servlet使用,就是service方法的使用,service方法,有ServletRequest和ServletResponse.

ServletRequest,是服务器,将所有的请求信息封装在该对象

ServletResponse,是服务器,将响应信息,封装在该对象中。

而HttpServletRequest是ServletRequest的一个子类,HttpServletResponse是ServletResponse的子类。

5.1.HttpServletRequest使用

package com.sxt.controller;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.tribes.util.Arrays;

/**
 * @ClassName: ServletMethod 
 * @Description: 该方法主要用于演示 Servlet中  request 和  response的核心方法
 * @author: Mr.T
 * @date: 2020年2月11日 下午5:38:10
 */
public class ServletMethod extends HttpServlet {

    private static final long serialVersionUID = -6390310195529724055L;

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //getHttpInfo(req,resp);
        getRequestParam(req,resp);
    }

    /**
     * @Title: getHttpInfo
     * @author: Mr.T   
     * @date: 2020年2月11日 下午5:39:36 
     * @Description: 获取Http请求信息
     * @return: void
     */
    public void getHttpInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取HTTP请求的method值 : get  post  等等
        String method = req.getMethod();
        System.out.println(method);
        //获取HTTP请求的URL地址
        StringBuffer url = req.getRequestURL();
        System.out.println(url);
        //获取请求的资源路径
        String uri = req.getRequestURI();
        System.out.println(uri);
        //获取请求协议
        String protocol = req.getProtocol();
        System.out.println(protocol);
        //获取本地端口
        int localPort = req.getLocalPort();
        System.out.println(localPort);
        //获取请求头  请求头是  key - value 
        String host = req.getHeader("Host");
        System.out.println(host);
    }
    
    /**
     * @Title: getRequestParam
     * @author: Mr.T   
     * @date: 2020年2月11日 下午5:49:25 
     * @Description: 获取请求参数
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @return: void
     */
    public void getRequestParam(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求参数编码格式
        req.setCharacterEncoding("UTF-8");
        //getParameter(name) : 根据name值 获取对应提交的参数
        String name = req.getParameter("name");
        System.out.println(name);
        //getParameterValues(name) :根据name值 获取对应提交的参数,一般用于数组类型的数据,例如复选框
        String[] likes = req.getParameterValues("like");
        System.out.println("爱好:"+Arrays.toString(likes));
        //获取所有的请求参数的name值
        Enumeration<String> parameterNames = req.getParameterNames();
        while(parameterNames.hasMoreElements()) {
            //循环遍历所有的参数的名称
            System.out.println(parameterNames.nextElement());
        }
        //将请求参数封住成一个Map
        Map<String, String[]> parameterMap = req.getParameterMap();
        System.out.println(parameterMap);
        //进行页面跳转 内部转发
        req.getRequestDispatcher("index.jsp").forward(req, resp);
    }
    /**
     * @Title: attributeMethod
     * @author: Mr.T   
     * @date: 2020年2月11日 下午6:09:26 
     * @Description: request 属性相关方法
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @return: void
     */
    public void attributeMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //  向request 作用域设置属性值
        //req.setAttribute(name, o);
        //从request 作用域中取值
        //req.getAttribute(name)
        // 获取request 作用域中所有的属性name值
    }
    /**
     * @Title: scope
     * @author: Mr.T   
     * @date: 2020年2月11日 下午6:11:15 
     * @Description: 根据request 对象 获取其他作用域
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @return: void
     */
    public void scope(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据request 获取与之关联的session
        req.getSession();
        // 获取application作用域
        req.getServletContext();
    }
}

5.2.HttpServletResponse使用

    /**
     * @Title: responseMethod
     * @author: Mr.T   
     * @date: 2020年2月11日 下午6:14:06 
     * @Description: response 响应对象中的核心方法
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @return: void
     */
    public void responseMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应数据的编码
        resp.setCharacterEncoding("UTF-8");
        //设置响应头信息
        resp.addHeader("key11111111111", "value11111222222");
        // 获取打印流对象  向客户端输出数据  一般是文本数据
        //PrintWriter writer = resp.getWriter();
        //writer.print("Hello Servlet");
        // 设置Cookie addCookie
        //resp.addCookie(cookie);
        //获取字节输出流  一般用于文件下载
        //ServletOutputStream outputStream = resp.getOutputStream();
        //地址跳转    重定向
        resp.sendRedirect("index.jsp");
    }
}
上一篇 下一篇

猜你喜欢

热点阅读