Java0基础_day15_Javaweb后端_Tomcat服务器篇

标签:B/S结构、javaweb、Tomcat、servlet规范、网络通信

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第1张图片


1.B/S和C/S架构

众所周知,互联网通信分为C/S架构B/S架构,具体如下:

C/S架构:

  • C/S:Client/Server,即客户端/服务器架构
  • 客户端:即发起请求的一端;如我们的qq客户端打字“你好啊”并且发送到对方;
  • 服务器:接收请求的一端,如qq服务器接收到上述信息;
  • 使用场景:娱乐市场
  • 优点:客户端界面好看,减轻服务器负载,数据更安全
  • 缺点:客户端更新频繁,用户必须下载客户端,
  • 功能:服务器负责接收客户端发来的请求,称为request阶段,然后将找到的资源返回给客户端,称为response响应阶段。

B/S架构:

  • B/S:Brower/Server,即浏览器/服务器架构
  • 浏览器:即用户安装的浏览器,如chrome,firefox,edge
  • 服务器:接收浏览器请求的一端,又称为web服务器,http服务器
    • 其中Tomcat服务器较为常用,轻量级,免费
    • 实现了两个JAVAEE规范【共13个】,即servlet规范和jsp规范
  • 使用场景:企业
  • 优点:轻量级,不必经常更新,可以发送任意指令
  • 缺点:服务器负载大,速度慢
  • 功能:服务器负责接收浏览器发来的请求,称为request阶段,然后将找到的资源返回给浏览器,称为response响应阶段。
  • 关键点:网站的高并发问题
  • B/S是学习的重点,因为java后端开发程序员经常会在企业中处理brower的请求,而对于web前端html,css和javascript仅做了解即可;而其中java后端关键就是servlet规范。

2.B/S架构角色划分

  • 流程:用户在浏览器输入http://www.baidu.com:80/index.html之后,回车,此时浏览器会把该请求封装为request请求报文,经过dns解析为IP地址找到百度服务器的主机,通过80端口号与百度的web服务器建立通信,想要访问的是百度wb服务器根目录下的index.html页面,web服务器查找后返回response响应报文,即想要的资源
  • 不难发现,角色有:
  • 浏览器→负责封装、解封HTTP请求报文【request请求,response请求】
  • web服务器→根据URL寻找资源【Tomcat服务器、jetty服务器】
  • 后端人员→负责编写java小程序和配置路径与程序类名的映射关系【YOU!】
  • mysql数据库→存储资源,如员工工资表等【mysql,jdbc】
  • HTTP请求报文【request】
    • 结构:请求行【请求方式、URI、HTTP版本号】 、请求头、空白行、响应行
Get请求:
GET /wodewangzhan/getservlet?username=45&password=55555 HTTP/1.1
//请求头
Host: localhost:8080
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/wodewangzhan/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

//请求体
POST /wodewangzhan/postservlet HTTP/1.1
//请求头
Host: localhost:8080
Connection: keep-alive
Content-Length: 34
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/wodewangzhan/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

//请求体
username: 123456
password: 999999999

【注意】这里请求行中路径为URI,统一资源标识符,仅仅是资源的在站点的位置,他是整个URL的一部分。

  • HTTP响应报文【response】
//第一部分:状态行 版本号 状态码
HTTP/1.1 304
//状态码:200 成功;404 资源不存在,要么路径出错,要么资源并没有启动成功
//405 请求方式和处理方式不一样,post用get处理
//500 服务器后台程序出错
//4开头 浏览器册出错
//5开头 服务器侧出错
// ok正常 not found 资源找不到
//第二部分 响应头    关键是content-type,告诉浏览器我返回的是什么类型的资源
ETag: W/"865-1637892866027" 
Date: Fri, 26 Nov 2021 02:20:44 GMT
Keep-Alive: timeout=20 //响应时间,内容长度和类型;
Connection: keep-alive
//第三部分:响应体


  get请求


get server

h1>
  • HTTP请求方法中POST和GET方法的区别?

区别1:日常使用除非在form表单的method方法中显式声明为post,否则都是默认为get方式

区别2:post对长度类型无限制,get只能传输字符串,并且有长度限制

区别3:post的请求参数信息在请求体中,get请求参数在请求行中,即明文展示

区别4:get常用于获取服务器的数据,而post常用于向服务器提交数据,如文件上传

区别5:get是安全的,post由于上传文件因此有安全风险,同时为了保密,因此表单大多数使用的是post方法

区别6:get方式支持缓存,而post方式不支持浏览器缓存,因此如果想访问变动大的数据要用post,否则用get

相同点:二者都是name1=value1&name2=value2&name3=value3...的规范,而这里的 name字段就是相当于key字段,value就是对应key的value字段

  • 互联网通信协议流程图

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第2张图片

 资源分类:静态资源和动态资源

  • 静态资源
    • 如html,js,css样式和图片、文本、视频等资源,有固定的存放位置,内容一般不改变的资源。
  • 动态资源
    • java小程序,即servlet对象,用户想要输入自己的信息经过网站的程序才能返回某个值,因此java小程序就是动态资源,用户想要获取某些操作的结果。
  • web-inf目录:html,js,css资源不能放在这,因为受保护【有配置文件】

3.Tomcat服务器配置_手工配置_初级尝试

3.1 几个明确点:

  • Tomcat是web服务器,端口默认为8080

3.2 配置流程

第一步:下载tomcat,如下所示,在左边选择版本,我这里选择tomcat9.

Apache Tomcat® - Welcome!https://tomcat.apache.org/【注意】tomcat10中有些原本中的库名发生了改变,由javax改为了jakarta,这是因为本来是javaee规范,oracle将tomcat捐给了apache开源基金会的原因。Apache Tomcat® - Welcome!

第二步:在系统环境变量添加java_home和catalina_home的环境变量,以便在cmd的dos窗口可以进行开发。

【PS】tomcat是java写的,自然需要jvm,即需要关联jdk包,同时由于tomcat不知道catalina在哪里,故需要加入catalina_home。

第三步:第一次启动关闭tomcat,即进入tomcat安装包\bin目录,cmd进入该目录,敲击startup可以发现启动了,然后shutdown即可。

第四步:建立站点文件夹并进行静态资源访问: 

  →webapp文件夹是站点文件夹,默认是root站点,这里新建crm文件夹

 →→在crm文件夹放入静态资源,这里随便放一张图片,如4.jpg

→→→启动tomcat,注意不要关闭任何dos窗口

→→→→在浏览器输入http://localhost:8080/crm/4.jpg,回车,此时成功!

第五步:动态资源访问

【前知】需要知道的是,访问动态资源就是用户输入一段链接,tomcat服务器解析为某个java小程序,这里叫servlet对象,然后去找对应的类,实例化对象,执行其service方法,有可能还会操作数据库进行查询,最后返回。

→上文的crm文件夹下新建WEB-INF文件夹【全部大写!】

→→在WEB-INF文件夹下新建classes文件【存放小程序的.calss文件】

→→在WEB-INF文件夹下新建一个目录,名为lib【用于第三方依赖库,如mysql驱动】

→→→在WEB-INF文件夹下新建web.xml文件,当然这个文件最好复制下面的粘贴到你这里,因为这是tomcat默认的配置文件【tomcat从这里找到用户的urL路径和你写的类的映射】




→→编写小程序:

【注意】事实上,浏览器和web服务器之间由Oracle提供了一套规范,即servlet规范,浏览器、web服务器厂商和java开发人员都要遵循这套规范,实现解耦合、可拓展的目的。

因此,java程序员编写小程序就是实现servlet接口然后重写service方法即可。

小程序第一步:

  • package source.servlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    public class serve implements Servlet {
        public serve( ) {
            System.out.println("serve的构造方法被执行了");
        }
    
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
            System.out.println("serve的init方法被执行了");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            System.out.println("serve的getserveconfig被执行了");return null;
        }
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("serve的构services被执行了");
       
     //将信息输出到浏览器上;//该语句最好在设置流之前,以免乱码;
        servletResponse.setContentType("text/html;charset=utf-8");
    
        PrintWriter pw = servletResponse.getWriter();
        pw.println("

    1234

    "); } @Override public String getServletInfo() { System.out.println("serve的getServletInfo方法被执行了"); return null; } @Override public void destroy() { System.out.println("serve的destroy方法被执行了"); } }

    然后将其编译到上文讲到的classes文件夹即可。【由于javax.servlet不是JDK规范,因此需要在系统的 jre安装目录下的ext文件夹加入我们下载的javax.servlet包,后者可以在tomcat的lib文件夹找到相关包】

小程序第二步:关联web.xml文件→注册


		dd	
	
		serverLet.FirstDemo	
  
  
  
  
		dd	
	
	
		/SDFAD/SDAS	
	
   

【tomcat将浏览器的url-pattern找到servlet-name,进而找到serverLet.FirstDemo类执行】

小程序第三步:开启tomcat服务器,输入URL【http://localhost:8080/crm/SDFAD/SDAS 】,关闭服务器

【注意】可能运行会出现乱码问题,可参考如下修改:

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第3张图片

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第4张图片

 至此,一个简单的小程序开发完毕,不过,考虑到有时候链接太长,可以将用户输入URL→返回资源优化为用户点击超链接→解析为URL→返回资源,如下:

第一步:在crm目录下新建index.html文件,内容如下:

<!doctype = html>

你好啊





 我是打印

我是JDBC

第二步:访问http://localhost:8080/crm/INDEX.HTML,然后点击按钮,即可与上文的小程序过程一致。

过程总结:Tomcat启动自动执行main方法,进而执行service方法,我们只需要实现servlet接口,重写service方法,注册web.xml文件即可用urL访问。


4.Tomcat服务器配置_手工配置_JDBC实战

只需采用六步法实现servlet接口与jdbc接口,编译到classes文件夹,注册到web.xml,引入mysql驱动到lib包即可用URL访问:

// javac -encoding utf8 -d D:\minisoftware\apache-tomcat-9.0.55\webapps\crm\WEB-INF\classes  serverLet\StuInfo_Get.java
package serverLet;
import src.JDBC.Utils;
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * @author zhangsan
 * @create 2021-11-25 16:12
 */
public class StuInfo_Get 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 {
        servletResponse.setContentType("text/html;charset = utf-8");
        PrintWriter pw = servletResponse.getWriter();
        Connection col =null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            col = Utils.getConnection();
            String sql ="select * from user where sal=?";
            ps = col.prepareStatement(sql);
            ps.setInt(1, 2000);
            rs = ps.executeQuery();
            while(rs.next()){
                String name = rs.getString("username");
                String sal = rs.getString("sal");
                pw.println("name:" + name + "sal is " + sal);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            Utils.close(col,ps,rs);
        }
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    }
}

5. Tomcat服务器配置_IDEA中配置

第一步:新建空工程,新建一个javase普通模块,这里是servlet01

第二步:将上述模块变成javaee模块,方法:模块右键添加框架支持,选择web applcation,其中自动生成的蓝眼睛的web文件夹就相当于我们前面配置的crm文件夹。

第三步:删除index.jsp【暂时用不着】

第四步:写程序【src目录下新建一个source.servlet包】

public class serve implements Servlet {
    public serve( ) {
        System.out.println("serve的构造方法被执行了");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("serve的init方法被执行了");
    }

    @Override
    public ServletConfig getServletConfig() {
        System.out.println("serve的getserveconfig被执行了");return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("serve的构services被执行了");
        servletResponse.setContentType("text/html;charset = utf-8");
        PrintWriter pw = servletResponse.getWriter();
        Connection col =null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            col = Utils.getConnection();
            String sql ="select * from user where sal=?";
            ps = col.prepareStatement(sql);
            ps.setInt(1, 2000);

            rs = ps.executeQuery();

            while(rs.next()){
                String name = rs.getString("username");
                String sal = rs.getString("sal");
                pw.println("name:" + name + "sal is " + sal);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            Utils.close(col,ps,rs);
        }

    }
    @Override
    public String getServletInfo() {
        System.out.println("serve的getServletInfo方法被执行了");

        return null;
    }

    @Override
    public void destroy() {
        System.out.println("serve的destroy方法被执行了");
    }
}

【注意】此时会报错,因为没有引入javaee包,故点击项目结构,在模块中添加jar包,将tomcat安装目录的lib包下的servlrt-api.jar和jsp.api选进来。

第五步:引入mysql包,由于需要操控jdbc,故可以引入mysql驱动,如上一步。

【注意】当然为了统一,也可以在WEB-INF新建lib包,拖入驱动到这里,右键添加为库。

第六步:为web.xml注册,类名必须包括包名,同时路径不能包括根目录,即servlet01.

第七步:将Tomcat服务器与该站点关联

步骤:点击配置,加入tomcat-local,选择部署中加入该站点,同时修改部署页下的application context为/servlet01,这就是URL中本站点的根目录。

第八步:debug模式启动,打开浏览器输入URL即可见。


6.Servlet接口详细剖析

  • 是什么?

     servlet接口/规范是orcale公司的javaee规范的一员,用于webserver和webapp之间的一套规定,实现解耦合、高拓展的效果。

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第5张图片

  • 有什么用?

   有上述分析可知,servlet设计web服务器和后端工程师,一方面他规定了web服务器如何将小程序与路径映射,如web.xml文件,另一方面,规定了webapp的目录结构、配置文件、类放置目录等。

  • 怎么实现的?

    首先明确,它是Tomcat服务器实现的,可以从tomcat的servlet-api.jar源可知,Tomcat服务器通过配置文件找到类名,然后通过反射机制new对象,调用service服务进行程序的执行,下图为尝试实现的Tomcat服务器。

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第6张图片

  • 生命周期

       用户第一次请求会创建一个servlet对象,执行其中的init方法和service方法,然后后续每一次访问都会执行该对象的service方法,在关闭服务器时,destroy方法执行,进行最终的关闭。

  • 如何让服务器时创建servlet?

     在web.xml的每个servlet中加入0,0表示优先级最高


     DD 
    
         source.servlet.serve1 
    3



     DD 
    

      /student_server1   

  • 结论?

   结论1: 后端工程师只需要写好servlet实现类,配置web.xml文件即可。

【注意】因为Tomcat已经把配置文件的格式和位置规定好,我们只需按规定写即可。

   结论2:servlet是单实例的,但是由于其构造方法不是私有的,不是有程序员管理,故不是单例模式;同时init方法用于初始化操作,service方法用的最多。

  •    存在问题?

   编写servlet类是需要实现5个方法的,很麻烦怎么办?

    可以将其他方法都抽象为父类中实现,然后子类重写实现service方法即可【适配器模式】。

package source.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
 * @author zhangsan
 * @create 2021-11-25 20:08
 */
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
     */
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException ;


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

    @Override
    public void destroy() {

    }
}

由此,不难发现init方法有一个ServletConfig方法,故Tomcat必然是先创建servlet对象,然后创建ServletConfig对象,将其传给init实现初始化,过程大致如下:

public class Tomcat{
    public static void main(String[] args){
       //创建Servlet对象-反射机制
        //创建config对象
        servletConfig is org.apache.catalina.core.StandardWrapperFacade@7e7b743b
        //调用init方法
 public void init( servletConfig) throws ServletException { }   
        //调用service方法

    }     
}

对此,我们怎么复用局部变量ServetConfig?

因此可以在GenericServlet中引入类变量ServletConfig,然后将其赋值为父类的getServletConfig即可,同时,为了避免子类重写父类的init方法以免破坏属性,故在父类的init有参方法中调用父类的init无参方法,让子类重写这个无参方法,最终的GenericServlet如下:

package source.servlet;
import javax.servlet.*;
import java.io.IOException;
public abstract class GenericServlet implements Servlet {
    private ServletConfig config = null;
    public final void init(ServletConfig config) throws ServletException {
        this.config = config;
        System.out.println("我是父类的,我的servletConfig is" + config);
        this.init();
    }

    /**
     * 一下方法是供子类重写的;
     */
    public void init(){
        System.out.println("我是父类的inite方法,我出现代表程序出错了");
    }
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    /**
     * 该抽象类用于实现接口,屏蔽一些不重要的操作;
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException ;
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    }
}

7.ServletConfig接口详细剖析

  • 是什么?                                                         一个接口
  • 实现方法?                                      javax.servlet.ServletConfig
  • 谁实现的?                                       Tomcat服务器   config is org.apache.catalina.core.StandardWrapperFacade@36c3c0b6
  • 与servlet对象的关系?                  一个servlet对象有一个servletconfig
  • 谁创建的?                          web服务器创建的,在servlet创建的同时创建servletconfig对象
  • 有什么用?                                             servlet对象的配置信息
  • 包装了哪些信息?                     包装了web.xml中的servet之间的信息
  • 怎么包装的?                     Tomcat服务器解析web.xml,包装到servletconfig对象中   
  • 有哪些方法?                                        getInitParameter()
  • 举例?
    package source.servlet;
    
    import javax.servlet.*;
    import javax.servlet.GenericServlet;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Enumeration;
    
    /**
     *  
     *           configtest_2_config2   
     *         
     *           source.servlet.configtest_2 
     *         
     *             Driver
     *             "com.mysql.cj.jdbc"
     *         
     *         
     *             username
     *             "小猫腻"
     *         
     *初始化参数信息,封装到servletConfig对象中;
     *     
     */
    public class configtest_2 extends GenericServlet {
        @Override
        public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter pw = response.getWriter();
            ServletConfig config = this.getServletConfig();
    
            pw.println("

    config_test_2的 is "+config+"

    "); pw.print("
    "); //获取servlet的getname方法; pw.println("

    config_test_2的name is "+config.getServletName()+"

    "); // pw.println("

    config_test_2的name is "++"

    "); Enumeration ee= config.getInitParameterNames(); while(ee.hasMoreElements()){ String x = ee.nextElement(); pw.print(x+"的值是"+config.getInitParameter(x)); pw.print("
    "); } // pw.print("
    "+config.getInitParameter("Driver")); pw.print("
    "); //this也可以,因为父类Generic已经实现了servletconfig发发发; pw.print(this.getInitParameter("Driver")); } }

8.ServletContext接口详细剖析

  • 是什么?                                                         一个接口
  • 实现方法?                                      javax.servlet.ServletConfig
  • 谁实现的?                                       Tomcat服务器                               org.apache.catalina.core.ApplicationContextFacade
  • 与servlet对象的关系?                 

    一个webapp有一个ServletContext表,属于应用级对象,即整个web.xml文件,是所有servlet的共享对象,而Tomcat是一个容器,可以放多个webapp。

  • 谁创建的?                          web服务器创建的,在servlet创建的同时创建servletcontext对象
  • 包含哪些信息?                             一个webapp中所有的servlet对象的配置信息
  • 有哪些方法? 

getparameternames方法→共享信息参数

getInitParameter()→共享信息参数

getcontextpath()→动态获取应用的根路径

getrealpath()→获取文件的真实路径

log(String s)→ 将字符串s写入到日志文件中     

     如:

ServletContext con = this.getServletContext();
con.log("今天是11-25,我很开心");

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第7张图片

 【注意1】Tomcat和磁盘的站点并飞一一对应,一个IDEA可以创建多个Tomcat,多个站点。

【注意2】日志文件分类:

  • catalina.2021-11-25.log                           输出到idea控制台信息

  • localhost.2021-11-25.log                      来自Context对象的log方法

  • localhost_access_log.2021-11-25.txt         来自浏览器的访问日志

  • 举例:
    
        name
        我的家乡在中国
    
    
        age
        65
    
    /*全局配置;
            ServletContext con = this.getServletContext();
           Enumeration CC = con.getInitParameterNames();
            while(CC.hasMoreElements()){
                String s = CC.nextElement();
               pw.print(s+"→"+con.getInitParameter(s));
               pw.print("
    "); }*/
  • ServletContext与ServletConfig的区别?

     前者是每个webapp的全局配置,后者是每个servlet对象的局部配置,故不依赖于对象选前面。

  • 有什么操作?→增删改

增:setAttribute(String name,Object value)→map.put

取:getAttribute(String name,Object value)→map.get

删:deleteAttribute(String name,Object value)→map.del

user user1 = new user(30,1000);
//存
con.setAttribute("张三", user1);
 Object obj = con.getAttribute("张三");
        pw.println(" "+obj);
        package source.servlet;

/**
 * @author zhangsan
 * @create 2021-11-25 23:27
 */
public class user {
    private  int age;
    private double sal;

    @Override
    public String toString() {
        return "user{" +
                "age=" + age +
                ", sal=" + sal +
                '}';
    }

    public user(int age, double sal) {
        this.age = age;
        this.sal = sal;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }
}
  • 有什么用?

   如果所有用户共享一个数据量小、不经常修改的数据,那么可以放入context中。

为何共享 →共享的放入才有意义,冗余和安全

为何数据量小 →数据量大占用内存,其周期长

为何数据修改不要太多 →多用户修改设计线程安全问题

如此非常快,相当于缓存,下次再使用不用从数据库获取


9.HttpServlet接口详细剖析

  • 是什么?                    一个接口,专门用来处理http协议的,比genericservlet、servlet更常用
  • 位置?                                     javax.servlet.http.httpservlet
  • HTTP包有哪些接口?
    * http.httpservlet
    * http.httpservletrequest
      * 简称request对象
      * 封装了请求协议的全部内容
      * Tomcat服务器将“请求协议”中的数据全部解析处理,然后封装到request对象中
      * 只要面向request就可以获取协议中的数据;
    * http.httpservletresponse
  • HttpServlet的代码结构?

    public class haloservlet extends HttpServlet {
        //1.第一步创建对象,调用午餐方法
        public haloservlet() {
        }
        //2.执行父类的init方法
        public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
        {//调用genericServlet的init有参方法,调用该类的无参方法;
    
            public void init(ServletConfig config) throws ServletException {
            this.config = config;
            this.init();
        }
    
            public void init() throws ServletException {
            }
    
    
        }
    
        //3.调用老祖宗的原书的service方法
        public abstract class HttpServlet extends javax.servlet.GenericServlet {
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            HttpServletRequest request;
            HttpServletResponse response;
            try {
                request = (HttpServletRequest)req;//向下转型;
                response = (HttpServletResponse)res;
            } catch (ClassCastException var6) {
                throw new ServletException(lStrings.getString("http.non_http"));
            }
    
            this.service(request, response);//重载service
    
        }
    
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //获取请求方式
            String method = req.getMethod();
                long lastModified;
                if (method.equals("GET")) {
                    lastModified = this.getLastModified(req);
                    if (lastModified == -1L) {
                        this.doGet(req, resp);
                    } else {
                        long ifModifiedSince;
                        try {
                            ifModifiedSince = req.getDateHeader("If-Modified-Since");
                        } catch (IllegalArgumentException var9) {
                            ifModifiedSince = -1L;
                        }
    
                        if (ifModifiedSince < lastModified / 1000L * 1000L) {
                            this.maybeSetLastModified(resp, lastModified);
                            this.doGet(req, resp);
                        } else {
                            resp.setStatus(304);
                        }
                    }
                } else if (method.equals("HEAD")) {
                    lastModified = this.getLastModified(req);
                    this.maybeSetLastModified(resp, lastModified);
                    this.doHead(req, resp);
                } else if (method.equals("POST")) {
                    this.doPost(req, resp);
                } else if (method.equals("PUT")) {
                    this.doPut(req, resp);
                } else if (method.equals("DELETE")) {
                    this.doDelete(req, resp);
                } else if (method.equals("OPTIONS")) {
                    this.doOptions(req, resp);
                } else if (method.equals("TRACE")) {
                    this.doTrace(req, resp);
                } else {
                    String errMsg = lStrings.getString("http.method_not_implemented");
                    Object[] errArgs = new Object[]{method};
                    errMsg = MessageFormat.format(errMsg, errArgs);
                    resp.sendError(501, errMsg);
                }
    
            }
        }
  • 结论?

  可以重写父类的service方法,但是享受不到404 not found这样的独特的方法,因此建议根据需求重写doGet或者doPost方法,没必要都写,应当根据业务逻辑选择,例如后端重写了doPost方法,那么前端一定是发过来的post方法。

  • 405原因解释?

   上面的haloservet继承了httpservlet,但是没有重写doGet方法,此时浏览器发送了get请求,故会调用父类的doGet方法,而此时调用父类的doGet方法必然会导致405出错,因为父类的本意就是想让你重写需要的方法。

  • 最终的servlet类?

第一步:编写类继承HttpServlet类,按需求实现doGet或doPost方法

第二步:注册到web.xml中【路径不要有站点名】

第三步:准备前端的html、form表单

package helloservlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author zhangsan
 * @create 2021-11-26 12:37
 */
public class loginservlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.print("

登陆成功

"); } }

# HTML




    
    测试


get

get请求

post

servlettest

# web.xml



    
        helloservlet
        helloservlet.haloservlet
    
        
            helloservlet
            /hello
        

 
        finalservlet
        helloservlet.loginservlet
    
        
            finalservlet
            /finalservlet
        

10.ServletRequest接口详细剖析

  • 是什么?                                           一个接口,由Tomcat实现了
  • 谁实现的?                       org.apache.catalina.connector.RequestFacade
  • 子接口?                                        HttpServletRequest
  • HttpServletRequest有哪些信息?

  封装了HTTP请求信息,我们通过HttpServletRequest即可拿到用户的HTTP请求信息

  • 生命周期?                         只在当前请求有效,一个请求对应一个HttpServletRequest
  • 如果是你,用户的表单信息如何保存到后端?

前端的数据格式:aihao=eat&aihao=shui

故可以考虑Map集合,存储key-value值对:

Map"aihao" {"eat","shui"}

  • 有哪些方法?

Java0基础_day15_Javaweb后端_Tomcat服务器篇_第8张图片


 11.配置web欢迎页面

  • 配置方式?

方法1:全局配置

//catalina_HOME_web.xml
*  
          index.html
          index.htm
          index.jsp
      

方法2:局部配置

//web-WEB.XML

    xiaobai

 

法则:就近优先!

【注意】如果不配置,从全局配置可知,访问站点根目录默认访问的是该站点下的index.html页面。

  • 静态欢迎页配置步骤

第一步:配置IDEA站点

第二步:书写index.html,放到web根目录下

第三步:在web.xml中引入index.html,格式见上面的局部配置

【注意】这里面的路径是相对于web文件夹而言,不要加上了web站点的路径。

【注意2】可以设置多个欢迎页,从上到家优先。

【注意3】欢迎页也可以是一个servlet对象,如下。

  • 动态欢迎页配置步骤

第一步:写servlet

public class servletonIndex extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      response.setContentType("text/html;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.println("你好啊,我是servlet");
    }
}

第二步:在web.xml配置


    zhagnsan
    wel.servletonIndex
    zhagnsan
    /xiaobai

第三步:web.xml配置欢迎页:

    
        xiaobai

    

第四步:访问:http://localhost:8080/servlet01/


12.杂谈

第一个:缓存机制

为了提高效率,计算机的世界中引入了缓存机制,例如:

  • redis,mongdb
  • java中的字符串常量池和int型-128~127的常量池
  • 操作系统中的TLB
  • 连接池
    • 将连接对象放在一个集合,例如jdbc中有mysql和jvm
  • 线程池
    • Tomcat支持多线程,在启动时就创建若干线程对象,用户发送请求时,就用一个线程来进行处理,提高效率。
  • ServletContext应用域

第二个:设计模式

设计模式就是解决某个问题的固定解决方案,分为javaee设计模式,GoF设计模式等等,例如最常用的就是模板方法设计模式,我们通常把普适性的方法写到抽象父类,将一些特殊方法定义,然后让子类重写,例如我们的HttpServlet接口。

第三个:开发经验

  • 开发中往往是已经有人写好了多线程,我们的关键是在多线程的环境下代码是否安全。
  • java程序员面向接口编程,关注本文的几个接口即可

  • 多看源代码,学习、思考、创新、超越

  • 知识要整理,有逻辑的提前背诵,模拟面试。

你可能感兴趣的:(java,接口,抽象类)