JavaWeb—Servlet

概述

Javaweb的核心就是围绕servlet
Servlet就是一个接口, 定义了java类 被浏览器访问到(tomcat识别)的接口
将来就是自己写一个类 ,实现servlet接口 ,重写方法

 

执行过程

当服务器接收到客户端浏览器的请求后,会解析请求的url路径,获取访问的servlet的资源路径
查找web.xml文件是否有对应的<url-pattern>标签体内容与资源路径一致
如果有,则在找到<servlet-class>对应的全类名
tomcat会将字节码文件加载到内容 创建对象(反射) 调用 service方法 

快速入门

  • 创建javaee项目 
  • 定义一个类,这个类必须实现servlet接口
  • 实现接口中的抽象方法
  • 配置servlet 
public class ServletDemo1 implements Servlet {

    //初始化方法 初始化当前servlet
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }

//    获取当前servlet的配置信息
    @Override
    public ServletConfig getServletConfig() {
        System.out.println("getServletConfig");
        return null;
    }

//    访问服务方法  每次访问servlet都会执行一次这个方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service");
    }

    //获取当前servlet信息
    @Override
    public String getServletInfo() {
        System.out.println("getServletInfo");
        return null;
    }

//    销毁方法
    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

 web.xml

<!--    配置servlet-->
    <servlet>
        <servlet-name>servletDemo1</servlet-name>
<!--        当前servlet的全类名-->
        <servlet-class>servlet.ServletDemo1</servlet-class>
    </servlet>
<!--    servlet 映射-->
    <servlet-mapping>
<!--        通过这个名字 找到 servlet标签-->
        <servlet-name>servletDemo1</servlet-name>
<!--        当前 servlet实现类的访问路径-->
        <url-pattern>/servlet1</url-pattern>
    </servlet-mapping>

生命周期

init 被创建
service 被访问
每次访问servlet都会调用一次service方法
destroy 被销毁
servlet被销毁时,服务器正常关闭时执行destroy方法,但是服务器如果不是正常关闭不走这个方法
getServletConfig
返回servlet配置对象
getServletInfo
获取servlet的一些信息: 版本,作者等

init

默认情况下servlet第一次被访问时被创建
可以指定配置servlet的创建时机
init只执行一次,说明servlet在内存中只存在一个对象(servlet时单例的)
多用用户同时访问时,可能存在线程安全问题
解决方案:尽量不要在servlet中定义成员变量 ,即使定义的成员变量,也不要对其修改值 

<!--        配置 init初始话时间  正数
            负数 默认 第一次访问servlet的时候 执行init方法
            正数 启动服务的之后 执行init方法
-->
        <load-on-startup>1</load-on-startup>

Servlet的体系结构

  • Servlet -- 接口
  • GenericServlet -- 抽象类
  • HttpServlet -- 抽象类
  • GenericServlet :将Servlet接口中的方法做了默认的实现,只将service()方法作为抽象,将来定义Servlet时 直接继承 GenericServlet类即可
  • HttpServlet:对http协议的一种封装,简化操作
  • 定义类继承HttpServlet类
  • 重写doGet doPost方法
@WebServlet("/servletDemo4")
public class ServletDemo4  extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("我是用户发送的get请求");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("我是用户发送的post请求");
    }
}

 

Http

•HyperText Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间--数据传输的规则

•数据传输的规则指的是请求数据和响应数据需要按照指定的格式进行传输。

TCP协议和HTTP协议 

基于TCP协议: 面向连接,安全
TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全。
基于请求-响应模型的:一次请求对应一次响应
请求和响应是一一对应关系


HTTP协议是无状态协议:对于事物处理没有记忆能力。每次请求-响应都是独立的
无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。这种特性有优点也有缺点
缺点:多次请求间不能共享数据
优点:速度快
请求之间无法共享数据会引发的问题,如:
淘宝,加入购物车和去购物车结算是两次请求
HTTP协议的无状态特性,加入购物车请求响应结束后,并未记录加入购物车是何商品
Java提出了使用会话技术(Cookie、Session)来解决这个问题 

Request 请求

请求行: HTTP请求中的第一行数据,请求行包含三块内容,分别是 GET[请求方式] /[请求地址] HTTP/1.1[HTTP协议及版本]
请求方式有七种,最常用的是GET和POST

 常见的HTTP请求头:

获取请求体 公共方法

//        获取参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
//        String like = request.getParameter("like");
        //如果是多选 那么就选择这个方法
        String[] likes = request.getParameterValues("like");

        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(likes));

        System.out.println("---------");
//        获取所有请求参数的名称
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String s = parameterNames.nextElement();
            System.out.println(s);
        }

        System.out.println("--------------");
//        返回所有参数的集合

        Map<String, String[]> parameterMap = request.getParameterMap();

        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry:entries
             ) {
            System.out.print(entry.getKey()+":");
            System.out.print(Arrays.toString(entry.getValue()));

            System.out.println();
        }
    }

Request 乱码问题

POST请求解决方案
分析出现中文乱码的原因:
POST的请求参数是通过request的getReader()来获取流中的数据
TOMCAT在获取流的时候采用的编码是ISO-8859-1
ISO-8859-1编码是不支持中文的,所以会出现乱码
解决方案:
页面设置的编码格式为UTF-8
把TOMCAT在获取流数据之前的编码设置为UTF-8
通过request.setCharacterEncoding("UTF-8")设置编码,UTF-8也可以写成小写

//在获取请求参数之前 修改编码格式
 request.setCharacterEncoding("utf-8"); 

出现连接过大异常

修改ConnectionUtils

   static  DataSource dataSource;
    static {
        try {
            Properties properties = new Properties();
//            FileInputStream resourceAsStream = new FileInputStream("druid.properties");
            InputStream resourceAsStream = ConnectionUtil.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(resourceAsStream);
             dataSource = DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取连接对象
     * @return 连接对象
     */
    public static Connection getConnection(){

        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        }  catch (Exception e) {
            throw new RuntimeException(e);
        }
        return connection;
    }

 

请求转发

@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        在Servlet1中接收到 浏览器发送的请求
        System.out.println("我是servlet1 我接受到了请求");
        System.out.println("但是我解决不了 需要转发给servlet2");

        //请求 http://localhost:8080/javaweb2/ServletDemo1?name=tom
//        传入资源2的路径
//        不需要添加虚拟路径的 , 因为是在服务器本生资源中进行跳转
//        然后将当前的请求和响应对象传递过去
        request.getRequestDispatcher("/ServletDemo2").forward(request,response);
    }

概念

请求转发(forward):一种在服务器内部的资源跳转方式
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫==请求转发==

请求转发资源间共享数据

主要解决的问题是把请求从/req1转发到/req2的时候,如何传递数据给/req2。
需要使用request对象提供的三个方法:
存储数据到request域 void setAttribute(String name,Object o);
根据key获取值 Object getAttribute(String name);
根据key删除该键值对 void removeAttribute(String name); 

请求转发的特点

•浏览器地址栏路径不发生变化

•只能转发到当前服务器的内部资源

•不能从一个服务器通过转发访问另一台服务器

•一次请求,可以在转发资源间使用request共享数据

•虽然后台从/req1转发到/req2,但是这个==只有一次请求==  

响应 response

响应消息格式
响应行
组成 HTTP/1.1 200 ok 协议版本 /响应码 码表述
响应头 
格式:头名称:值
常见的响应头: 
content-type: 服务器告诉客户端 当前的响应的数据格式以及编码格式
content-disposition:服务器告诉客户端 ,以什么形式打开当前的响应体
    1.in-line:默认值,在当前页面打开
    2.attachment : 以附件的形式打开
响应体 :真实的传输的数据

响应码

功能:告诉浏览器或者客户端一个当前的请求的响应状态
响应码 都是3位数
1xx  服务器接收客户端消息 但是没有接收完成,等待一段时间之后发送1xx ,询问客户端    还有没有数据 (不常见)
2xx  成功 代表:200
3xx  重定向 代表:302 (重定向) 304(访问缓存) 
4xx  客户端错误。代表404(请求路径没有对应的资源) 405(没有对应的请求方法 )
5xx  服务器端错误 代表500(服务器内部出现异常)


出现4xx 就去查看请求路径或者配置servlet的路径 ,转发重定向路径有没有问题
如果出现500 就看控制台提示的报错信息

 

操作response
 //操作响应
//      响应行
    //方法: setStatus(int i) 设置响应状态码
//        response.setStatus(500);


//        设置响应头
//        方法: setHeader()设置响应头
//        response.setHeader("content-disposition","attachment");


//        响应体
        /*
        响应体
方法:字符输出流 getWriter  字节输出流 getOutputStream
使用输出流将数据输出到浏览器客户端上

         */
        response.getWriter().write("你好世界");

 

重定向

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的 路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向

  
 System.out.println("A接收到了请求");
        String name = req.getParameter("name");
        System.out.println(name);

        System.out.println("重定向到B");

//        在request 请求域对象中 设置一个内容
        req.setAttribute("abc","hello");

        //http://localhost:8080/javaweb2/ServletDemoA?name=tom
        //设置状态码为302
//        resp.setStatus(302);
        //设置响应头中的location 为 新的请求地址
//      请求地址是需要添加虚拟路径
//        resp.setHeader("location","/javaweb2/ServletDemoB");


//        重定向的方式2
        resp.sendRedirect("/javaweb2/ServletDemoB");

重定向的特点

浏览器地址栏路径发送变化当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化
可以重定向到任何位置的资源(服务内容、外部均可) 因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。
两次请求,不能在多个资源使用request共享数据 因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据 

重定向和转发的区别

浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不需要加虚拟目录 对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录 
对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。 

设置响应的编码格式

 */

        /*
        setCharacterEncoding 要保证和浏览器的编码格式一致

         */
//        response.setCharacterEncoding("gbk");
        //通过设置请求头来解决这个问题 数据格式;编码格式
        response.setHeader("content-type","text/html;charset=utf-8");
        response.getWriter().write("你好世界");

 

ServletContext

ServletContext代表整个web应用
可以和程序的容器(服务器)(servlet)来进行通讯

功能    :
    获取MIME类型 (互联网中文件的类型) text/html
    域对象 : 共享数据
    获取文件的真实路径(服务器路径)

 

//        获取 servletContext的对象
        //方式1
        ServletContext servletContext = req.getServletContext();
        System.out.println(servletContext);

        //方式2
        /*
        servletContext 在多个Servlet中获取到的是一个对象
         */
//        ServletContext servletContext2 = getServletContext();

//      context的功能
//        功能1 获取文件的额mime类型
        //格式:大类型/小类型 例如  text/html   image/jpg

        String fileName = "a.java";
        String mimeType = servletContext.getMimeType(fileName);
        System.out.println(mimeType);


//        功能2 域对象
        servletContext.setAttribute("name","张三");
//        转发到servletContext2中
        resp.sendRedirect("/javaweb3/ServletContext2");

 //功能3 获取服务器的真实路径
        //druid.properties
        //           /project/Project/out/artifacts/javaweb3_war_exploded/WEB-INF/classes/druid.properties
//E:\sofwin\2312二阶段\project\Project\out\artifacts\javaweb3_war_exploded\
        //获取当前项目下 web文件夹下的路径
        String realPath = servletContext.getRealPath("index.jsp");
        System.out.println(realPath);

        //WEB-INF目录下的资源访问
        String realPath2= servletContext.getRealPath("/WEB-INF/");

//        WEB-INF下 classes 的路径
        String realPath3= servletContext.getRealPath("/WEB-INF/classes/");

 

 文件上传

1.将form表单中的enctype属性修改为multipart/form-data
2.servlet需要添加@MultipartConfig注解
3.获取Part对象 将post请求的数据封装成part对象
4.通过part. getSubmittedFileName获取文件名字
5.通过part. write输出到指定目录

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$Title$</title>
</head>
<body>
 <form action="/javaweb3/UpdateServlet" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit">
 </form>

</body>
</html>

Java代码

 /**
         * 1.将form表单中的enctype属性修改为multipart/form-data
         * 2.servlet需要添加@MultipartConfig注解
         * 3.获取Part对象 将post请求的数据封装成part对象
         * 4.通过part.getSubmittedFileName获取文件名字
         * 5.通过part. write输出到指定目录
         */
        //3.获取Part对象 将post请求的数据封装成part对象
        Part part = request.getPart("file");

//        4.通过part.getSubmittedFileName获取文件名字
        String fileName = part.getSubmittedFileName();

        //5.通过part. write输出到指定目录
        //获取真实路径
        String realPath = getServletContext().getRealPath(fileName);
        part.write(realPath);

 

文件下载

1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
2. 定义Servlet        
1. 获取文件名称        
2. 使用字节输入流加载文件进内存        
3. 指定response的响应头: content-disposition:attachment;filename=xxx
4. 将数据写出到response输出流

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<a href="/javaweb3/DownLoadServlet?filename=dog.jpg">点击下载</a>
</body>
</html>
//        1. 获取文件名称
        String filename = req.getParameter("filename");

//        2. 使用字节输入流加载文件进内存

        //获取 servletContext对象
        ServletContext servletContext = getServletContext();
        String realPath = servletContext.getRealPath(filename);

        FileInputStream fileInputStream = new FileInputStream(realPath);

//        3. 指定response的响应头: content-disposition:attachment;filename=xxx
        resp.setHeader("content-disposition","attachment;filename="+filename);
        ServletOutputStream outputStream = resp.getOutputStream();
//        4. 将数据写出到response输出流
        int len=0;
        byte [] bytes = new byte[1024];
        while ((len=fileInputStream.read(bytes))!=-1){
            outputStream.write(bytes,0,len);
        }


        outputStream.close();
        fileInputStream.close();

 

 

 

  

 

 

        

 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】机器学习与时间序列分析的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在时间序列分析中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 数据增强 1.2 模型选择1.2.1 自回归模型1.2.2 移动平均模型1.2.3 长短期记忆网络1.2.4 卷积神经网络 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 A…

C# 编程中互斥锁的使用

C# 中的互斥锁 互斥锁是 C# 中使用的同步原语&#xff0c;用于控制多个线程或进程对共享资源的访问。其目的是确保在任何给定时间只有一个线程或进程可以获取互斥锁&#xff0c;从而提供互斥。 C# 中互斥锁的优点 可以使用互斥锁 (Mutex) 并享受其带来的好处。 1. 共享资源…

一篇就够了,为你答疑解惑:锂电池一阶模型-在线参数辨识(附代码)

锂电池一阶模型-在线参数辨识 背景在线 VS 离线 参数辨识递推最小二乘法一阶戴维南Z域离散表达式 背景 锂电池一阶戴维南等效模型的基础知识和离线辨识方法&#xff0c;已经在上一期非常详细地讲解了一轮&#xff08;上期文章请戳此处&#xff09;&#xff0c;本期继续讲解一下…

秋招提前批面试经验分享(上)

⭐️感谢点开文章&#x1f44b;&#xff0c;欢迎来到我的微信公众号&#xff01;我是恒心&#x1f60a; 一位热爱技术分享的博主。如果觉得本文能帮到您&#xff0c;劳烦点个赞、在看支持一下哈&#x1f44d;&#xff01; ⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读…

vue3中使用EasyPlayer播放h265视频流

1、下载EasyPlayer 5.0.3版本 在package.json中加入EasyPlayer&#xff0c;并全局install下 "dependencies": {"easydarwin/easyplayer": "^5.0.3" }2、找到node_modules中的EasyPlayer.wasm和EasyPlayer-element.min.js 3、复制到public下面&…

多元微分学中可微、连续、存在问题

一、偏导存在 与一元证明相同&#xff0c;利用偏导定义式&#xff0c;证明偏导数左右极限存在且相同。 二、偏导连续 与一元证明相同&#xff0c;证明 三、极限存在 1、找一条路径&#xff0c;一般地找 y kx 2、代入f(x,y)&#xff0c;得f(x,kx) 3、证明f(x,kx)极限存在 注意&…

基于java语言+ Vue+ElementUI+ MySQL8.0.36数字化产科管理平台源码,妇幼信息化整体解决方案

基于java语言 VueElementUI MySQL8.0.36数字化产科管理平台源码&#xff0c;妇幼信息化整体解决方案 数字化产科管理平台是为医院产科量身定制的信息管理系统。它管理了孕妇从怀孕开始到生产结束42天一系列医院保健服务信息。该系统由门诊系统、住院系统、数据统计模块三部分组…

昇思25天学习打卡营第14天|Pix2Pix实现图像转换

Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到真实图片、灰度图到彩色图、航空图到…

MSPM0G3507——滴答定时器和普通定时

滴答定时器定时&#xff1a;&#xff08;放在主函数即可&#xff09; volatile unsigned int delay_times 0;//搭配滴答定时器实现的精确ms延时 void delay_ms(unsigned int ms) {delay_times ms;while( delay_times ! 0 ); } //滴答定时器中断 void SysTick_Handler(…

桌面快充插线板+伸缩数据线,轻松实现1+1>2

手机、平板、笔记本等电子设备已成为我们日常工作和学习的必备工具。然而,随着设备数量的增加,充电问题也日益凸显。桌面空间有限,多个快充头不仅显得杂乱无章,而且效率低下,无法满足我们高效办公的需求。 在这样的背景下,倍思Nomos氮化镓100W桌面充电站凭借其创新的设计和强大…

下载,连接mysql数据库驱动(最详细)

前言 本篇博客&#xff0c;我讲讲如何连接数据库&#xff1f;我使用mysql数据库举例。 目录 下载对应的数据库jar 包 百度网盘 存有8.4.0版本压缩包&#xff1a;链接&#xff1a;https://pan.baidu.com/s/13uZtXRmuewHRbXaaCU0Xsw?pwduipy 提取码&#xff1a;uipy 复制这…

Day05-04-持续集成总结

Day05-04-持续集成总结 1. 持续集成2. 代码上线目标项目 1. 持续集成 git 基本使用, 拉取代码,上传代码,分支操作,tag标签 gitlab 用户 用户组 项目 , 备份,https,优化. jenkins 工具平台,运维核心, 自由风格工程,maven风格项目,流水线项目, 流水线(pipeline) mavenpom.xmlta…

基于SpringBoot的时间管理系统

你好&#xff0c;我是专注于时间管理的技术爱好者&#xff01;如果你对时间管理有独到的见解&#xff0c;欢迎私信交流。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;Eclipse、MySQL数据库管理工具 系统展示 首页…

【C语言】 —— 编译和链接

【C语言】 —— 编译和链接 一、编译环境和运行环境二、翻译环境2.1、 预处理2.2、 编译&#xff08;1&#xff09;词法分析&#xff08;2&#xff09;语法分析&#xff08;3&#xff09;语义分析 2.3、 汇编2.4、链接 三、运行环境 一、编译环境和运行环境 平时我们说写 C语言…

区块链论文速读A会-ISSTA 2023(2/2)如何检测DeFi协议中的价格操纵漏洞

Conference&#xff1a;ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2023 第1~5篇区块链文章 请点击此…

2-5 softmax 回归的简洁实现

我们发现通过深度学习框架的高级API能够使实现线性回归变得更加容易。 同样&#xff0c;通过深度学习框架的高级API也能更方便地实现softmax回归模型。 本节如在上节中一样&#xff0c; 继续使用Fashion-MNIST数据集&#xff0c;并保持批量大小为256。 import torch from torc…

论文复现-基于决策树算法构建银行贷款审批预测模型(金融风控场景)

作者Toby&#xff0c;来源公众号&#xff1a;Python风控模型&#xff0c;基于决策树算法构建银行贷款审批预测模型 目录 1.金融风控论文复现 2.项目背景介绍 3.决策树介绍 4.数据集介绍 5.合规风险提醒 6.技术工具 7.实验过程 7.1导入数据 7.2数据预处理 7.3数据可…

隔离级别-隔离级别中的锁协议、隔离级别类型、隔离级别的设置、隔离级别应用

一、引言 1、DBMS除了采用严格的两阶段封锁协议来保证并发事务的可串行化&#xff0c;实现事务的隔离性&#xff0c;也可允许用户选择一个可以保证应用程序正确执行并且能够使并发度最大的隔离性等级 2、通常用隔离级别来描述隔离性等级&#xff0c;以下将主要介绍ANSI 92标准…

LaTeX教程(014)-LaTeX文档结构(14)

LaTeX教程(014)- LaTeX \LaTeX LATE​X文档结构(14) 2.3.3 multitoc - 将目录设置为多栏 multitoc包的使用方法相当简单&#xff0c;只需要调用这个包&#xff0c;并将要设置为多栏(默认是双栏)的目录指定到包选项中即可。如\usepackage[toc]{multitoc}&#xff0c;设置的就是…

GIT 使用相关技巧记录

目录 1、commit 用户信息变更 全局用户信息&#xff08;没有特殊配置的情况下默认直接用全局信息&#xff09; 特定仓库用户信息&#xff08;只针对于当前项目&#xff09; 方法一&#xff1a;修改config文件 方法二&#xff1a;命令方式 2、idea同一代码推向多个远端仓库…