• 【JavaWeb】01_Tomcat、Servlet、Thymeleaf



    注:本文项目代码见码云:

    Tomcat

    Tomcat:服务器端的Web容器。
    在容器中部署项目。项目称为context root。

    • BS/CS:
      浏览器服务器架构 与 客户端服务器架构。
      BS:优点:不需要安装、维护成本低
      缺点:服务器负荷较重。
      CS:优点:充分利用客户端机器的资源。(安全要求不高的项目放到客户端执行。)
      缺点:需要安装、升级维护。

    • Tomcat 目录结构说明
      目录:
      D:\MySQL\Tomcat\apache-tomcat-8.5.76-windows-x64
      bin:可执行文件目录。
      conf:配置文件。
      lib:依赖的Java类。
      logs:存放日志的文件夹。
      temp:临时文件夹。
      webapps:部署项目的空间。
      work:工作目录。

    注意:因为tomcat也是用Java和C来写的,所以需要配置环境变量。具体的操作可以自己搜索。

    手动部署Web项目: 在配置好环境变量的前提下,双击bin目录下startup.bat文件即可启动tomcat。在webapps下新建文件夹,在文件夹下创建文件夹名:WEB-INF和所需项目即可。然后就可以通过浏览器访问了。

    • IDEA下部署Web项目的几个必要步骤
      JavaWeb_01项目流程为例:
      在这里插入图片描述
    1. 创建Web项目:新建项目后,右键项目——添加框架支持——web应用程序。

    2. 部署Tomcat。

    3. 导入MySQL驱动。(记得将lib添加到工件,进行更新)。启动数据库。

    4. 导入Tomcat的jar包。

    5. 创建Servlet类(服务器端应用程序),命名为AddServlet,继承Tomcat中的HttpServlet。重写doPost方法(具体由表单的method决定),使用FruitDAO与数据库进行交互。

    6. 配置web.xml文件。使表单发起的action=add请求,对应调用AddServlet类。

    • 常用名词解释:
    • pojo
      Plain Old Java Object。“普通Java对象”
    • dao
      DAO(Data Access Object):数据访问层。封装对数据库的访问,不涉及业务逻辑。
    • impl
      impl的全称为implement,表示实现的意思。
      即用来存放接口的实现类。
    • 其他注意事项:
      1. 注意,IDEA比较特殊,项目部署在out目录下,而不是在webapps目录下。
      2. BaseDAO中要记得修改数据库的Driver等为自己的。
      3. add.html创建再web目录下。
      4. 点击调试按钮执行程序,这样可以随时debug。
      5. 更多详见CSDN文章。

    Servlet

    Servlet的继承关系

    1. 继承关系

      • javax.servlet.Servlet接口
        • javax.servlet.GenericServlet抽象类
          • javax.servlet.http.HttpServlet抽象子类
    2. 相关方法 - 重点查看服务方法。

      • javax.servlet.Servlet接口:

          void init(config) - 初始化方法
               //客户端发送请求,service方法自动执行。
             void service(requst,response) - 服务方法
             void destory() - 销毁方法
        
        • 1
        • 2
        • 3
        • 4
      • javax.servlet.GenericServlet抽象类:
        void service(requst,response) - 仍然是抽象方法

      • javax.servlet.http.HttpServlet抽象类:
        void service(requst,response) - 不是抽象方法

        service方法执行流程:

        1. String method = req.getMethod(); 获取请求的方式。
        2. 判断,根据请求方式不同,决定调用不同do方法。
     ```java
       if (method.equals("GET")) {
                      this.doGet(req, resp);
                  } else if (method.equals("HEAD")) {
                      this.doHead(req, resp);
                  } else if (method.equals("POST")) {
                      this.doPost(req, resp);
                  }
                  doPost方法:
                  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                          String msg = lStrings.getString("http.method_post_not_supported");
                          this.sendMethodNotAllowed(req, resp, msg);
                      }
                  sendMethodNotAllowed方法:
                  private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException {
                          String protocol = req.getProtocol();
                          if (protocol.length() != 0 && !protocol.endsWith("0.9") && !protocol.endsWith("1.0")) {
                              resp.sendError(405, msg);
                          } else {
                              resp.sendError(400, msg);
                         }
     ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    小结:
    1)继承关系:HttpServlet-> GenericServlet-> Servlet
    2)Servlet中核心方法:init() 、service()、destory()
    3)服务方法:当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)
    在HttpServlet中的service方法会分析发送请求的方式:到底是get、post还是…然后再决定调用哪个do方法。
    在HttpServlet中这些do方法都是405的实现风格,所以要我们子类去实现对应的方法,否则默认会报405。
    4)因此,在新建Servlet时,会考虑请求方法,从而决定重写哪个do方法。

    Servlet生命周期

    JavaWeb_02——DemoServlet02

    1. 生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init()、service()、destroy()
    2. 默认情况下,第一次接收请求:Servlet实例化(调用构造方法)、初始化(调用init)、服务(调用service)。
      从第二次请求开始:每一次都是服务。
      当容器关闭:销毁服务。
    3. Servlet实例tomcat只会创建一个,所有的请求都通过这个实例去响应。
      好处:提高系统的启动速度。
      缺点:第一次请求时耗时较长。
      如果需要提高第一次请求的响应速度,应该设置Servlet初始化时机。
    4. Servlet的初始化时机:
      可以通过来设置servlet的启动先后顺序,数字越小,启动越靠前。
    5. Servlet在容器中是单例的(只有一个servlet实例去响应线程)、线程不安全的
      所以:不要在servlet中定义成员变量。如果不得不定义成员变量的值,不要去修改值或做逻辑判断。

    HTTP协议

    1. HTTP称为超文本传输协议。

    2. Http是无状态的。

    3. Http请求响应包含两个部分:请求 request 和 响应 response。

      • 请求:
      1. 请求行:包含请求方式、访问地址url、HTTP协议的版本。
      2. 请求(消息)头:包含很多客户端需要告诉服务器的信息,比如:浏览器型号,版本,可以接收内容的类型。
      3. 请求主体:
        get方式:没有请求体,但是有一个queryString
        post方式:有请求体,form data
        json格式:有请求体,request payload
      • 响应:
      1. 响应行:包含协议、响应状态码(200)、响应状态(ok)
      2. 响应头:包含服务器的信息。
      3. 响应体:响应的实际内容(比如等)

    常见Http响应状态码:
    404:找不到对应的资源。
    405:当前请求的方法不支持。
    500:没有找到数据库驱动/driver、url错误。为数据库内部错误。
    200:正常访问。
    302:客户端重定向

    session会话

    JavaWeb_02——DemoServlet03

    因为Http协议是无状态的,服务器无法判断两次请求是否都由同一客户端发出。
    所以通过会话跟踪技术来解决无状态问题。

    • 会话跟踪技术

      客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的sessionID。响应给客户端。下次客户端发送请求时,会把session带给服务器,那么服务器就可以判断是哪台客户端。

    • 常用API

      //获取当前会话,如果没有创建一个新的会话。
      request.getSession();
      request.getSession(true);
      //获取当前会话,如果没有返回null。
      request.getSession(false);
      //获取会话ID
      session.getId();
      //判断当前session是否是新的
      session.isNew();
      //获取/设置session的最大非激活间隔时长,默认1800秒
      session.getMaxInactiveInterval();
      session.setMaxInactiveInterval(16000);
      //强制让会话失效
      session.invalidate();
      
      //向session的保存作用域中保存数据
      session.setAttribute(key,value);
      //读取session保存作用域中key对应的value。
      session.getAttribute(key);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • session保存作用域
      JavaWeb_02——DemoServlet04/05

      session保存作用域是和具体的某一个sessionID对应的。

      比如下图:浏览器通过demo04向服务器发送请求,获得了一个sessionID并且通过session.setAttribute(key,value);在保存作用域保存了数据。

      那么只要sessionID一致,都可以通过session.getAttribute(key);直接获取保存作用域的数据。
      在这里插入图片描述

    服务器内部转发及客户端重定向

    JavaWeb_02——DemoServlet06/07

    • 服务器内部转发:
      API:req.getRequestDispatcher("demo07").forward(req,resp);
      是一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端不知道。
      在这里插入图片描述
    • 客户端重定向:
      API:resp.sendRedirect("demo07");
      两次请求响应的过程,客户端知道请求的url有变化。
      在这里插入图片描述

    Thymeleaf

    视图模板技术:可以在你的页面上加载保存作用域中的数据。以JavaWeb_03为例。
    在这里插入图片描述

    • 在服务器端引入Thymeleaf技术的步骤

      1. 在项目中加入Thymeleaf jar包
      2. 在web.xml中添加配置(配置前缀prefix和后缀suffix)
      3. 新建Servlet类ViewBaseServlet——>代码直接复制即可。
      4. 使得我们的Servlet继承ViewBaseServlet。
      5. 在do方法中加入下面这句话:
      //thymeleaf会将这个逻辑视图名称 对应到 物理视图 名称上去。
      //逻辑视图名称: index
      //物理视图名称: view-prefix + 逻辑视图名称 + view-suffix
      //真正的视图名称:  /           index        .html
      super.processTemplate("index",req,resp);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      1. 在html页面中使用thymeleaf的标签:

        th:if、th:unless、th:each、th:text,标签作用已注释在代码中。

    保存作用域

    • request:一次请求响应范围有效。
      在这里插入图片描述
    • session:一次会话范围有效。
      使用request.getSession()方法获取session。
      在这里插入图片描述
    • application:一次应用程序范围有效。
      使用request.getServletContext()方法获取application。
      ServletContext:Servlet上下文。Tomcat启动,上下文开始,Tomcat关闭,上下文停止。
      在这里插入图片描述

    路径问题

    相对路径下,使用../可以返回上一级。以下面的图片为例:红色即为相对路径。蓝色为绝对路径。
    一般情况下最好写绝对路径,所以用th : ... = @{ }
    在这里插入图片描述

    水果库存系统实现CRUD、分页功能

    1. 编辑和修改功能的实现逻辑:
      index.html(点击水果名称的超链接进行跳转,th:href=edit.do)——>
      EditServlet(获取要编辑的水果的fid,将该水果的信息放入保存作用域中,使用thymeleaf,执行super.processTemplate(“edit”,request,response) )——>edit.html(编辑完成后,提交表单,action=update.do)——>UpdateServlet(获取表单数据,使用FruitDAO与数据库进行交互,客户端重定向)——>index.html
    2. 删除功能的实现逻辑:
      index.html(点击删除图片,绑定th:οnclick=delFruit方法,在js中实现该方法,执行del.do)——>DelServlet(获取fid,使用FruitDAO与数据库进行交互,客户端重定向)——>index.html

    th:onclick="|delFruit(${fruit.fid})|" 的解释:

    1. 使用th:onclick而不是简单的onclick。

      因为fruit.fid要随着不同水果fid的变化而变化,所以要用th:onclick。

    2. 在thymeleaf使用方法时,添加竖线可以自动实现字符串拼接。

    1. 添加功能的实现逻辑:
      index.html(点击添加按钮,绑定action=add.html,直接访问静态网页。)——>add.html(表单绑定action=add.do,直接访问AddServlet)
      ——>AddServlet(获取表单数据,使用FruitDAO与数据库进行交互,客户端重定向)——>index.html(最终回到index.html)
      在这里插入图片描述

    2. 分页功能的实现逻辑:
      JavaWeb_04.1

      index.html(点击下一页按钮,绑定th:οnclick=pageNo方法,在js中实现该方法,执行index)——>IndexServlet(按页数显示)——>index.html

    3. 查询功能:
      JavaWeb_04.2,暂时最终的IndexServlet版本。

      index.html(点击查询,form表单传入index)——>IndexServlet(具体见注释)——>index.html

    注意事项/技巧:

    • 这里默认从index.html开始,其实是使用index,访问IndexServlet,使用thymeleaf将index——>index.html。

    • 如果修改后页面没有更新,可以检查out文件夹中的文件是否都齐全。或者清除浏览器缓存。

    • 查看div边距,可以使用border:1px solid red来实现。

    • 使用ctrl+F5可以快捷刷新页面。

  • 相关阅读:
    C#重点问题之Struct和Class的异同
    运动品牌推荐:2022年最值得入手的一些运动装备
    函数形状有几种定义方式;操作符infer的作用
    程序员打工人的一天
    自研框架跻身全球 JS 框架榜单,排名紧随 React、Angular 之后!
    11-JVM中常用垃圾回收器分析与实践
    不同数据类型在单片机内存中占多少字节?
    关于c#:displayname属性
    常见服务知识点罗列--nginx
    独立产品灵感周刊 DecoHack #029 - 随便逛逛谷歌街景
  • 原文地址:https://blog.csdn.net/weixin_62633072/article/details/126024602