JavaWeb-Servlet(上)

目录

1 关于系统结构分析

1.1 系统架构包括什么形式?

1.2 C/S架构?

1.3 B/S架构

2 配置Tomcat服务器

2.1 Tomcat概述

2.2 启动Tomcat

3 编写第一个webapp

4 模拟servlet本质

5 开发第一个Servlet

5.1 开发步骤

5.2 Servlet中编写JDBC连接数据库

6 使用IDEA工具开发Servlet

7 Servlet中的方法概述

8 适配器模式改造Servlet

9 ServletConfig接口详解

10 ServletContext接口详解

10.1 ServletContext概述

10.2 ServletContext作用

10.3 应用域


1 关于系统结构分析

1.1 系统架构包括什么形式?

        C/S架构
        B/S架构


1.2 C/S架构?

Client/ Server (客户端/服务器)
C/S架构的特点:需要安装特定的客户端软件。
C/S架构的系统优点和缺点分别是什么?
优点:

  • 速度快(软件中的数据大部分都是集成到客户端软件当中的,很少量的数据从服务器端传送过来,所以C/S结构的系统速度快)
  • 体验好(速度又快,界面又酷炫,当然体验好了。)
  • 界面酷炫(专门的语言去实现界面的,更加灵活。)
  • 服务器压力小(因为大量的数据都是集成在客户端软件当中,所以服务器只需要传送很少的数据量,当然服务器压力小。)
  • 安全(因为大量的数据是集成在客户端软件当中的,并且客户端有很多个,服务器虽然只有- 个,就算服务器那边地震了,火灾了,服务器受损了,问题也不大,因为大量的数据在多个客户端.上有缓存,有存储,所以从这个方面来说,C/S结构的系统比较安全。)

缺点:

  • 升级维护比较差劲。 (升级维护比较麻烦。成本比较高。每一个客户端软件都需要升级。有一 些软件不是那么容易安装的。)

1.3 B/S架构

我们经常使用的百度、京东等等网页就是B/S架构。

B/S架构的优点和缺点。

优点:

  • 升级维护方便,成本比较低。 (只需要升级服务器端即可。)
  • 不需要安装特定的客户端软件,用户操作极其方便。只需要打开浏览器,输入网址即可。

缺点:

  • 速度慢(不是因为带宽低的问题,是因为所有的数据都是在服务器上,用户发送的每-个请求都是需要服务器全身心的响应数据,所以B/S结构的系统在网络中传送的数据量比较大。)
  • 体验差(界面不是那么酷炫, 因为浏览器只支持三个语言HTML CSS JavaScript。 在加上速度慢。)
  • 不安全(所有的数据都在服务器上, 只要服务器发生火灾,地震等不可抗力,最终数据全部丢失。)

2 配置Tomcat服务器

2.1 Tomcat概述

配置Tomcat服务器之前先安装jdk并配置好环境变量

关于Tomcat的安装:Tomcat是绿色版解压即是安装

关于Tomcat服务器的目录:

JavaWeb-Servlet(上)_第1张图片

bin:这个目录是Tomcat服务器的命令文件存放的目录,比如:启动Tomcat,关闭Tomcat等。

conf:这个目录用来存放Tomcat服务器配置文件

lib:是Tomcat服务器的核心程序目录,因为Tomcat服务器是Java语言编写的,这里的jar包都是class文件

logs:Tomcat服务器的日志文件目录,Tomcat服务器启动等信息都会在这个目录下生成日志

temp:Tomcat服务器的临时目录,存放临时文件

webapps:存放大量的webapp——(web application:web应用)

work:存放JSP文件翻译后的Java文件以及编译之后的class文件

2.2 启动Tomcat

bin目录下有一个文件:startup.bat,通过它可以启动Tomcat服务器

xxx.bat是什么文件?bat文件是Windows操作系统专用的,bat文件是批处理文件,这种文件中可以编写大量的Windows的dos命令,然后执行bat文件就相当于批量的执行dos命令

startup.sh,这个文件在Windows当中无法执行,在Linux中可以使用。

分析startup.bat文件得出,执行这个命令,实际上最后是执行:catalina.bat文件

JavaWeb-Servlet(上)_第2张图片

catalina.bat文件中有这样一行配置:MAINCLASS=org.apache.catalina.startup.Bootstrap(这个类就是main方法所在的类)

Tomcat服务器是Java语言写的,既然是Java语言写的,那么启动Tomcat服务器就是执行main方法

我们尝试在dos窗口输入startup.bat来启动Tomcat服务器。启动Tomcat服务器只配置path对应的bin目录是不够的,有两个环境变量需要配置:

JAVA_HOME=JDK的根             CATALINA_HOME=Tomcat服务器的根   

这样就能成功启动Tomcat服务器,我们也终于发现了最开始学习Java时配置的JAVA_HOME到底有什么用,这就是Java的家。

总结一下:配置Tomcat服务器需要的环境变量有哪些?

JAVA_HOME=JDK的根   CATALINA_HOME=Tomcat服务器的根   

PATH=%JAVA_ HOME%\bin;%CATALINA_ HOME%\bin

启动Tomcat:startup或者startup.bat

关闭Tomcat:stop(shutdown.bat重命名为stop.bat,为什么修改?以为与Windows的关机命令重复了,避免冲突或者是是避免使用错误导致电脑关机)

怎么在浏览器测试Tomcat服务器配置成功?

我们知道要想访问一个服务器需要输入IP地址和端口号即可,Tomcat的IP就是本机IP,端口号就是8080,经测试没有问题 

JavaWeb-Servlet(上)_第3张图片

3 编写第一个webapp

第一步:找到CTALINA_HOME\webapps目录,因为所有的webapp都要放到webapps目录下。没有为什么,这是王八的屁股--规定,如果不放到这,Tomcat服务器找不到你的应用。

第二步:在CTALINA_HOME\webapps目录新建一个子目录,起名:oa。这个名字就是你的webapp的名字

第三步:在oa目录下新建资源文件,例如:index.html。接着编写html内容

第四步:启动Tomcat服务器

第五步:打开浏览器输入URL:http://127.0.0.1:8080/oa/index.html

注意:在编写html时,绝对路径不需要添加html://127.0.0.1:8080,直接以/开始带项目名就是一个绝对路径,如本次项目中用户登录这就是绝对路径

JavaWeb-Servlet(上)_第4张图片

 在项目目录下编写两个html文件

 两个HTML文件内容为:



	
		index
	
	
		

我的第一个页面

用户登录


	
		login
	
	
		

用户登录

用户名:
密 码:

JavaWeb-Servlet(上)_第5张图片不过本次第一个项目出了点小问题,输入URL无法访问到html资源,将服务器重启也不行,但是将dos窗口关闭重开就可以了不知道为啥捏。

4 模拟servlet本质

做了这么多准备终于到了servlet部分

JavaWeb-Servlet(上)_第6张图片

根据上图,我们 发现要想完成一个完整的web服务,需要这四个部分,现在来模拟servlet的本质

主要模拟三部分:制定servlet规范;充当tomcat服务器开发者;充当webapp的开发者。

JavaWeb-Servlet(上)_第7张图片

编写的三个webapp都要实现Servlet接口

当启动Tomcat服务器时,要求用户输入相应路径来启动相应的java小程序,这时java小程序和路径要有一个对照关系。这个对照关系就需要Java程序员来完成,需要一个配置文件。然后需要Tomcat服务器来解析配置文件。

代码:

Tomcat服务器:

//充当Tomcat服务器的开发者
package org.apache;

import java.util.Scanner;
import java.util.Properties;
import java.io.FileReader;
import javax.servlet.Servlet;

public class Tomcat
{
	public static void main(String[] args) throws Exception{
		System.out.println("Tomcat服务器启动成功,开始接收用户访问。");
		//用Scanner模拟用户的请求

		System.out.print("请输入您的访问路径:");
		Scanner sc = new Scanner(System.in);
		String key = sc.nextLine();

		//Tomcat服务器应该根据用户输入的请求路径获取相应的xxxServlet
		FileReader reader = new FileReader("web.properties");
		Properties pro = new Properties();
		pro.load(reader);
		reader.close();

		//通过key获取value
		String className = pro.getProperty(key);
		//通过反射机制获取对象
		Class clazz =  Class.forName(className);
		Object obj = clazz.newInstance();
		
		Servlet servlet = (Servlet)obj;
		servlet.service();
		
	}
}

Servlet:

package javax.servlet;

public interface Servlet
{
	void service();
}

 java小程序:

package com.itzw.servlet;

import javax.servlet.Servlet;

public class UserloginServlet implements Servlet
{
	public void service(){
		System.out.println("UserloginServlet's service....");
	}
}

结果:

JavaWeb-Servlet(上)_第8张图片

由此我们可以看到,在实际开发中,对于javaweb程序员来说只需要做两件事:编写一类实现Servlet接口;编写配置文件指定请求路径和类名的关系。

同时我们也发现,Tomcat服务器的源码中已经规定好了配置文件的路径和名字,已经写死了,不能随便写。

Servlet规范包括什么?

规范了哪些接口、规范了哪些类、规范了一个web应用中应该有哪些配置文件、规范了一个web应用中配置文件的名字、规范了一个web应用中配置文件的内容、规范了一个合法有效的web应用它的目录结构应该是怎样的。

5 开发第一个Servlet

5.1 开发步骤

第一步:在webapps目录下新建一 个目录,起名crm (这个crm就是webapp的名字) 。当然,也可以是其它项目,比如银行项目,可以创建一个目录bank, 办公系统可以创建一个oa。
注意: crm就是这个webapp的根

第二步:在webapp的根下新建一 个目录: WEB-NF
注意:这个目录的名字是Servlet规范中规定的,必须全部大写,必须一模一 样。必须的必须。

第三步:在WEB-INF目录下新建一 个目录: classes
注意:这个目录的名字必须是全部小写的classes。 这也是Servlet规范中规定的。另外这个目录下一定存放的是Java程序编译之后的class文件(这里存放的是字节码文件)。

第四步:在WEB-INF目录下新建一 个目录: lib
注意:这个目录不是必须的。但如果一个webapp需 要第三方的jar包的话,这个jar包要放到这个lib目录下,这个目录的名字也不能随意编写,必须是全部小写的lib。例如java语言连接数据库需要数据库的驱动jar包。那么这个jar包就一定要放到ib目录下。这Servlet规范中规定的。

第五步:在WEB-INF目录下新建一个文件: web.xml
注意:这个文件是必须的,这个文件名必须叫做web.xml。这个文件必须放在这里。一个合法的webapp, web.xml文件是必须的,这个web.xml文件就是一个配置文件, 在这个配置文件中描述了请求路径和Servlet类之间的对照关系。这个文件最好从其他的webapp中拷贝,最好别手写。没必要。复制粘贴即可。

第六步:编写一个java程序,这个小java程序也不能随意开发,必须实现Servlet接口。                     编写小程序时,不一定要把源码写在classes目录中,只要把编译生成的class文件放入其中即可
注意:从JakartaEE9开始,Servlet接口的全名变了:jakarta.servlet.Servlet

第七步:编译我们编写的HelloServlet
重点:你怎么能让你的HelloServlet编译通过呢?配置环境变量CLASSPATH
CLASSPATH=.;D:\Java\dev\Javaweb\Tomcat\apache-tomcat-10.0.12\lib\servlet-api.jar                  CLSSPATH环境变量的作用就是,当编译java文件时,会去这个路径寻找需要的class文件前面的“.”表示在当前目录寻找,“;”表示去别的目录寻找。
思考问题:以上配置的CLASSPATH和Tomcat服务器运行有没有关系?
没有任何关系,以上配置这个环境变 量只是为了让你的HelloServlet能够正常编译生成class文件。

第八步:将以上编译之后的HelloSenvlet.lass文件拷贝到WEB-INF\classes目录下。

第九步:在web.xml文件中编写配置信息,让"请求路径"和"Servlet类名”关联在一起。
这一步用专业术语描述:在web.xml|文件中注册Servlet类。





    
    
    
        fjafnjeml
        
        com.bjpowernode.servlet.HelloServlet
    

    
    
        
        fjafnjeml
        
        
        
        /daw/dw/fe/qw
    

第十步:启动Tomcat服务器

第十一步:打开浏览器,在浏览器地址栏上输入一个url, 这个URL必须是:http://127.0.0.1:8080/crm/zw/wzj/hhh                                                                                        浏览器路径复杂可以使用超链接,HTML页面只能放在WEB-INF目录外

注意一点:解决Tomcat服务器在DOS命令窗口中的乱码问题(控制台乱码)
将CATALINA_ HOME/conf/logging.properties文件中的内容修改如下: .
java.util.logging.ConsoleHandler.encoding = GBK

代码:

java小程序:

package com.bjpowernode.servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.ServletConfig;
import java.io.IOException;
import java.io.PrintWriter;


public class HelloServlet implements Servlet{

	// 5个方法
	public void init(ServletConfig config) throws ServletException{
	
	}

	public void service(ServletRequest request,ServletResponse response)
		throws ServletException , IOException{

		// 向控制台打印输出
		System.out.println("My First Servlet, Hello Servlet");

		// 设置响应的内容类型是普通文本或html代码
		// 需要在获取流对象之前设置,有效。
		response.setContentType("text/html");

		// 怎么将一个信息直接输出到浏览器上?
		// 需要使用ServletResponse接口:response
		// response表示响应:从服务器向浏览器发送数据叫做响应。
		PrintWriter out = response.getWriter();
		
		// 设置响应的内容类型时不要在获取流之后设置。
		//response.setContentType("text/html");

		out.print("Hello Servlet, You are my first servlet!");

		// 浏览器是能够识别html代码的,那我们是不是应该输出一段HTML代码呢?
		out.print("

hello servlet,你好Servlet

"); // 这是一个输出流,负责输出字符串到浏览器 // 这个输出流不需要我们刷新,也不需要我们关闭,这些都由Tomcat来维护。 /* out.flush(); out.close(); */ } public void destroy(){ } public String getServletInfo(){ return ""; } public ServletConfig getServletConfig(){ return null; } }

当我们想把内容输出到浏览器时需要写入这样的代码:PrintWriter out = response.getWriter();      response表示相应:从服务器向浏览器发送数据叫做响应。然后out.print("...");写入想要输出的内容即可。

当我们想在浏览器输出html语言时,需要写入这样的代码:response.setContentType("text/html");这表示设置相应的内容类型是普通文本或者html代码,需要再获取流对象之前设置,也就是在response那条代码之前。

5.2 Servlet中编写JDBC连接数据库

和之前学的类似,只需把JDBC代码放入service方法中即可,不过如今我们需要把数据输出到浏览器上,所以添加几行html相关代码即可,这个上一小节有学到。注意要将jdbc连接数据库的jar包加入到lib目录中,并且web.xml文件中添加一个新的目录与java小程序的对应关系。代码如下:

package com.bjpowernode.servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.ServletConfig;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;


public class StudentServlet implements Servlet{

	public void init(ServletConfig config) throws ServletException{
	
	}

	public void service(ServletRequest request,ServletResponse response)
		throws ServletException , IOException{

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print("学生信息如下:" + "
"); // 编写JDBC代码,连接数据库,查询所有学生信息。 Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try{ // 注册驱动 (com.mysql.jdbc.Driver,这个已过时。) // 新版本中建议使用:com.mysql.cj.jdbc.Driver驱动。 Class.forName("com.mysql.cj.jdbc.Driver"); // 获取连接 String url = "jdbc:mysql://127.0.0.1:3306/db1"; String user = "root"; String password = "123456"; conn = DriverManager.getConnection(url, user, password); // 获取预编译的数据库操作对象 String sql = "select id,loginName,loginPwd,realName from t_user"; ps = conn.prepareStatement(sql); // 执行SQL rs = ps.executeQuery(); // 处理查询结果集 while(rs.next()){ String id = rs.getString("id"); String loginName = rs.getString("loginName"); String loginPwd = rs.getString("loginPwd"); String realName = rs.getString("realName"); //System.out.println(no + "," + name); out.print(id + "," + loginName + "," + loginPwd +"," + realName + "
"); } }catch(Exception e){ e.printStackTrace(); }finally{ // 释放资源 if(rs != null){ try{ rs.close(); }catch(Exception e){ e.printStackTrace(); } } if(ps != null){ try{ ps.close(); }catch(Exception e){ e.printStackTrace(); } } if(conn != null){ try{ conn.close(); }catch(Exception e){ e.printStackTrace(); } } } } public void destroy(){ } public String getServletInfo(){ return ""; } public ServletConfig getServletConfig(){ return null; } }
	    
        servletJDBC
        com.bjpowernode.servlet.StudentServlet
    

    
        servletJDBC
        /zw/wzj/aaa
    

结果:

JavaWeb-Servlet(上)_第9张图片

6 使用IDEA工具开发Servlet

  • 第一步:New Project(我比较习惯先创建一个Empty Project【空工程】,然后在空工程下新建Module【模块】,这不是必须的,只是一种习惯,你可以直接新建非空的Project),这个Empty Project起名为:javaweb(不是必须的,只是一个名字而已。一般情况下新建的Project的名字最好和目录的名字一致。)
  • 第二步:新建模块(File --> new --> Module...)
    • 这里新建的是一个普通的JavaSE模块(这里先不要新建Java Enterprise模块)
    • 这个Module自动会被放在javaweb的project下面。
    • 这个Module起名:servlet01
  • 第三步:让Module变成JavaEE的模块。(让Module变成webapp的模块。符合webapp规范。符合Servlet规范的Module)
    • 在Module上点击右键:Add Framework Support...(添加框架支持)
    • 在弹出的窗口中,选择Web Application(选择的是webapp的支持)
    • 选择了这个webapp的支持之后,IDEA会自动给你生成一个符合Servlet规范的webpp目录结构。
    • 重点,需要注意的:在IDEA工具中根据Web Application模板生成的目录中有一个web目录,这个目录就代表webapp的根

JavaWeb-Servlet(上)_第10张图片

  • 第四步(非必须):根据Web Application生成的资源中有index.jsp文件,这里我选择删除这个index.jsp文件。
  • 第五步:编写Servlet(StudentServlet)
    • class StudentServlet implements Servlet
    • 这个时候发现Servlet.class文件没有。怎么办?将CATALINA_HOME/lib/servlet-api.jar和jsp-api.jar添加到classpath当中(这里的classpath说的是IDEA的classpath
      • File --> Project Structrue --> Modules --> + 加号 --> Add JARS....
      • JavaWeb-Servlet(上)_第11张图片

    • 实现jakarta.servlet.Servlet接口中的5个方法。
  • 第六步:在Servlet当中的service方法中编写业务代码(我们这里连接数据库了。)
  • 第七步:在WEB-INF目录下新建了一个子目录:lib(这个目录名可不能随意,必须是全部小写的lib),并且将连接数据库的驱动jar包放到lib目录下。
  • 第八步:在web.xml文件中完成StudentServlet类的注册。(请求路径和Servlet之间对应起来)
  • 
    
        
            studentServlet
            com.itzw.javaweb.servlet01.StudentServlet
        
        
            studentServlet
            /servlet/student
        
    
  • 第九步:给一个html页面,在HTML页面中编写一个超链接,用户点击这个超链接,发送请求,Tomcat执行后台的StudentServlet。

    • student.html

    • 这个文件不能放到WEB-INF目录里面,只能放到WEB-INF目录外面。

    • student.html文件的内容

    • 
      
      
          
          student page
      
      
          
          student list
      
      
      
  • 第十步:让IDEA工具去关联Tomcat服务器。关联的过程当中将webapp部署到Tomcat服务器当中。

    • IDEA工具右上角,绿色小锤子右边有一个:Add Configuration
    • 左上角加号,点击Tomcat Server --> local
    • 在弹出的界面中设置服务器Server的参数(基本上不用动)
    • 在当前窗口中有一个Deployment(点击这个用来部署webapp),继续点击加号,部署即可。
    • 修改 Application context为:/xmm
  • 第十一步:启动Tomcat服务器

    • 在右上角有绿色的箭头,或者绿色的小虫子,点击这个绿色的小虫子,可以采用debug的模式启动Tomcat服务器。
    • 我们开发中建议适用debug模式启动Tomcat
  • 第十二步:打开浏览器,在浏览器地址栏上输入:http://localhost:8080/xmm/student.html

java小程序代码:

package com.itzw.javaweb.servlet01;

import jakarta.servlet.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;

public class StudentServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        //设置响应格式
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/db1";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url,user,password);
            //获取预编译的数据库操作对象
            String sql = "select id,balance from t_act";
            ps = conn.prepareStatement(sql);
            //执行sql
            rs = ps.executeQuery();
            //处理结果集
            while (rs.next()){
                int id = rs.getInt("id");
                String balance = rs.getString("balance");
                out.print(id + "," + balance + "
"); } } catch (Exception e) { e.printStackTrace(); }finally { if (rs != null) { try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }

7 Servlet中的方法概述

构造方法只执行一次,在Tomcat服务器启动时并不会调用任何方法,当用户访问服务器时,Tomcat会先调用构造方法。

init方法只执行一次,init被翻译为初始化,在Servlet对象被创建之后执行,在构造方法之后执行。init方法使用很少,通常在init方法中做初始化操作,如初始化数据库连接池,初始化线程池等等。

service方法:用户发送一次请求执行一次,发送N次请求执行N次,service方法是我们使用最多的,是处理用户请求的核心方法。

destroy方法:只执行一次,在Tomcat关闭前执行,相当于遗言,此方法使用也很少,通常在destroy方法中进行资源关闭等。

注意:init方法的功能好像和无参构造一样,init能完成的构造方法也可以,为什么还需要init方法?更多的原因是,不建议我们自己写构造方法,因为如果忘记写无参构造只写了有参构造就会出现错误(500错误),500是一个HTTP协议的错误状态码,一般情况下是因为服务器端的java程序出现了异常。

8 适配器模式改造Servlet

通过上面的练习发现一个问题,每次都要实现Servlet接口,而Servlet中的方法很多却基本上用不到,搞得代码很丑陋,怎么解决?

现实生孩子我们发现,当我们想给手机充电时需要一个充电器或者说适配器,它像一个中介或者说一个接口来过度能更方便的充电,我们也可以写一个适配器来协助更方便的写代码。

写个适配器:

package com.itzw.javaweb.servlet;

import jakarta.servlet.*;

import java.io.IOException;

public abstract class GenericServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 抽象方法最常用,注意抽象方法没有主体,不需要大括号
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException ;

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

简单些个servlet继承适配器:

package com.itzw.javaweb.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import java.io.IOException;

public class LoginServlet extends GenericServlet{

    /*这样就很简洁*/
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("登陆成功了捏。。。");
    }
}

添加配置文件:

    
        loginServlet
        com.itzw.javaweb.servlet.LoginServlet
    
    
        loginServlet
        /login
    

配置Tomcat

JavaWeb-Servlet(上)_第12张图片

 运行:

但是有个问题,当我想在service中用init方法中的ServletConfig对象就用不了了,需要再改造。

我们知道的是,ServletConfig对象创建在init方法中,是局部变量,但是此方法是Tomcat操作的,所以Tomcat中会创建一个ServletConfig对象传入到init方法中从而执行init方法。那么如何在service方法中拿到这个对象呢?

可以创建使用ServletConfig创建一个变量,然后在init方法中将ServletConfig对象传到这个变量中,很巧的是在Servlet接口中有getServletConfig方法,好像就是给这种情况准备一样,在getServletConfig方法中返回这个变量,这样就能在继承的service方法中调用getServletConfig方法得到这个对象了。运行确实可以得到。

JavaWeb-Servlet(上)_第13张图片

JavaWeb-Servlet(上)_第14张图片

 但是这样又有一个问题,假如我真的要用到init方法该怎么办,虽然用的少,但是确实我想重写init该怎么办?需要再改造。

假如我在子类重写了init方法,那么父类的init方法就不会执行,那上一步的改造就废了。所以不能让子类重写init方法,不允许子类重写方法可以加个final关键字。但是我想重写啊,该怎么办?那既然子类不能重写就在父类重写。可以先在父类重写一个无参init方法,在有参init方法中调用这个无参init方法,然后我在子类中再重写这个无参init方法,这样有参init必然会执行,也就必然会调用到无参init,而子类重写的init必然是无参init,这样保证了service方法中可以正常使用ServletConfig对象,也可以重写init方法。

JavaWeb-Servlet(上)_第15张图片

JavaWeb-Servlet(上)_第16张图片 

执行成功。

有个好消息是忙活了半天,GenericServlet这个适配器Tomcat中已经写好了,打开源码发现和我们写的差不多,我们直接使用就可以了。

测试一下:

package com.itzw.javaweb.servlet;

import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import java.io.IOException;

public class UserServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Tomcat的GenericServlet执行了。。。");
    }
}

 更好的消息是,还有更好用的“适配器”,我们一般也不用GenericServlet。。。。日常白学。

9 ServletConfig接口详解

ServletConfig是Servlet中的一员,ServletConfig是一个接口,Tomcat服务器实现了这个接口,一个Servlet对象中有一个ServletConfig对象,它们一一对应,在创建Servlet对象的同时创建了ServletConfig对象

ServletConfig有什么用?

在翻开GenericServlet接口我们发现里面有这样三个方法,其中getServletConfig就是来获取ServletConfig对象,而其它两个方法都用到了这个对象,通过翻开帮助文档我们得知ServletConfig里面装的是配置文件信息,是servlet标签中的信息,也就是可以获取到web.xml文件中的初始化参数配置信息。

JavaWeb-Servlet(上)_第17张图片

 接下来我们在web.xml文件中写入一些初始化信息,这些信息写在servlet标签内


        config
        com.itzw.javaweb.servlet.ConfigTest
        
        
            driver
            com.mysql.cj.jdbc.Driver
        
        
            url
            jdbc:mysql://localhost:3306/db1
        
        
            user
            root
        
        
            password
            123456
        
    

接下来我们在java小程序内借助getServletConfig获取这些信息。

package com.itzw.javaweb.servlet;

import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

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

public class ConfigTest extends GenericServlet {
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        //获取servlet名称
        String servletName = this.getServletName();
        //结果和web.xml中的信息是对应的 config
        out.print(servletName + "
"); //获取初始化信息中的name Enumeration names = this.getInitParameterNames(); while (names.hasMoreElements()){ String s = names.nextElement(); //根据name获取value String value = this.getInitParameter(s); out.print("name:" + s + ",value:" + value + "
"); } } }

结果:

JavaWeb-Servlet(上)_第18张图片

 从这我们可以看出这个小东西还是挺有用的,在后面连接数据库中应该可以更方便。

10 ServletContext接口详解

10.1 ServletContext概述

ServletContext是接口,是Servlet规范中的一员,ServletContext是Tomcat服务器实现的。ServletContext对象再WEB服务器启动时创建的,ServletContext对象时WEB服务器创建的,经测试,我们发现对于webapp来说,ServletContext对象只有一个,ServletContext对象在关闭服务器时销毁,ServletContext对象其实对应的就是整个web.xml文件,因为在同一个webapp中不管有多少java小程序或者说有多少servlet,只有一个web.xml文件,这里和ServletConfig区分开来。

10.2 ServletContext作用

用处一:既然ServletContext对象对应整个web.xml文件,那么它可以获取到web.xml中的配置文件信息,不过这个信息是应用级的配置信息,一般一个项目中共享的配置信息会放到这里,下面是这种配置信息的模式:

    
        pageSize
        10
    
    
        startIndex
        0
    

以上的信息使用ServletContext对象可以获取,下面演示如何获取

        //获取ServletContext对象
        ServletContext application = this.getServletContext();
        out.print("ServletContext的对象是:" + application+ "
"); //获取所有上下文初始化参数的name Enumeration names = application.getInitParameterNames(); //遍历name while (names.hasMoreElements()){ String s = names.nextElement(); //根据name获取对应的value String value = application.getInitParameter(s); out.print(s + "=" + value + "
"); }

这种信息有什么用呢:一般用在限制一页网页展示的信息量上。

用处二:获取应用的根路径(非常重要)

在java代码中,不要将根路径写死,这也是我们学代码一直在讲的解耦合,提高代码的通用性:

        //获取context的根
        String contextPath = application.getContextPath();
        out.print("此应用的根:" + contextPath + "
"); //获取文件的绝度路径,这里的文件是web目录下的文件,默认去web下面找 //前面加不加“/”都可以 String realPath = application.getRealPath("index.jsp"); out.print(realPath + "
");

用处三:写日志

需要注意的是,日志文件存放在运行tomcat后在idea中找到这样一个目录:

JavaWeb-Servlet(上)_第19张图片

        //写日志
        application.log("大家好,我是练习时长两年半的个人练习生,喜欢唱跳rap蓝球。");

        //可以使用日志记录异常
        int age = 17;
        if (age < 18){
            application.log("对不起您未成年,请绕行",new RuntimeException("小屁孩滚滚滚"));
        }

JavaWeb-Servlet(上)_第20张图片

10.3 应用域

ServletContext对象还有另一个名字:应用域(后面还有其它域,例如:请求域、会话域)

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

为什么这些共享数据很少修改或者说不修改,因为如果涉及修改必然存在线程并发所带来的安全问题,所以放在ServletContext对象中的数据一般是只读的。

存:怎么向ServletContext应用域中存数据

  • setAttribute方法

取:怎么从ServletContext应用域中取数据

  • getAttribute方法

删:怎么删除ServletContext应用域中的数据

  • removeAttribute方法

这个小程序完整代码:

package com.itzw.javaweb.servlet;

import jakarta.servlet.*;

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

public class AServlet extends GenericServlet {
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        //获取ServletContext对象
        ServletContext application = this.getServletContext();
        out.print("ServletContext的对象是:" + application+ "
"); //获取所有上下文初始化参数的name Enumeration names = application.getInitParameterNames(); //遍历name while (names.hasMoreElements()){ String s = names.nextElement(); //根据name获取对应的value String value = application.getInitParameter(s); out.print(s + "=" + value + "
"); } //获取context的根 String contextPath = application.getContextPath(); out.print("此应用的根:" + contextPath + "
"); //获取文件的绝度路径,这里的文件是web目录下的文件,默认去web下面找 //前面加不加“/”都可以 String realPath = application.getRealPath("index.jsp"); out.print(realPath + "
"); //写日志 application.log("大家好,我是练习时长两年半的个人练习生,喜欢唱跳rap蓝球。"); //可以使用日志记录异常 int age = 17; if (age < 18){ application.log("对不起您未成年,请绕行",new RuntimeException("小屁孩滚滚滚")); } //准备数据 User user = new User("王德发","123"); //存 //application.setAttribute("userObj",user); //取 Object userObj = application.getAttribute("userObj"); out.print(userObj); //删 application.removeAttribute("userObj"); } }

你可能感兴趣的:(javaweb,Java,servlet,服务器,java,web)