百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程文章 > 正文

Servlet基本原理与常见API方法的应用

qiyuwang 2024-10-07 15:24 9 浏览 0 评论

?1.Tomcat如何调用Servlet

?1.1Servlet原理

Servlet是属于上层建筑,它处在应用层,它的下层有传输层,网络层,数据链路层,硬件,属于“经济基础”,毕竟下层经济基础决定上层建筑。前面说过,Servlet是一组操作HTTP的API,Tomcat可作为HTTP服务器来处理请求,这个处理请求的关键就是调用Servlet来操作HTTP给客户端做出响应。

我们所写的Servlet代码没有main方法,那他是如何运行的呢?其实是Tomcat在调用Servlet,Tomcat其实就是一个应用程序,是运行在用户态上的一个普通的Java进程。

当浏览器发送请求给服务器的时候,Tomcat作为HTTP Server会调用Serlvet API,然后执行我们所写的Servlet程序来处理请求。

处理请求的过程中牵涉的不仅仅只有HTTP,还有其他层的协议,但是我们并没有感知到其他层协议的细节,只关注了应用层HTTP协议的细节,这就是协议分层好处,程序员在实现处理请求时,不必去关心应用层下面的细节。

?1.2Tomcat的执行逻辑

为了方便描述Tomcat的执行逻辑,我们使用伪代码的形式来分析:

初始化与收尾工作,又细分为以下几部分:

1)从指定的目录中找到Servlet类,并加载。

2根据加载的结果,给这些类型创建实例。

3)创建好实例后,调用Servlet对象中的 init 方法。

4)创建TCP socket对象,监听8080端口,等待客户端来连接。

5)如果请求处理完毕,也就是处理请求的循环退出了,那Tomcat也结束了,调用 destroy 方法结束进程,但是这个环节不一定可靠,正常退出的情况下,需要在管理端口(8005)去调用 destroy ,将Tomcat关闭,但很多时候都是直接杀死进程来达到关闭的目的,此时根本来不及调用 dsetroy 方法。

class Tomcat {
 
    // 用来存储所有的 Servlet 对象
    private List<Servlet> instanceList = new ArrayList<>();
    public void start() {
 
        // 根据约定,读取 WEB-INF/web.xml 配置文件;
        // 并解析被 @WebServlet 注解修饰的类

        // 假定这个数组里就包含了我们解析到的所有被 @WebServlet 注解修饰的类. 
        Class<Servlet>[] allServletClasses = ...;

        // 这里要做的的是实例化出所有的 Servlet 对象出来;
        for (Class<Servlet> cls : allServletClasses) {
 
            // 这里是利用 java 中的反射特性做的
            // 实际上还得涉及一个类的加载问题,因为我们的类字节码文件,是按照约定的
            // 方式(全部在 WEB-INF/classes 文件夹下)存放的,所以 tomcat 内部是
            // 实现了一个自定义的类加载器(ClassLoader)用来负责这部分工作。

            Servlet ins = cls.newInstance();
            instanceList.add(ins);
        }

        // 调用每个 Servlet 对象的 init() 方法,这个方法在对象的生命中只会被调用这一次;
        for (Servlet ins : instanceList) {
 
            ins.init();
        }

        // 利用我们之前学过的知识,启动一个 HTTP 服务器
        // 并用线程池的方式分别处理每一个 Request
        ServerSocket serverSocket = new ServerSocket(8080);
        // 实际上 tomcat 不是用的固定线程池,这里只是为了说明情况
        ExecuteService pool = Executors.newFixedThreadPool(100);

        while (true) {
 
            Socket socket = ServerSocket.accept();
            // 每个请求都是用一个线程独立支持,这里体现了我们 Servlet 是运行在多线程环境下的
            pool.execute(new Runnable() {
 
                doHttpRequest(socket);//处理请求
            });
        }
        // 调用每个 Servlet 对象的 destroy() 方法,这个方法在对象的生命中只会被调用这一次;
        for (Servlet ins : instanceList) {
 
            ins.destroy();
        }
    }

    public static void main(String[] args) {
 
        new Tomcat().start();
    }
}

Tomcat处理请求工作:

1)读取socket中的数据,并按照HTTP协议的格式来进行解析,获取请求。

2)判断请求是需要静态内容还是动态内容,如果是静态内容,可以在根路径上找到目的文件,返回请求

3)如果是动态文件,则需要通过URL上的一级路径与二级路径来确定通过哪一个Servlet类来进行处理,没有的话就会返回404

4)找到对应Servlet对象,调用对象里面的 service 方法,根据请求的方法来调用对应的 do... 方法

class Tomcat {
 
    void doHttpRequest(Socket socket) {
 
        // 参照我们之前学习的 HTTP 服务器类似的原理,进行 HTTP 协议的请求解析,和响应构建
        HttpServletRequest req = HttpServletRequest.parse(socket);
        HttpServletRequest resp = HttpServletRequest.build(socket);
        
        // 判断 URL 对应的文件是否可以直接在我们的根路径上找到对应的文件,如果找到,就是静态
        // 直接使用我们学习过的 IO 进行内容输出
        if (file.exists()) {
 
            // 返回静态内容
            return;
       }
        
        // 走到这里的逻辑都是动态内容了
        
        // 根据我们在配置中说的,按照 URL -> servlet-name -> Servlet 对象的链条
        // 最终找到要处理本次请求的 Servlet 对象
        Servlet ins = findInstance(req.getURL());
        
        // 调用 Servlet 对象的 service 方法
        // 这里就会最终调用到我们自己写的 HttpServlet 的子类里的方法了
        try {
 
       		ins.service(req, resp); 
       } catch (Exception e) {
 
            // 返回 500 页面,表示服务器内部错误
       }
   }
}

service方法执行逻辑:

class Servlet {
 
    public void service(HttpServletRequest req, HttpServletResponse resp) {
 
        String method = req.getMethod();
        if (method.equals("GET")) {
 
            doGet(req, resp);
       } else if (method.equals("POST")) {
 
            doPost(req, resp);
       } else if (method.equals("PUT")) {
 
            doPut(req, resp);
       } else if (method.equals("DELETE")) {
 
            doDelete(req, resp);
       } 
       ......
   }
}

在整个流程中,有三个关键的方法:

init

?2.Servlet中关键的几个API

?2.1常用方法列举

HttpServlet关键方法:

方法名称

调用时机

init

在 HttpServlet 实例化之后被调用一次

destory

在 HttpServlet 实例不再使用的时候调用一次

service

收到 HTTP 请求的时候调用

doGet

收到 GET 请求的时候调用(由 service 方法调用)

doPost

收到 POST 请求的时候调用(由 service 方法调用)

doPut/doDelete/doOptions/…

收到其他请求的时候调用(由 service 方法调用)

这些方法的调用时机,就构成了“Servlet”的生命周期。

HttpServletRequest关键方法:

方法

描述

String getProtocol()

返回请求协议的名称和版本。

String getMethod()

返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。

String getRequestURI()

从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的层次路径部分。

String getContextPath()

返回指示请求上下文的请求 URI 部分(一级路径)。

String getQueryString()

返回包含在路径后的请求 URL 中的查询字符串。

Enumeration getParameterNames()

返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。

String getParameter(String name)

以字符串形式返回请求参数的值,或者如果参数不存在则返回null。

String[] getParameterValues(String name)

返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。

Enumeration getHeaderNames()

返回一个枚举,包含在该请求中包含的所有的头名。

String getHeader(String name)

以字符串形式返回指定的请求头的值。

String getCharacterEncoding()

返回请求主体中使用的字符编码的名称。

String getContentType()

返回请求主体的 MIME 类型,如果不知道类型则返回 null。

int getContentLength()

以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。

InputStream getInputStream()

用于读取请求的 body 内容. 返回一个 InputStream 对象.

HttpServletResponse关键方法:

方法

描述

void setStatus(int sc)

为该响应设置状态码。

void setHeader(String name, String value)

设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值,可以实现页面的刷新

void addHeader(String name, String value)

添加一个带有给定的名称和值的 header. 如果name 已经存在,不覆盖旧的值, 并列添加新的键值对

void setContentType(String type)

设置被发送到客户端的响应的内容类型。

void setCharacterEncoding(String charset)

设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。

void sendRedirect(String location)

使用指定的重定向位置 URL 发送临时重定向响应到客户端。

PrintWriter getWriter()

用于往 body 中写入文本格式数据.

OutputStream getOutputStream()

用于往 body 中写入二进制格式数据.

?2.2Post请求的构造

在同一webapp里面,关联路径不能够相同,不然Tomcat跑不起来,对于GET请求,可以使用URL的查询字符串进行构造,但是POST请求不行,需要使用form或者ajax。

构造Post请求(使用ajax构造):

在webapp目录下创建一个HTML文件,用来构造POST请求,首先我们先的引入 jquery 依赖(博主使用的是本地导入,你可以如果网络地址: https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js 导入依赖),然后调用ajax构造请求。

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
        $.ajax({
   
            type: "post",
            url: "method",
            success: function (body){
   
                console.log(body);
            }
        })
    </script>

注意上面的URL属性不能加 / ,加上表示的就是绝对路径了,当然你也可以使用 ./ 来表示相对路径,但是在Servlet注解关联路径必须得加上 /

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/method")
public class MethodServlet extends HttpServlet {
 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        resp.getWriter().write("POST请求");
    }
}

我们访问 http://127.0.0.1:8080/hello_servlet/test.html 来看控制台输出的返回结果。

我们发现与我们的预期不一致,我们处理请求的时候返回了 POST请求 ,而这里显示了 POST?? ,原因是发生了乱码,idea默认编码格式为 utf-8 ,Windows默认的编码格式是 gbk ,那浏览器解析body的时候也是以 gbk 格式去进行解析,要想统一格式,就得先告诉浏览器响应数据的编码格式是什么,我们需要在Servlet程序里面设置字符格式,设置方法为调用HttpServletResponse对象的 setContentType 方法,传入参数 text/html; charset=utf8

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/method")
public class MethodServlet extends HttpServlet {
 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("POST请求");
    }
}

重新打包部署,刷新页面:

?2.3获取请求信息

对于请求的信息,我们运用HttpServletRequest类的方法来进行请求信息的获取:

比如我们访问的url为 http://127.0.0.1:8080/hello_servlet/showreq?key=10&a=100&b=200 ,很明显这是使用查询字符串构造的一个GET请求,通过HttpServletRequest类一系列对应的方法,我们可以获取到这个请求的方法类型,协议版本,URL,查询字符串,头部的一些信息等。其中查询字符串与头部信息的获取先要使用getParameterNames方法或者getHeaderNames方法获取所有的查询字符串或头部信息的所有 key 值,这个一个枚举对象,然后在根据getParameter或者getHeader方法通过 key 值遍历枚举对象获取 value

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/showreq")
public class ShowRequestServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
    //访问链接:http://127.0.0.1:8080/hello_servlet/showreq?key=10&a=100&b=200
        StringBuilder stringBuilder = new StringBuilder();
        resp.setContentType("text/html; charset=utf-8");
        //1协议名称与版本
        stringBuilder.append("协议版本:");
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("<br>");
        //2方法类型
        stringBuilder.append("方法:");
        stringBuilder.append(req.getMethod());
        stringBuilder.append("<br>");
        //3获取查URL路径
        stringBuilder.append("URL路径:");
        stringBuilder.append(req.getRequestURI());
        stringBuilder.append("<br>");
        //4URL(不包括查询字符串后面的部分)
        stringBuilder.append("URL(不包括查询字符串后面的部分):");
        stringBuilder.append(req.getRequestURL());
        stringBuilder.append("<br>");

        //5一级路径
        stringBuilder.append("一级路径:");
        stringBuilder.append(req.getContextPath());
        stringBuilder.append("<br>");
        //6查询字符串
        stringBuilder.append("查询字符串:");
        stringBuilder.append(req.getQueryString());
        stringBuilder.append("<br>");
        //7正文编码格式
        stringBuilder.append("正文编码格式:");
        stringBuilder.append(req.getCharacterEncoding());
        stringBuilder.append("<br>");
        //8mine
        stringBuilder.append("mine:");
        stringBuilder.append(req.getContentType());
        stringBuilder.append("<br>");
        //9正文长度
        stringBuilder.append("正文长度:");
        stringBuilder.append(req.getContentLength());
        stringBuilder.append("<br>");
        //10获得每一个查询字符串的键值:
        stringBuilder.append("<h3>获得每一个查询字符串的键值:</h3>");
        Enumeration query = req.getParameterNames();
        while(query.hasMoreElements()) {
 
            String key = (String)query.nextElement();
            stringBuilder.append(key);
            stringBuilder.append(":");
            stringBuilder.append(req.getParameter(key));
            stringBuilder.append("<br>");
        }
        //11获得头部的键值
        stringBuilder.append("<h3>获得头部的键值:</h3>");
        Enumeration header = req.getHeaderNames();
        while(header.hasMoreElements()) {
 
            String key = (String)header.nextElement();
            stringBuilder.append(key);
            stringBuilder.append(":");
            stringBuilder.append(req.getHeader(key));
            stringBuilder.append("<br>");
        }
        resp.getWriter().write(stringBuilder.toString());
    }
}

结果:

?2.4Post请求信息的获取

我们知道post请求的请求信息在http格式中的 body 部分当中,而 body 中的请求内容的格式是有很多种的,比如最常见的有:

  1. x-www-form-urlencode格式,通过form表单或者postman构造。
  2. json格式
  3. form-data格式

x-www-form-urlencode格式:

k e y = v a l u e & k e y = v a l u e & . . . key=value\&key=value\&... k e y = v a l u e & k e y = v a l u e & . . .

form表单创建 x-www-form-urlencode格式 请求:

<!DOCTYPE html>
<html lang="ch">
<head>
    <meta charset="UTF-8">
    <title>post</title>
</head>
<body>
    <form action="./postParameter" method="post" accept-charset="utf-8">
        <span>userId</span>
        <input type="text" name="userId">
        <span>classId</span>
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>
</body>
</html>

Servlet程序接收和处理请求:

对于 x-www-form-urlencode格式 请求可以直接使用 HttpServletRequest 中的 getParameter 方法依据 key 来获取 value ,然后再将获取到的数据返回,form表单构造的请求会自动跳转页面。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/postParameter")
public class GetPostParameterServlet extends HttpServlet {
 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //获取post请求body请求中的参数
        //设置请求与响应编码格式
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf8");
        //比如useId =   classId=
        String userId = req.getParameter("userId");
        String classId = req.getParameter("classId");
        //写会数据
        resp.getWriter().write("userId=" + userId + ", " + "classId=" + classId);
    }
}

运行结果:

json格式:

{ \{ {

k e y : v a l u e , key:value, k e y : v a l u e ,

k e y : v a l u e , key:value, k e y : v a l u e ,

k e y : v a l u e , key:value, k e y : v a l u e ,

. . . ... . . .

} \} }

对于json格式,手动解析不容易,因为json里面的字段是可以嵌套的,但我们可以借助第三方库来解析处理json,比如Jackson,Jackson依赖导入过程如下:

处理json请求步骤:

第一步,在前端js代码中构造出格式为 json 格式的请求。

其中 ajax 构造 post 请求,使用 contentType 来说明请求的类型, data 属性来设置 body 的内容。

<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <title>json</title>
</head>
<body>
    <!-- 前端HTML部分 -->
    <input type="text" id="userId"> 
    <input type="text" id="classId">
    <input type="button" id="submit" value="提交"> 
	<!-- 如果已经准备好本地的jQuery就导入本地的,否则可以找网上的jQuery cdn网络路径 -->
    <script src="./jquery3.6.0.js"></script>

    <script>
        let userIdInput = document.querySelector("#userId");
        let classIdInput = document.querySelector("#classId");
        let button = document.querySelector("#submit");

        button.onclick = function() {
   
            $.ajax({
   
                type : "post",
                url: "getJsonPost",
                contentType: "appliaction/json",
                data:JSON.stringify({
   
                    userId: userIdInput.value,
                    classId:classIdInput.value
                }),
                success: function(body){
   
                    console.log(body);
                }
            })
        }
    </script>
</body>
</html>

第二步,在java后端代码中使用Jackson处理。

  • 1)创建Jackson核心对象ObjectMapper对象。
  • 2)读取请求中的body信息,该过程通过ObjectMapper对象的 readValue 方法实现。
  • 3)创建用来接受 json 数据的类。
  • 4) readValue 方法的参数有两个,第一个参数用来表示请求的来源,可以是路径字符串,与可以是 InputSream 对象,也可以是 File 对象,第二个参数表示接收json数据的类对象。
  • 5)处理并响应请求。
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

class User {
 
    public String userId;
    public String classId;
}
@WebServlet("/getJsonPost")
public class GetJsonPostServlet extends HttpServlet {
 
    //1.创建一个Jackson的核心对象
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //格式
        resp.setContentType("text/html; charset=utf8");
        //处理
        //2.读取body请求的内容,使用ObjectMapper对象的readValue方法来解析
        //就是将字符串转换成java的对象,readValue方法的第一个参数可以是路径字符串可以是输入流对象,引入可以是File对象
        //第二个参数,表示需要将请求的json格式数据转换成哪一个java对象
        User user = objectMapper.readValue(req.getInputStream(), User.class);
        System.out.println(user.userId);
        System.out.println(user.classId);
        resp.getWriter().write("userId=" + user.userId + "  ,classId=" + user.classId);
    }
}

运行结果:

readValue 方法基本原理:

  1. 读取json格式的数据,并解析成键值对。
  2. 便利这些键值对,获得 key ,并与所需传入的对象中的属性(反射)相比,如果 key 与属性的名字相同,则把 key 对应的 value 赋值给这个属性,否则就跳过,所有的键值对便利完后,这个对象差不多就被构造的差不多了。

?2.5响应的构造

案例1:设置响应状态码

设置方法很简单,只需要调用 httpServletResponse 对象中的 setStatus 方法就可以了

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //格式
        resp.setContentType("text/html; charset=utf8");
        //设置状态码
        int status = 200;
        resp.setStatus(status);

        resp.getWriter().write("hello,这是" + status + "状态码的响应内容!");
    }
}

启动程序,网页显示如下:

我把状态码修改为 404 ,网页显示如下:

那为什么不是之前我们所遇到的那种404页面呢?这是因为我们设置的页面响应内容就是 hello,这是404状态码的响应内容! ,可以理解为自定义的 404 状态响应页面,就像其他的网站,如果访问不到页面,显示的提醒页面也是不一样的,比如b站的页面是这个样子的:

案例2:自动页面刷新

自动页面刷新只要在响应中设置一个header: Refresh就能实现页面的定时刷新了,对于响应 header 的设置,我们可以通过 HttpServletResponse 对象中的 setHeader 方法来设置Refresh属性和刷新频率。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/autorefresh")
public class AutoRefreshServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //格式
        resp.setContentType("text/html; charset = utf8");
        //设置Refresh,第二个参数表示刷新频率,单位是秒
        resp.setHeader("Refresh", "1");
        //响应
        resp.getWriter().write("时间戳:" + System.currentTimeMillis());
    }
}

效果:

案例3:重定向案例

第一步,设置状态码为 302

第二步,设置header:Location,调用 setHeader 方法时,第一个参数填 Location ,表示设置 header 字段为 Location ,第二个参数为重定向的目的地址,你要重定向到哪一个网址就传入哪一个地址的字符串。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //格式
        resp.setContentType("text/html; charset = utf8");
        //设置状态码
        resp.setStatus(302);
        //设置重定向字段与地址,如跳转到力扣官网
        resp.setHeader("Location", "https://leetcode.cn/");
    }
}

效果:

当然,servlet提供了更为简便的重定向方法,就是使用 HttpServletResponse 类中的 sendRedirect 方法。

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        //格式
        resp.setContentType("text/html; charset = utf8");
        //设置状态码
//        resp.setStatus(302);
//        //设置重定向字段与地址,如跳转到力扣官网
//        resp.setHeader("Location", "https://leetcode.cn/");
        resp.sendRedirect("https://leetcode.cn/");
    }
}

效果与上面第一种方法是一样的。

原文:https://blog.csdn.net/m0_59139260/article/details/125578758

相关推荐

在Word中分栏设置页码一页两个页码的技巧!

施老师:在正常情况下,Word文档中一页只会出现一个页码。但在某种情况下,比如说:用了分栏后,我们希望一页中出现两个页码,那应该如何实现呢?今天,就由宁双学好网施老师来为大家讲一下,利用域来实现一页两...

如何在关键时刻向上自荐(如何在关键时刻做出正确选择)

抓住机会,挺身而出有种时刻叫“关键时刻”,关键时刻,作为一个认为自己有能力的、训练有素的人,应该考虑挺身而出,甚至应该不考虑就挺身而出。...

WPS Word:跨页的文档表格,快速调整为一页。#Excel

如何快速将跨页的文档表格调整为一页?需要根据两种情况分别处理。如果表格所有行的行高相同,调整为一页的方法有两种。第一种方法是将光标移动到表格内,然后将鼠标移动到表格右下角的方框处,按住鼠标左键向上拖动...

word文档插入下一页分节符(word下一页分页符)

在word文档中,对文档页面进行分页是特别常见的操作,其中的下一页分节符也是用得比较多的,但是一些人不太清楚在哪里设置,也不知道它具体能实现的功能是什么。接下来看看如何在word文档中插入下一页分节符...

word文档如何设置某一页纸张的方向

word文档页面方向有横向和纵向,纵向是默认的纸张方向,有时我们需要将页面设置为横向,或只设置其中某一页方向,应该怎么操作呢?一起来看看下面的详细介绍第一步:...

word怎么单独设置一页为横向(word2019怎样设置单独一页为横向)

word里面其中一页可以改为横向的吗?经过实际操作发现是完全可以的。...

Word如何设置分栏,如何一页内容同时显示一栏和两栏

我们使用Word文档,有时需要用到两栏的排版,甚至一页内容同时包含一栏和两栏的排版,这种格式怎么设置呢?具体步骤如下:首先是两栏排版的设置,直接点击Word文件上方工具栏【布局】,选择【分栏】下面的【...

Word怎么分页?这三个方法可以帮到你

我们不仅可以利用Word编辑文档,还可以编辑文集呢。但是有时候会出现两个部分的文章长短不一,我们需要对文档进行分页处理。这样可以方便我们对文档进行其他操作。那么Word怎么分页呢?大家可以采用下面这...

Word内容稍超一页,如何优化至单页打印?

如何将两页纸的内容,缩到一页打印呢?有时候一页纸多一点内容,我们完全可以缩一下,放到一页来打印。...

[word] word 表格如何跨行显示表头、标题

word表格如何跨行显示表头、标题在Word中的表格如果过长的话,会跨行显示在另一页,如果想要在其它页面上也显示表头,更直观的查看数据。难道要一个个复制表头吗?当然不是,教你简单的方法操作设置Wo...

Word表格跨页如何续上表?(word如何让表格跨页不断掉)

长文档的表格跨页时,你会发现页末空白太多了,这时要怎么调整?选中整张表格,右击【表格属性】,点击【行】选项,之后勾选【允许跨页断行】,点击确定即可解决空白问题。...

Word怎么连续自动生成页码,操作步骤来了!

Word怎么连续自动生成页码,操作步骤来了!...

word文档怎么把两页合并成一页内容?教你4种方法

word怎么把两页合并成一页?word怎么把两页合并成一页?用四种方法演示一下。·方法一:把这一个文档合并成一页,按ctrl加a全选文档,然后右键点击段落,弹出的界面行距改成固定值,磅值可以改小一点,...

如何将Word中的一页的纸张方向设置为横向?这里提供详细步骤

默认情况下,MicrosoftWord将页面定向为纵向视图。虽然这在大多数情况下都很好,但你可能拥有在横向视图中看起来更好的页面或页面组。以下是实现这一目标的两种方法。无论使用哪种方法,请注意,如果...

Word横竖混排你会玩吗?(word横排竖排混合)

我们在用Word排版的时候,一般都是竖版格式,但偶尔会需要到一些特殊的版式要求,比如文档中插入的一个表格,横向的内容比较多,这时就需要用到横版,否则表格显示不全。这种横竖版混排的要求,在Word20...

取消回复欢迎 发表评论: