Servlet—环境,生命周期,session,重定向,转发

Servlet简介(什么是Servlet)

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。

Eclipse JSP/Servlet 环境搭建:

Tomcat下载网址:Apache Tomcat® - Welcome!
然后点击Tomcat9就可以,太新版的也不太好,用旧版就可以,Tomcat8也可以

 然后点击进去往下滑,选择自己电脑对应的是32位还是64位

 

 解压文件夹如下:

  • bin:二进制执行文件。里面最常用的文件是startup.bat,如果是 Linux 或 Mac 系统启动文件为 startup.sh。
  • conf:配置目录。里面最核心的文件是server.xml。可以在里面改端口号等。默认端口号是8080,也就是说,此端口号不能被其他应用程序占用。
  • lib:库文件。tomcat运行时需要的jar包所在的目录
  • logs:日志
  • temp:临时产生的文件,即缓存
  • webapps:web的应用程序。web应用放置到此目录下浏览器可以直接访问
  • work:编译以后的class文件。
然后点击startup.bat启动Tomcat,如下图

接着我们在浏览器中输入 http://localhost:8080/,如果弹出如下界面,表示tomcat安装成功并且启动起来了:

在Eclipse中window然后点击preferences然后选择server的RunTime Environment中的add添加刚才下载的Tomcat

实现Servlet

1、implements Servlet 2、extends Servlet 3、extends HttpServlet(最常用的)

写相关servlet类

1.首先,配置Servlet要加入Servlet的api,将Tomcat全加进去可以
点击Add Library选择你的Tomcat文件的位置就可以
2.然后创建一个类继承HttpServlet,如下列代码所示extends HttpServlet
package com.demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class D extends HttpServlet{    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
           //respon的getWriter方法服务端回应客户端信息
        response.getWriter().write("66");
    }
}
配置映射文件(创建Web项目的时候一定要创建Web.xml)映射文件就在web.xml里面配置例如我的类名是D所以我的web.xml配置如下代码所示
<servlet>
      <servlet-name>D</servlet-name>
      <servlet-class>com.hzj.D</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>D</servlet-name>
      <url-pattern>/D</url-pattern>
  </servlet-mapping>
以上的代码意思就是一启动项目,就会启动Tomcat服务器,然后会根据映射文件来访问对应的Servlet,然后测试一下看能不能输出,运行可以输出
3.request的getParameter方法接受客户端传来的数据信息,如下列代码获取传来的name和age
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
          String name=request.getParameter("name");
        String age=request.getParameter("age");
        response.getWriter().write("nihao");
        System.out.println(name+" "+age);
    }
}

然后控制台可以看到djm 21

Servlet的url配置方式, (注意@WebServlet("/***")这个注释也可以,不过web.xml的优先级高,先去访问web.xml)

精确路径 :/abc,如LX03精确路径
<servlet>
      <servlet-name>LX03</servlet-name>
      <servlet-class>com.demo.LX03</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>LX03</servlet-name>
      <url-pattern>/LX03</url-pattern>
  </servlet-mapping>
输出LX03
以do结尾的:*.do,以do结尾的去找LX04
 <servlet>
      <servlet-name>LX04</servlet-name>
      <servlet-class>com.demo.LX04</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>LX04</servlet-name>
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>
输出LX04
如果没有就是找这个所有的匹配的: /(拦截)
 <servlet>
      <servlet-name>D</servlet-name>
      <servlet-class>com.demo.D</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>D</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
输出D

Servlet从创建到销毁所经历的方法,Servlet的生命周期(初始化,提供服务,销毁)

void init(ServletConfig) 
void service(ServletRequest,ServletResponse)
void destory()
init方法是单例只执行一次,并且只有程序执行的时候才会被调用,Tomcat启动不会调用,每一次访问该Servlet都会执行Service方法,服务器关闭或重启销毁Servlet执行Destory方法,Servlet是单例的
什么时候被调用: init()方法只会被调用一次,是在第一次访问(or 创建) Servlet 的时候被调用,在后续的每次请求时都不会再调用 init() 方法了。
作用: init()方法用于 Servlet 的初始化,可以简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
注意:Servlet、ServletConfig、ServletContext之间的联系
一个Servlet对应一个ServletConfig,100个Servlet对应100个ServletConfig,所有的Servlet共享一个ServeletContext对象
SevletContext是什么?什么时候被创建?什么时候被销毁?创建几个?
ServletContext被翻译为:Servlet上下文【Context一般被翻译为上下文】
一个webapp只有一个web.xml文件,web.xml文件服务器启动阶段被刷新
ServletContext在服务器启动阶段被实例化
ServletContext在服务器关闭的时候被销毁
ServletContext对应的web.xml文件,是web.xml文件的代表
public LX03() {
        super();
        System.out.println("---LX03---");
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(this);
}
 Servlet 调用inti方法的时间
     -- 可以是用户第一次访问该 Servlet 时——web.xml 文件的<load-on-startup>标签
     不配置或者配置为小于零的数;
     -- 也可以指定 Servlet 在服务器第一次启动时调用 init 方法——web.xml 文件
     的<load-on-startup>标签配置为大于等于0的数。
 当用户调用一个 Servlet时,会创建一个 Servlet 实例,
 每个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或者 doPost 方法。
只输出一次---Lx03---多次输出一样的内存地址,只执行一次,如下图

web.xml编码,设为utf-8

<servlet>
      <servlet-name>LX03</servlet-name>
      <servlet-class>com.demo.LX03</servlet-class>
      <init-param>
          <param-name>encode</param-name>
          <param-value>UTF-8</param-value>
      </init-param>
  </servlet>
  <servlet-mapping>
      <servlet-name>LX03</servlet-name>
      <url-pattern>/LX03</url-pattern>
  </servlet-mapping>
写入以下代码获取
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletConfig config = this.getServletConfig();
        String encode = config.getInitParameter("encode");
        System.out.println(encode);    
  }
输出UTF-8

load-on-startup,(默认配置的@WebServlet注解是-1,所以默认就是-1)如下图LX03的为3,LX04的为0

在servlet的配置当中,<load-on-startup>1</load-on-startup>的含义是:标记容器是否在启动的时候就加载这个servlet。

当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。

正数的值越小,启动该servlet的优先级越高。

 如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服务器会根据load-on-startup的大小依次对servlet进行初始化。不过即使我们将load-on-startup设置重复也不会出现异常,服务器会自己决定初始化顺序。

配置load-on-startup后,servlet在startup后立即加载,但只是调用servlet的init()方法,用以初始化该servlet相关的资源。初始化成功后,该servlet可响应web请求;如未配置load-on-startup,容器一般在第一次响应web请求时,会先检测该servlet是否初始化,如未初始化,则调用servlet的init()先初始化,初始化成功后,再响应请求。

PS:一般我们在开发web应用时,都会配置这个参数,有两个好处:1、如果初始化过程失败,则容器会提示启动失败,此时我们能够提前知道相关错误;2、配置该参数相当于将初始化servlet的工作转移到容器启动过程,使得容器只要启动成功后,就可立即响应web请求。

 <servlet>
      <servlet-name>LX03</servlet-name>
      <servlet-class>com.demo.LX03</servlet-class>
      <init-param>
          <param-name>encode</param-name>
          <param-value>UTF-8</param-value>
      </init-param>
      <load-on-startup>3</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>LX03</servlet-name>
      <url-pattern>/LX03</url-pattern>
  </servlet-mapping>
  
  <servlet>
      <servlet-name>LX04</servlet-name>
      <servlet-class>com.demo.LX04</servlet-class>
      <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>LX04</servlet-name>
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>
当运行LX03的时候,会先输出LX04
如下图输出,所以load-on-startup值越小,优先级越高,默认是-1

request和response

Cookie

cookie可以保存会话状态,但是在这个会话状态是保留在1客户端的。只cookie清除或者cookie失效这个会话状态就没有了。

cookie是保存在浏览器客户端的cookie可以保存在浏览器的缓存中,浏览器关闭cookie消失。cookie也可以保存在客户端的硬盘文件中,浏览器关闭cookie还在除非cookie失效

cookie实现的功能有:保留购物车商品的状态在客户端上,十天内免登录

添加两个cookie

Cookie cookie = new Cookie("D","H");
Cookie cookie2 = new Cookie("H","D");

response.addCookie(cookie);
response.addCookie(cookie2);

打开浏览器可以看到存储的两个cookie

Session会话。

session是自己的,别人拿不到我放的session
什么是session,session就是一次会话,tomcat启动会发送请求,多次请求,只要没结束这个会话,就是一次session
从客户端到服务器发送请求,服务器响应客户端就是一次请求,session就是多次请求,多次响应,从开始到关闭。
我的浏览器和tomcat通信放的session我自己可以取出来,别人取不出来,因为我的浏览器和tomcat通信属于一次session

cookie可以将会话保存到客户端,session可以将会话保存到服务器端

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //设置session名字为djm
          HttpSession session = request.getSession();
        session.setAttribute("name","djm");
        
    }
 //另一个servlet
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //然后获取上个servlet设置的session
          HttpSession session = request.getSession();
        Object object = session.getAttribute("name");
        System.out.println(object);
        
    }
首先启动LX03
地址栏在输入LX04,这时候就可以拿到LX03的Session

 

前台获取数据session

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");    
        HttpSession session = request.getSession();
        session.setAttribute("name",name);    
    }
  //另一个servlet
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //然后获取上个servlet设置的session
          HttpSession session = request.getSession();
        Object object = session.getAttribute("name");
        System.out.println(object);
        
  }
地址栏输入HHH获取HHH
这时候换为LX04,控制台会输出HHH,并且可以获取多次,缓存的原因

 

注意:session默认为true,true的时候,有的话返回,没有session创建新的session,false的话,有的话返回,没有返回null

servletcontext,每个人都可以拿到获取信息(和session差不多的方式)request.getServletContext();获取,servletcontext是同一个,是共享的

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name=request.getParameter("name");
        ServletContext application = request.getServletContext();
        application.setAttribute("name",name);    
    }
  //另一个servlet
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //然后获取上个servlet设置的application
        ServletContext application = request.getServletContext();
        Object object = application.getAttribute("name");
        System.out.println(object);
        
    }
设置名字
访问

 

request,注意request在另一个servlet取不到,这个是可以自己传,自己收到(session在另一个servlet可以取到,servletcontext可以在另一个浏览器取到)

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name=request.getParameter("name");
        request.setAttribute("name",name);
        Object object = request.getAttribute("name");
        System.out.println(object);
    }
如下图

重定向

public class Redirect extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
            String name=request.getParameter("name");
          response.sendRedirect("/Servlet/RedirectTest");        
    }
}
在前台获取数据重定向,因为重定向是请求转发了两次,所以RedirectTest拿不到在Redirect写的数据所以会显示null,所以下面这个写法不能接收到
public class RedirectTest extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String name=request.getParameter("name");
       System.out.println(name);
    }
}
这时候还没有回车,运行的Redirect,然后一回车就会跳转到RedirectTest
回车之后
在浏览器查看会看到有两次请求,先是到Redirect然后到RedirectTest
具体流程如下图所示
下面这个就可以,直接就可以获取到Redirect传来的数据,直接写好地址栏的
public class Redirect extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String name=request.getParameter("name");
       response.sendRedirect("/Servlet/RedirectTest?name"+name);        
    }    
}

转发

public class Redirect extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //转发 request
        String name=request.getParameter("name");
        request.getRequestDispatcher("/RedirectTest").forward(request, response);
    }    
}
public class RedirectTest extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String name=request.getParameter("name");
       System.out.println(name);
    }
}
转发流程图,如下
浏览器可以查看是这样的

转发和重定向区别

1、请求次数

重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;

2、地址栏不同

重定向地址栏会发生变化,转发地址栏不会发生变化;

3、是否共享数据

重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);

4、跳转限制

重定向可以跳转到任意URL,转发只能跳转本站点资源;

5、发生行为不同

重定向是客户端行为,转发是服务器端行为;

注意:把数据放到request中,只有转发才能拿出来,因为重定向是发送了两次请求,而转发则是一次请求,两次请求的话会发生变化,所request在重定向的时候拿不到

Servlet九大内置对象

 

 

 

 

posted @ 2022-11-08 16:27  花海~  阅读(48)  评论(0)    收藏  举报