JavaWeb:Servlet (学习笔记)【1】

news2025/2/25 2:21:16

目录

一,Servlet介绍

1,简介

2,Servlet技术特点

3,Servlet在应用程序中的位置

4,Servlet在程序中到底处于一个什么地位?

二,servlet运行过程:

三,servlet路径配置

四,Servlet的生命周期

1,伪单例模式

2,生命周期的步骤

3,讲解Servlet是一个伪单例模式

五,什么是生命周期啊?就是说什么时候有的,以及什么时候没的。

六,HttpServletRequest请求对象

1,获取请求行信息

2,获取请求头信息

3,获取请求体数据

 回顾http请求:

 七,HttpServletResponse响应对象

1,响应行

2,响应头

(1)设置响应头(setHeader)【解决乱码】

(2)设置同名的响应头(addHeader)——怎么能不覆盖呢?

(3)设置字符型响应

(4)设置字节型响应

(5)设置响应编码

(6)在响应中添加附加信息(文件下载)

3,响应主体

回顾http响应:

八,乱码问题

1,请求数据乱码

2,响应的数据乱码

3,jsp页面乱码


一,Servlet介绍

1,简介

  • 是一种web服务器端编程技术

     (不要觉得Servlet很神奇,就是一个普通的java类,只不过可以运行在服务器端。在服务器端接收客户端的请求和返回响应信息)

  • 是实现了特殊接口的Java类

     (一级一级往上找,确实实现了Servlet接口,但是我们用得时候,是继承httpServlet类

  •  一个Servlet负责对应一个或一组URL访问请求,并返回相应的响应内容。
  • Servlet是Server Applet的简称,称为服务端小程序,是JavaEE平台下的技术标准基于Java语言编写的服务端程序。Web容器或应用服务器实现了Servlet标准所以Servlet需运行在Web容器或应用服务器中。Servlet主要功能在于能在服务器中执行并生成数据
  • Html,css,js在浏览器中执行,在服务器端生成。我们学习的Servlet就是一种在服务器端动态生成html,css,js数据的技术。

  •  Servlet对象是伪单例模式;通过map集合实现。(可以延迟创建,也可以立即创建)
     使用web.xml  和 注解方式配置Servlet。

  • Servlet作为一种动态资源技术,是我们后续学习框架的基础

2,Servlet技术特点

Servlet使用单进程多线程方式运行。

3,Servlet在应用程序中的位置

4,Servlet在程序中到底处于一个什么地位?

  • Servlet是可以接受Http请求并作出相应的一种技术,是JAVA语言编写的一种动态资源
  • Servlet是前后端衔接的一种技术,不是所有的JAVA类都可以接收请求和作出相应,Servlet可以
  • 在MVC模式中,Servlet作为Controller层(控制层)主要技术,用于和浏览器完成数据交互,控制交互逻辑
  • 静态资源和动态资源区分

静态资源: 每次访问都不需要运算,直接就可以返回的资源, 如HTML  CSS  JS  多媒体文件等等,每次访问获得的资源都是一样的

动态资源:每次访问都需要运算代码生成的资源,如Servlet JSP ,每次访问获得的结果可能都是不一样的


二,servlet运行过程:

  • 浏览器发送请求到服务器(用到http协议)
  •  服务器根据请求的url,去调用响应的Servlet类(请求)
  • 通过Servlet中的打印流对象将生成的html数据输出给服务器(响应)
  • 服务器将servlet生成的数据在输出给客户端浏览器(用到http协议)

三,servlet路径配置

web.xml中配置Servlet的映射路径

<url-pattern>/abcd</url-pattern>只有abcd这一种方式可以访问到hiServlet类。

      <url-pattern>/aaa/*</url-pattern>
只要是在aaa这个路径下的所有请求都可以访问hiServlet类。
      <url-pattern>*.bbb</url-pattern>
 只要是以bbb结尾的路径都可以访问hiServlet类。
       http://localhost:8080/项目名/asdsafd/asffs/fsfdsgf/sfasdfsa.bbb
http://localhost:8080/项目名/sfasdfsa.bbb都可以
<url-pattern>/ccc/*.bbb</url-pattern>===非法写法!!

四,Servlet的生命周期

1,伪单例模式

单例:一个类只创建一个对象

servlet是一个伪单例模式,只是借鉴了单例模式的思想,他通过别的途径做的实现】

通过map集合来实现单例效果!因为构造器不是private

2,生命周期的步骤

第一步:实例化 

第二步:初始化

延迟创建:客户端【第一次】发送请求   ----到该Servlet服务器才会创建该对象)

立即创建:<load-on-startup>1</load-on-startup>)

第三步:执行服务——》接收请求——》对请求进行分发,给回响应)【反复】

第五步:销毁。(1.服务器关闭的时候,所有Servlet对象都销毁

new   

实例化

init()

初始化 

service()

执行服务

destroy()

回收销毁

Servlet的生命周期是由容器管理的,分别经历四各阶段:

阶段           次数        时机

创建          1次          第一次请求

初始化       1次          实例化之后

执行服务    多次        每次请求

销毁           1次         停止服务 

3,讲解Servlet是一个伪单例模式

(1)创建HelloServlet类,实现5个方法,其中service方法,调用父类的Service方法。

(2)为什么说Servlet是伪单例模式呢?

        因为单例模式有3种方式,懒汉式(需要私有构造),饿汉式(需要私有构造),枚举方式。而我们的Servlet中没有枚举,也没有出现私有构造。那是通过什么方式实现单例模式的呢?---map集合方式。

因为运行在servlet容器中,类似于map(key-value)

         Map<String,HttpServlet>

         Key:String --- (servlet-name)hello

         Value:代表Servlet对象通过反射获的。Class.getConstructor(null).newInstance(null);

               第一次访问的时候创建新的对象

               第二次访问直接使用已有的对象====所以servlet-name的名字不能重复。

(3),在servlet容器中最多只有一个对象(理论上),实际上可以创建多个

(4)那你说Servlet模拟的是懒汉式还是饿汉式啊?

   Servlet默认属于懒汉式,第一次访问的时候被载入并初始化;

   如果觉得初始化时间较长Servlet可以设置成饿汉式。

 ---在web.xml中,

<servlet>1

     <servlet-name>helloServlet</servlet-name>

     <servlet-class>servlet.helloServlet</servlet-class>

    <load-on-startup></load-on-startup>

     ----如果值是正整数就是启动服务就被加载,整数越小越提前加载;

        如果值是负整数,或者没写这个标签,都是在第一次访问的时候加载。

</servlet>

五,什么是生命周期啊?就是说什么时候有的,以及什么时候没的。

     什么时候有的:第一次访问的时候(默认)

     什么时候没的:服务器关闭,而不是调用destory();调用destory()方法只是为了在销毁之前,在做一些工作。不需要我们手动调用,服务器会给我们自动调用。

  • 在Servlet中我们一般不要轻易使用成员变量!!!! 可能会造成线程安全问题
  • 如果要使用的话,应该尽量避免对成员变量产生修改
  • 如果要产生修改我们应该注意线程安全问题
  • 如果我们自己添加线程安全编码处理,会严重影响效率
  • 综上所述:原则,能不用成员变量就不用!!!

六,HttpServletRequest请求对象

HttpServletRequest对象代表客户端浏览器的请求,当客户端浏览器通过HTTP协议访问服务器时,HTTP请求中的所有信息都会被Tomcat所解析并封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

1,获取请求行信息

请求方式

request.getMethod();---用的比较多

资源路径URL

request.getRequestURL();{访问项目外的}

资源路径URI

request.getRequestURI();

协议

request.getScheme();

协议版本号

request.getProtocol()

get方式的请求信息

request.getQueryString()

当前项目部署的名称

request.getContextPath();---用的比较多 

返回发出请求的客户机的IP地址

(客户端)

request.getRemoteAddr()
返回WEB服务器的IP地址request.getLocalAddr()
返回WEB服务器处理Http协议的连接器所监听的端口request.getLocalPort()

2,获取请求头信息

根据请求头中的key获取对应的value。

{不区分大小写}

request.getHeader("headerKey")
获取请求头中所有的key,该方法返回枚举类型。request.getHeaderNames()
public class Servlet3 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(req.getRequestURL());//返回客户端浏览器发出请求时的完整URL。
        System.out.println(req.getRequestURI());//返回请求行中指定资源部分。
        System.out.println(req.getRemoteAddr());//返回发出请求的客户机的IP地址。
        System.out.println(req.getLocalAddr());//返回WEB服务器的IP地址。
        System.out.println(req.getLocalPort());//返回WEB服务器处理Http协议的连接器所监听的端口。
        System.out.println("主机名: " + req.getLocalName());
        System.out.println("客户端PORT: " + req.getRemotePort());
        System.out.println("当前项目部署名: " + req.getContextPath());
        System.out.println("协议名:"+req.getScheme());
        System.out.println("请求方式:"+req.getMethod());

        // 根据请求头名或者请求头对应的值
        System.out.println(req.getHeader("Accept"));
        // 获得全部的请求头名
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String headername = headerNames.nextElement();
            System.out.println(headername+":"+req.getHeader(headername));
        }
    }
}

3,获取请求体数据

根据key获取指定valuerequest.getParameter("key")
获取复选框(checkbox组件)中的值,返回一个String[]request.getParameterValues("checkboxkey")
获取请求中所有数据的key,该方法返回一个枚举类型request.getParameterNames()
获取请求中所有的数据并存放到一个Map结构中,该方法返回一个Map,其中key为String类型value为String[]类型。request.getParameterMap()
设置请求编码request.setCharacterEncoding("utf-8")

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
开发form表单注意事项
1form 不是from
2form表单内部不是所有的标签信息都会提交 一些输入信息  input select textarea ... ...
3要提交的标签必须具备name属性  name属性的作用是让后台区分数据  id便于在前端区分数据
4要提交的标签一般都要具备value属性  value属性确定我们要提交的具体的数据
5 get post
  get方式数据是通过URL携带
  提交的数据只能是文本
  提交的数据量不大
  get方式提交的数据相对不安全
  post 将数据单独打包放到请求体中
  提交的数据可以是文本可以是各种文件
  提交的数据量理论上没有上限
  post方式提交数据相对安全
  当一个表单标签
  readonly只读 也是会提交数据的
  hidden  隐藏 也是会提交数据
  disabled 不可用 显示但是不提交
-->
<form method="get" action="myServlet">
    <table style="margin: 0px auto" width="300px" cellpadding="0px" cellspacing="0px" border="1px">
        <tr>
            <td>用户名</td>
            <td>
                <input type="text" name="username" id="in1" value="12345" disabled >
            </td>
        </tr>
        <tr>
            <td>密码</td>
            <td>
                <input type="password" name="pwd">
            </td>
        </tr>
        <tr>
            <td>性别</td>
            <td>
                <input type="radio" name="gender" value="1" checked>男
                <input type="radio" name="gender" value="0">女
            </td>
        </tr>
        <tr>
            <td>爱好</td>
            <td>
                <input type="checkbox" name="hobby" value="1">蓝球
                <input type="checkbox" name="hobby" value="2">足球
                <input type="checkbox" name="hobby" value="3">羽毛球
                <input type="checkbox" name="hobby" value="4">乒乓球
            </td>
        </tr>
        <tr>
            <td>个人简介</td>
            <td>
                <!--文本域 双标签 页面上显示的文字是双标签中的文本 不是value属性
                    文本域提交的数据不是value属性值,是双标签中的文本
                -->
                <textarea name="introduce" >b</textarea>
            </td>
        </tr>
        <tr>
            <td>籍贯</td>
            <td>
                <!--
                select
                option没有定义value属性 那么就提交option中间的文字(不推荐)
                -->
                <select name="provience">
                    <option value="1">a京</option>
                    <option value="2">b津</option>
                    <option value="3">c冀</option>
                </select>
            </td>
        </tr>
        <tr align="center">
            <td colspan="2">
                <input type="submit" value="提交数据">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

Servlet页面

package com.mashibing.servlet;
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.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
/**
 * @Author: Ma HaiYang
 * @Description: MircoMessage:Mark_7001
 */
public class MyServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // req获取参数
        // 如果 前端发过来的数据由数据名但是没有值, getParameter返回的是一个空字符串  ""
        // 获取的参数在提交的数据中名都没有,getParameter返回的是null
        String username = req.getParameter("username");
        System.out.println("username:"+username);
        System.out.println("password:"+req.getParameter("pwd"));
        System.out.println("gender:"+req.getParameter("gender"));
        // hobby=1&hobby=2&hobby=3 想要获得多个同名的参数 getParameterValues 返回的是一个Sting数组
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("hobbies:"+ Arrays.toString(hobbies));
        // textarea
        System.out.println("introduce:"+req.getParameter("introduce"));
        // select
        System.out.println("provience:"+req.getParameter("provience"));
        System.out.println("___________________________");
        // 如果不知道参数的名字?
        // 获取所有的参数名
        Enumeration<String> pNames = req.getParameterNames();
        while(pNames.hasMoreElements()){
            String pname = pNames.nextElement();
            String[] pValues = req.getParameterValues(pname);
            System.out.println(pname+":"+Arrays.toString(pValues));
        }
        System.out.println("________________________________");
        Map<String, String[]> pmap = req.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = pmap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
        }
    }
}

 回顾http请求:

一个http请求可以分为三个部分,分别是请求行,请求头,请求体

  • 请求行

  • 请求头

  • 请求体

get方式     提交的请求数据通过地址栏提交 ,没有请求体
post方式    提交请求数据单独放到请求体中,

请求时所携带的数据 (post方式)

  • http支持的请求方式


 七,HttpServletResponse响应对象

1,响应行

 response.setStatus(222,"故意不写200");

2,响应头

(1)设置响应头(setHeader)【解决乱码】

Response.setHeader(“content-type”,”text/html;charset=utf-8”);

response.setContentType("text/html;charset=utf-8");

response.setCharacterEncoding("utf-8");

Response.setHeader(“hello”,”bjsxt”);

Response.setHeader(“hello”,”sxt”);---只会显示一个,覆盖了。

====在service方法中,写完,运行项目。在浏览器中F12查看响应信息就可以了

(2)设置同名的响应头(addHeader)——怎么能不覆盖呢?

Response.addHeader(“hi”,”bjsxt”);

Response.addheader(“hi”,”sxt”);

(3)设置字符型响应

设置响应类型为文本型,内容含有html字符串,是默认的响应类型response.setContentType("text/html")
设置响应类型为文本型,内容是普通文本。response.setContentType("text/plain")
设置响应类型为JSON格式的字符串response.setContentType("application/json")

(4)设置字节型响应

设置响应类型为图片类型,图片类型为jpeg或jpg格式。response.setContentType("image/jpeg")
设置响应类型为图片类型,图片类型为gif格式response.setContentType("image/gif")

(5)设置响应编码

设置服务端为浏览器产生响应的响应编码,服务端会根据此编码将响应内容的字符转换为字节。response.setCharacterEncoding("utf-8")
设置服务端为浏览器产生响应的响应编码,服务端会根据此编码将响应内容的字符转换为字节。同时客户端浏览器会根据此编码方式显示响应内容。response.setContentType("text/html;charset=utf-8")

(6)在响应中添加附加信息(文件下载)

在实现文件下载时,我们需要修改响应头,添加附加信息。

Content-Disposition:attachment

该附加信息表示作为对下载文件的一个标识字段。不会在浏览器中显示而是直接做下载处理。

filename=文件名,

表示指定下载文件的文件名。

package com.mashibing.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @Author: Ma HaiYang
 * @Description: MircoMessage:Mark_7001
 */
public class MyServlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置响应码
        //resp.setStatus(500);
        //resp.setStatus(405, "request method not supported");
        // 设置响应头
        //resp.setHeader("Date","2022-11-11");
        // 自定义头
        // resp.setHeader("aaa", "bbb");
        // 高速浏览器响应的数据是什么? 浏览器根据此头决定 数据如何应用
        // 设置MIME类型 json  xml 文件下载  ... ...
        // resp.setHeader("content-type", "text/css");
        resp.setContentType("text/html");// 专门用于设置Content-Type 响应头
        resp.getWriter().write("<h1>this is tag h1</h1>");
    }
}

3,响应主体

   response.getWriter().println("设置响应对象!");

回顾http响应:

http响应部分可以分为三部分:响应行,响应头,响应体  

1.响应行   

响应状态码列表如下

2. 响应头:

3响应实体:

服务器响应回来的内容 

HttpServletResponse

HttpServletResponse对象代表服务器的响应。这个对象中封装了响应客户端浏览器的流对象,以及向客户端浏览器响应的响应头、响应数据、响应状态码等信息。


八,乱码问题

1,请求数据乱码

Request.setCharacterEncoding(“utf-8”);

2,响应的数据乱码

Response.setContentType(“text/html;charset=utf-8”);

Response.setCharacterEncoding(“utf-8”);

===以上3行代码,写在Service的分发方法里!

3,jsp页面乱码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2253344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32-C语言基础知识

C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程&#xff1a;先清0&#xff0c;再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句&#xff0c;如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…

Android 应用单元测试涉及 Telephony 环境初始化问题

Telephony 相关类注入问题 SubscriptionManager Cannot invoke "android.telephony.SubscriptionManager.getActiveSubscriptionInfoList()" because "this.mSubscriptionManager" is nulljava.lang.NullPointerException: Cannot invoke "android.t…

mysql 存储结构的进化之路

文章目录 前言一、线性结构二、二叉树&#xff08;BST&#xff09;三、平衡二叉树&#xff08;AVL&#xff09;四、多路平衡查找树&#xff08;B Tree&#xff09;五、加强版多路平衡查找树&#xff08;B Tree&#xff09;总结 前言 树形结构是一种具有层次关系的数据结构&…

高速定向广播声光预警系统赋能高速安全管控

近年来&#xff0c;高速重大交通事故屡见不鲜&#xff0c;安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段&#xff0c;创新、智能、高效的压降交通事故的发生概率&#xff0c;优化交通安全管控质量&#xff0c;是近年来交管部门的主要工作&#xff0c;也是…

【机器学习】CatBoost 模型实践:回归与分类的全流程解析

一. 引言 本篇博客首发于掘金 https://juejin.cn/post/7441027173430018067。 PS&#xff1a;转载自己的文章也算原创吧。 在机器学习领域&#xff0c;CatBoost 是一款强大的梯度提升框架&#xff0c;特别适合处理带有类别特征的数据。本篇博客以脱敏后的保险数据集为例&#x…

游戏引擎学习第25天

Git: https://gitee.com/mrxiao_com/2d_game 今天的计划 总结和复述&#xff1a; 这段时间的工作已经接近尾声&#xff0c;虽然每次编程的时间只有一个小时&#xff0c;但每一天的进展都带来不少收获。尽管看起来似乎花费了很多时间&#xff0c;实际上这些日积月累的时间并未…

AI开发:生成式对抗网络入门 模型训练和图像生成 -Python 机器学习

阶段1&#xff1a;GAN是个啥&#xff1f; 生成式对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;&#xff0c;名字听着就有点“对抗”的意思&#xff0c;没错&#xff01;它其实是两个神经网络互相斗智斗勇的游戏&#xff1a; 生成器&#xff08;Gene…

040集——CAD中放烟花(CAD—C#二次开发入门)

效果如下&#xff1a; 单一颜色的烟花&#xff1a; 渐变色的火花&#xff1a; namespace AcTools {public class HH{public static TransientManager tm TransientManager.CurrentTransientManager;public static Random rand new Random();public static Vector3D G new V…

JavaScript实现tab栏切换

JavaScript实现tab栏切换 代码功能概述 这段代码实现了一个简单的选项卡&#xff08;Tab&#xff09;切换功能。它通过操作 HTML 元素的类名&#xff08;class&#xff09;来控制哪些选项卡&#xff08;Tab&#xff09;和对应的内容板块显示&#xff0c;哪些隐藏。基本思路是先…

【天地图】HTML页面实现车辆轨迹、起始点标记和轨迹打点的完整功能

目录 一、功能演示 二、完整代码 三、参考文档 一、功能演示 运行以后完整的效果如下&#xff1a; 点击开始&#xff0c;小车会沿着轨迹进行移动&#xff0c;点击轨迹点会显示经纬度和时间&#xff1a; 二、完整代码 废话不多说&#xff0c;直接给完整代码&#xff0c;替换…

HCIA笔记6--路由基础与静态路由:浮动路由、缺省路由、迭代查找

文章目录 0. 概念1.路由器工作原理2. 跨网访问流程3. 静态路由配置4. 静态路由的应用场景4.1 路由备份4.2 浮动路由4.3 缺省路由 5. 迭代路由6 问题6.1 为什么路由表中有的下一跳的地址有接口&#xff1f;6.2 个人电脑的网关本质是什么&#xff1f; 0. 概念 自治系统&#xff…

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libncurses.so.5的问题

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libncurses.so.5的问题 2024/11/29 21:11 缘起&#xff1a;中科创达的高通CM6125开发板的Android10的编译环境需要。 vendor/qcom/proprietary/commonsys/securemsm/seccamera/service/jni/jni_if.…

Matlab搜索路径添加不上

发现无论是右键文件夹添加到路径&#xff0c;还是在“设置路径”中专门添加&#xff0c;我的路径始终添加不上&#xff0c;导致代码运行始终报错&#xff0c;后来将路径中的“”加号去掉后&#xff0c;就添加成功了&#xff0c;经过测试&#xff0c;路径中含有中文也可以添加成…

自由学习记录(28)

C# 中的流&#xff08;Stream&#xff09; 流&#xff08;Stream&#xff09;是用于读取和写入数据的抽象基类。 流表示从数据源读取或向数据源写入数据的矢量过程。 C# 中的流类是从 System.IO.Stream 基类派生的&#xff0c;提供了多种具体实现&#xff0c;每种实现都针对…

Redis3——线程模型与数据结构

Redis3——线程模型与数据结构 本文讲述了redis的单线程模型和IO多线程工作原理&#xff0c;以及几个主要数据结构的实现。 1. Redis的单线程模型 redis6.0之前&#xff0c;一个redis进程只有一个io线程&#xff0c;通过reactor模式可以连接大量客户端&#xff1b;redis6.0为了…

使用playwright自动化测试时,npx playwright test --ui打开图形化界面时报错

使用playwright自动化测试时&#xff0c;npx playwright test --ui打开图形化界面时报错 1、错误描述&#xff1a;2、解决办法3、注意符号的转义 1、错误描述&#xff1a; 在运行playwright的自动化测试项目时&#xff0c;使用npm run test无头模式运行正常&#xff0c;但使用…

深度学习模型:门控循环单元(GRU)详解

本文深入探讨了门控循环单元&#xff08;GRU&#xff09;&#xff0c;它是一种简化版的长短期记忆网络&#xff08;LSTM&#xff09;&#xff0c;在处理序列数据方面表现出色。文章详细介绍了 GRU 的基本原理、与 LSTM 的对比、在不同领域的应用以及相关的代码实现&#xff0c;…

用html+jq实现元素的拖动效果——js基础积累

用htmljq实现元素的拖动效果 效果图如下&#xff1a; 将【item10】拖动到【item1】前面 直接上代码&#xff1a; html部分 <ul id"sortableList"><li id"item1" class"w1" draggable"true">Item 1</li><li …

单片机学习笔记 12. 定时/计数器_定时

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

【乐企文件生成工程】搭建docker环境,使用docker部署工程

1、自行下载docker 2、自行下载docker-compose 3、编写Dockerfile文件 # 使用官方的 OpenJDK 8 镜像 FROM openjdk:8-jdk-alpine# 设置工作目录 WORKDIR ./app# 复制 JAR 文件到容器 COPY ../lq-invoice/target/lq-invoice.jar app.jar # 暴露应用程序监听的端口 EXPOSE 1001…