请求与相应

news2024/9/23 5:22:45

从容器到Servlet

前面我们介绍了JSP的内置对象和Servlet的相关知识, 以及如何部署和开发一个Servlet。但是, 并没有详细介绍如何将Servlet与JSP结合起来使用。Web容器是JSP唯一可以识别的HTTP服务器, 所以必须了解Web容器如何生成请求和响应对象。本节将介绍容器HttpServlet之间的“来龙去脉”

web容器可以做什么

Web容器的作用就是创建一个Servlet实例, 并完成Servlet注册以及根据web.xml中的URL 进行响应。当请求来到容器时, Web容器会转发给对应的Servlet来处理请求。
当客户端请求HTTP服务器时, 会使用HTTP来传递请求、标头、参数等信息。HTTP协议是无状态的协议, 通过文本信息传递消息, 而Servlet是Java对象, 运行在Web容器中。当HTTP 服务器将请求转给Web容器时, Web容器会创建一个HttpServletRequest和HttpServletResponse对象, 将请求中的信息传递给HttpServletRequest对象, 而HttpServletResponse对象则作为对客户端响应的Java对象, 这一过程如图所示。

Web容器会根据配置信息(例如web.xml或者@WebServlet)查找相对应的Servlet并调用它的service() 方法。service() 方法会根据HTTP请求的方式, 决定是调月用doPost() 方法或者是doGet(方法。例如, HTTP请求的方式为post,则调用doPost() 方法。
在这里插入图片描述
在doPost() 方法中, 可以使用HttpServletRequest对象、HttpServletResponse对象。例如, 使用getParameter() 取得请求参数值, 使用getWriter() 取得输出流对象PrintWriter, 并进行响应处理。最后由Web容器转换为HTTP响应, 由HTTP服务器对浏览器做出响应。随后, Web容器将HttpServletRequest对象、HttpServletResponse对象销毁回收, 请求响应结束, 过程如图所示。
在这里插入图片描述
前面提到过HTTP协议是一种无状态的协议, 每一次的请求、响应后, 浏览器不会记得客户端的信息。Web容器根据每次请求都会创建新的request、response对象, 做出响应后就销毁该次的request、response对象。下次的请求、响应就与上一次的请求、响应对象无关了, 所以对于请求、响应的设置,是不能保存到下一次请求的。
类似于这种request、response对象的创建、服务、销毁, 就是Web容器提供的请求、响应的生命周期管理。

令人茫然地doXXX()方法

Servlet中的service() 方法包括多种:doGet() 、doPost() 、doHead() 等。当Method是POST时,请求会调用doPost() 方法; 当Method是GET时, 请求会调用doGet() 方法。在定义Servlet时,一般是继承HttpServlet类, 然后定义doPost() 或者doGet() 方法。在HttpServlet中doGet() 和doPost()方法的实现过程如下:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String msg = lStrings.getString("http.method_get_not_supported");
    this.sendMethodNotAllowed(req, resp, msg);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   String msg = lStrings.getString("http.method_post_not_supported");
   this.sendMethodNotAllowed(req, resp, msg);
}

假如, 在自定义Servlet时不实现doGet() 或者doPost() 方法, 那么程序就会调用以上方法。当客户端发出POST请求时, 就会收到错误消息, 如图所示。

package com.wujialiang;

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(name="hello",urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

在这里插入图片描述
因此, 在定义完Servlet后, 需要实现doGet() 或者doPost() 方法。

关于HttpServletRequest对象

HttpServletRequest对象是请求封装对象, 由Web容器生成, 使用该对象可以取得HTTP请求中的信息。在Servlet中, 也是使用该对象进行请求处理的。如果要共享request中的属性值, 可以将请求对象设置到该对象中, 那么Servlet在同一请求中就可以共享其对象。曾介绍过JSP的内置对象request实质上就是HttpServletRequest。本节将要讨论的是如何读取Body内容、取得上传文件、调派请求等。

getReader() getInputStream()读取body内容

在HttpServletRequest对象中, 可以运用getReader() 方法获取Body内容, 而使用getInputStream()方法获得上传文件的内容。下面利用一个示例来说明如何获取Body内容。

package com.wujialiang;

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.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name="GetReaderBody",urlPatterns = {"/getreader"})
public class GetReaderBody extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BufferedReader br =req.getReader();
        String input ="";
        String body = "";
        while ((input=br.readLine())!=null){
            body+=input+"<br>";
        }
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out =resp.getWriter();
        out.println("<!doctype html>");
        out.println("<html lang=\"zh-CN\">");
        out.println("<head>");
        out.println("<meta charset=\"UTF-8\">");
        out.println("<title>Document</title>");
        out.println("</head>");
        out.println("<body>");
        out.println(body);
        out.println("</body>");
        out.println("</html>");
        out.flush();
        out.close();
    }
}

index.jsp

<%@page language="java" import="java.util.*" pageEncoding="utf-8" %>
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<form action="/web05_war/getreader" method="post">
    用户名:
    <input type="text" name="username">
    <br>
    密码:
    <input type="password" name="pwd">
    <br>
    <input type="submit" value="提交" name="user_submit">
</form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
从图中可以看出, 页面用的是UTF-8编码, 所以在Servlet中都统一被转化为UTF-8编码,并且参数值都是一一对应的。以上是用get Reader() 方法获取Body内容。如果在form中设置enctype 的值为multipart/form-data, 表示从客户端上传文件, 获取Body的内容时就会获得一堆很奇怪的字符。
在这里插入图片描述

在这里插入图片描述
上传文件
index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" %>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>获取div内容</title>
</head>
<body>
<form action="/web01_war/body" method="post" enctype="multipart/form-data">
    <span>选择文件</span>
    <input type="file" name="filename">
    <br>
    <input type="submit" value="提交">
</form>
</body>
</html>

后台接口

package com.wujialiang;

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.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

@WebServlet(name="getreaderbody",urlPatterns = {"/body"})
public class GetReaderBody extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        byte[] body =readBody(req);
        String txtBody = new String(body,"UTF-8");
        String fileName = getFilename(txtBody);
        wirteToFile(fileName,body);
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<h1>上传成功</h1>");
        out.flush();
        out.close();
    }

    private byte[] readBody(HttpServletRequest req) throws IOException{
        int len = req.getContentLength();
        InputStream is = req.getInputStream();
        byte[] bt = new byte[len];
        int total = 0;
        while (total<len){
            int bytes = is.read(bt,total,len);
            total+=bytes;
        }
        return bt;
    }

    private String getFilename(String bodyText){
        int index = bodyText.indexOf("filename=\"")+10;
        String filename = bodyText.substring(index);
        filename = filename.substring(filename.lastIndexOf("\\")+1,filename.indexOf("\""));
        return filename;
    }

    private void wirteToFile(String filename,byte[] body){
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("d:/"+filename);
            fileOutputStream.write(body);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
程序运行结束后会在“d:/”文件夹下新建一个上传的文件,打开文件后可发现多了很多
页面中的信息,这是因为没有进行位置的过滤。其实在Servlet3.0及4.0中,可以利用getPart()
getParts()去获取上传文件。

getPart和getParts获取文件

在Servlet3.0中新增getPartO)和getParts()方法来处理上传文件的功能。getPart()用于处理单文件内容,getParts()用于处理多文件内容。在使用getPart()和getParts()方法时,必须使用MultipartConfig注解,这样Servlet才能获得Part对象。MultipartConfig的属性如表所示。

属性说明
fileSizeThreshold数值类型,当上传文件的大小大于该值时,内容将先写入缓存文件,默认值为0
location字符串类型,设置存放生成的文件目录地址,也是上传过程中临时文件的保存路径,执行Part.write()方法之后,临时文件将被清除
maxFileSize数值类型,设置允许文件上传的最大值,默认值为-1L,表示不限制大小
maxRequestSize数值类型,限制multipart/form-data请求的最大数,默认值为-lL,表示不限制大小
package com.wujialiang;

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

@MultipartConfig(location = "D:/home",maxFileSize = 1024*1024*10)
@WebServlet(name="getreaderbody",urlPatterns = {"/partbody"})
public class GetPartBody extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        Part part = req.getPart("filename");
        String filename = getFileName(part);
        part.write(filename);
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out =resp.getWriter();
        out.println("<h1>上传成功</h1>");
        out.flush();
        out.close();
    }

    private String getFileName(Part part){
        if(part==null){
            return null;
        }
        String fileName = part.getHeader("content-disposition");
        if(fileName==null||fileName=="") {
            return null;
        }
        return getFilename(fileName);
    }

    private String getFilename(String bodyText){
        int index = bodyText.indexOf("filename=\"")+10;
        String filename = bodyText.substring(index);
        filename = filename.substring(filename.lastIndexOf("\\")+1,filename.indexOf("\""));
        return filename;
    }
}

html页面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" %>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>获取div内容</title>
</head>
<body>
<form action="/web01_war/partbody" method="post" enctype="multipart/form-data">
    <span>选择文件</span>
    <input type="file" name="filename">
    <br>
    <input type="submit" value="提交">
</form>
</body>
</html>

在这里插入图片描述
上传文件
在这里插入图片描述
在这里插入图片描述
上传多个文件
修改servlet

package com.wujialiang;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

@MultipartConfig(location = "D:/home",maxFileSize = 1024*1024*10)
@WebServlet(name="getreaderbody",urlPatterns = {"/partbody"})
public class GetPartBody extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        Collection<Part> parts = req.getParts();
        for (Part part:
             parts) {
            String filename = getFileName(part);
            part.write(filename);
        }
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out =resp.getWriter();
        out.println("<h1>上传成功</h1>");
        out.flush();
        out.close();
    }

    private String getFileName(Part part){
        if(part==null){
            return null;
        }
        String fileName = part.getHeader("content-disposition");
        if(fileName==null||fileName=="") {
            return null;
        }
        return getFilename(fileName);
    }

    private String getFilename(String bodyText){
        int index = bodyText.indexOf("filename=\"")+10;
        String filename = bodyText.substring(index);
        filename = filename.substring(filename.lastIndexOf("\\")+1,filename.indexOf("\""));
        return filename;
    }
}

jsp修改

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" %>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>获取div内容</title>
</head>
<body>
<form action="/web01_war/partbody" method="post" enctype="multipart/form-data">
    <span>选择文件1</span>
    <input type="file" name="filename1">
    <br>
    <span>选择文件2</span>
    <input type="file" name="filename2">
    <br>
    <input type="submit" value="提交">
</form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
上传多个文件成功
在这里插入图片描述

使用RequestDispatcher调派请求

在Web程序中,经常是由多个Servlet来完成请求.RequestDispatcher接口就是为了多个Servlet
之间的调整而实现的。该接口可以由HttpServletRequest的getRequestDispatcher(方法取得。调用时
指定跳转的URL地址即可完成跳转动作。RequestDispatcher接口有两种方法实现跳转Servlet:
include()和forward()。

include

include方法的含义是可以在当前的Servlet中显示另外一个Servlet中的内容
新建GetRequestDispatcherSecond.java

package com.wujialiang;

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.io.PrintWriter;

@WebServlet(name="GetRequestDispatcherSecond",urlPatterns = {
        "/include_second"
},loadOnStartup = 0)
public class GetRequestDispatcherSecond extends HttpServlet {
    private static  final long serialVersionUID=1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("<h1>second Servlet</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

GetRequestDispatcher.java

package com.wujialiang;

import javax.servlet.RequestDispatcher;
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.io.PrintWriter;

@WebServlet(name="GetRequestDispatcher",urlPatterns = {
        "/include"
},loadOnStartup = 0)
public class GetRequestDispatcher extends HttpServlet {
    private static  final long serialVersionUID=1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("<h1>first Servlet</h1>");
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/include_second");
        requestDispatcher.include(req,resp);
        out.println("<h1>including servlet</h1>");
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

在这里插入图片描述

forward()方法

forward()方法是RequestDispatcher中的另一种Servlet跳转方法,只是它的含义是跳转到其他
的Servlet,.而不会再返回跳转前的Servlet。forward()方法在Servlet中经常用到,因为很多业务逻
辑都是跳转到其他的Servlet中进行处理。下面利用一个实例说明其用法并且建立简单的模型架构。
HelloServlet.java

package com.wujialiang;

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.io.PrintWriter;

@WebServlet(name="hello",urlPatterns = {
        "/hello"
},loadOnStartup = 0)
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        String msg = (String)req.getAttribute("msg");
        out.println("<h1>Hello "+msg+"</h1>");
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

ForwardServlet.java

package com.wujialiang;

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(name="forward",urlPatterns = {
        "/forward"
},loadOnStartup = 0)
public class ForwardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        req.setAttribute("msg",username);
        req.getRequestDispatcher("/hello").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

在这里插入图片描述

关于HttpResponse对象

HttpServletResponse是用于对浏览器做出响应的操作对象, 可以设置响应类型, 也可以直接输出HTML内容。
通常情况下, 使用setContentType() 设置JSP响应类型, 使用getWriter() 取得PrintWriter对象或者使用getOutputStream() 取得ServletOutputStream流对象, 使用setHeader() 、addHeader() 设置标头, 使用sendRedirect() 、sendError() 对页面进行重定向或者是发送错误消息。

使用getWriter()输出字符串

在前面的例子中,经常可以看到使用get Writer() 方法获取PrintWriter对象, 指定字符串对浏览器输出HTML代码。
通常情况下, 在对浏览器做出响应的同时会设置字符编码, 因为默认的编码是GBK或者是ISO-8859-1, 输出中文时会显示乱码, 所以需要设置支持中文的字符编码格式。这里有两种设置编码格式方式:使用setContentType() 或者setCharacter Encoding() 方法。
设置编码语句为:

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

设置编码的时候需要在获得PrintWriter对象或者ServletOutputStream流对象之前进行,否则无效。如果请求的参数中有中文,还需要设置在请求中支持中文字符编码,而且要注意与响应的编码保持一致。

在Servlet开发中, 必须告诉浏览器是以何种方式处理响应(内容类型) , 所以要设置响应标头。在设置context-type中, 指定MIME类型后, 浏览器就能知道标头类型。MIME类型有text/html、application/pdf、application/jar、application/x-zip、image/jpeg等。在应用程序中, 可以在web.xml中设置MIME类型。例如:

<mime-mapping>
  <extension>jar</extension>
  <mime-type>application/jar</mime-type>
</mime-mapping>

<extension>用于设置文件的后缀, <mime-type>用于设置对应的MIME类型名称。在前面的例子中,曾介绍过请求参数是中文的例子。这里通过实例说明请求参数是中文和响应中也有中文时应该如何发送请求。
index.jsp

<%@page pageEncoding="utf-8" import="java.util.*" %>
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div>
    <h1>调查问卷</h1>
    <form action="/web07_war/resp" method="post">
        姓名:
        <input type="text" name="name">
        <br>
        邮箱:
        <input type="text" name="email">
        <br>
        你喜欢的明星是:
        <select name="star" multiple>
            <option value="成龙">成龙</option>
            <option value="邓超">邓超</option>
            <option value="洪金宝">洪金宝</option>
        </select>
        <input type="submit" value="提交">
    </form>
</div>
</body>
</html>

接口

package com.wujialiang;

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.io.PrintWriter;

@WebServlet(name = "getResponseServlet",urlPatterns = {
        "/resp"
})
public class getResponseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String name = req.getParameter("name");
        String eamil = req.getParameter("email");
        String[] startName = req.getParameterValues("star");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("您好,"+name);
        out.println("<br>您的邮箱为:"+eamil);
        String likeStars = "";
        for (String s : startName) {
            likeStars+=" "+s;
        }
        out.println("<br>您喜欢的明星为:"+likeStars);
        out.close();
    }
}

在这里插入图片描述
在这里插入图片描述

使用getOutoutStream输出二进制字符串

getOutputStream() 是为了取得输出流而设置的, 在大多数情况下, PrintWriter对象就能解决问题。但是对于上传文件和下载文件则需要用到字节输出流。通过getOutputStream() 方法可以取得ServletOutputStream对象, 它是OutputStream的子类。
resources下新建doc文件夹,该文件夹下新增test.doc
编写downloadServlet.java

package com.wujialiang;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.io.InputStream;

@WebServlet(name = "download",urlPatterns = {
        "/down"
})
public class downloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/msword");
        resp.addHeader("Content-dispotion","attachment;filename=test.doc");

        InputStream in =getServletContext().getClassLoader().getResourceAsStream("doc/test.doc");
        ServletOutputStream os = resp.getOutputStream();
        byte[] bytes = new byte[1024];
        int len=-1;
        while ((len=in.read(bytes))!=-1){
            os.write(bytes,0,len);
        }
        //关闭输入输出流
        in.close();
        os.close();

    }
}

在这里插入图片描述

sendRedirect和sendError方法

sendRedirect

redirectServlet.js

package com.wujialiang;

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.io.PrintWriter;

@WebServlet(name = "redirectServlet",urlPatterns = {
        "/redirect2"
})
public class redirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("我是redirect2页面");
        out.close();
    }
}

sendRedirectServlet.java

package com.wujialiang;

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.io.PrintWriter;

@WebServlet(name = "sendRedirectServlet",urlPatterns = {
        "/redirect"
})
public class sendRedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("跳转到另一个页面");
        resp.sendRedirect(req.getContextPath()+"/redirect2");
        out.println("跳转完成");
        out.close();
    }
}

访问http://localhost:8080/web07_war/redirect跳转到了http://localhost:8080/web07_war/redirect2
在这里插入图片描述
从中可以看出, 跳转到redirect2后, 只显示其内容, 而不显示跳转前的Servlet内容。

sendError

如果在处理请求的时候发生错误, 就可以用send Error) 方法传递服务器的状态和错误消息。例如,请求的页面地址不存在,则可以发送如下错误信息:

response.sendError(HttpServletResponse.SC_NOT_FOUND);

SC_NOT_FOUND表示资源文件不存在, 服务器会响应404错误代码, 错误代码统一定义在HttpServletResponse接口上, 还可以自定义错误信息, 程序如下:

response.sendError(HttpServletResponse.SC NOTFOUND, "页面错误");

sendErrorServlet.java

package com.wujialiang;

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(name = "error",urlPatterns = {
        "/error"
})
public class sendErrorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,"不允许get请求");
    }
}

在这里插入图片描述

常见的http错误请求码

错误代码说明
401访问被拒绝
401.2服务器配置导致登录失败
403禁止访问
403.6IP地址被拒绝
403.9用户数过多
404没有找到文件或目录
405用来访问本页面的HTTP不被允许(方法不被允许)
406客户端浏览器不接受所请求页面的MIME类型
500内部服务器错误
504网关超时
505HTTP版本不受支持

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

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

相关文章

来上海一个月的记录、思考和感悟

作者 | gongyouliu 编辑 | gongyouliu 从4月3号早上来上海&#xff0c;到今天差不多整整一个月了&#xff0c;也是自己正式从杭州离职创业&#xff08;我更愿意称之为自由职业者&#xff0c;毕竟我没有招聘全职员工&#xff0c;有两个朋友业余时间在帮我&#xff09;的第一个月…

SAP UI5 之Bootstrap(引导)笔记二

文章目录 Setting up Visual Studio Code for UI5 development1.0 官网 Walkthrough学习-Bootstrap 引导加载1.0.1 在 index.html中新增script标签1.0.2 在webapp 下面新增index.js文件1.0.3启动UI5的服务 Setting up Visual Studio Code for UI5 development 学习链接 Setti…

如何正确部署Redisearch和Rejson(附*.so文件免费下载)

1 缘起 项目需要。 最近的一个项目需要做文本搜索,技术选型:Redis的两个组件Redisearch和ReJSON。 Redisearch和ReJSON是Redis的两个组件: RediSearch为Redis提供查询、二次索引和全文搜索。使用RediSearch,首先要在Redis数据上声明索引。然后使用RediSearch查询语言来查…

【电子通识】颜色的困惑:什么是国际通用Panone(潘通)

Pantone 是世界知名的色彩权威机构&#xff0c;也是色彩系统的供应商&#xff0c;为许多行业提供专业色彩选择。在 Pantone 之前&#xff0c;每个印刷公司都有自己的色彩指南。比如都是“黄色”&#xff0c;但由于印刷方式有所不同&#xff08;具体取决于每个油墨公司如何解释该…

学习之-Mysql Sql 优化之 Explain

在开发中&#xff0c;往往遇到一些慢查询语句&#xff0c; 我们需要对慢查询进行优化。Explain工具就是用来分析某个慢查询执行情况的工具。通过在select 语句前加上explain 关键字&#xff0c;然后执行就会得到某个sql 执行计划信息&#xff0c;通过分析执行计划&#xff0c;我…

vue相关知识导学

学习资料 Vue 相关源码地址&#xff1a; vue2.0 GitHub - vuejs/vue: This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/coreVue3.0 GitHub - vuejs/core: &#x1f596; Vue.js is a progressive, incrementally-adoptable JavaScri…

【从0到1了解Libarchive】Libarchive的用途意义以及成功入门Libarchive

目录 0 如果你还不知道Libarchive是什么请一定要先看一下 1 简介 1.1 为什么实现Libarchive 1.2 到底都有谁在用呢&#xff1f; 1.3 Libarchive都有哪些功能 1.4 我们可以通过这些获取更多信息 1.5 如何贡献 2 Libarchive归档与压缩 3 Libarchive编译 4 Libarchive简…

maven gpg报错:no default secret key: No secret key signing failed: No secret key

一、问题描述 我这边情况是这样的&#xff0c;原本在A电脑上&#xff0c;通过maven打包安装都是好的&#xff0c;最近新弄了台电脑&#xff0c;然后把A电脑的gpg秘钥通过Kleopatra的方式直接导出来 然后在B电脑上通过Kleopatra导入&#xff0c;整了很久&#xff0c;在IDEA中执…

FreeRTOS 事件标志组

文章目录 一、事件标志组简介二、创建事件标志组1. 函数 xEventGroupCreate()2. 函数 xEventGroupCreateStatic() 三、设置事件位1. 函数 xEventGroupClearBits()2. 函数 xEventGroupClearBitsFromISR()3. 函数 xEventGroupSetBits()4. 函数 xEventGroupSetBitsFromISR() 四、获…

Linux pthread线程操作 和 线程同步与互斥操作

在Linux系统中玩线程&#xff0c;使用pthread&#xff0c;这篇博客记录如何创建线程和使用线程和线程的同步与互斥。 还有一份nginx线程池的代码供大家阅读学习&#xff01; 目录 一、简介 什么是线程 线程的优点、缺点 线程的应用场合 二、线程的使用 1. 创建线程 - p…

如何评价聚类结果的好坏?

聚类有效性的评价可分为内部指标和外部指标&#xff0c;内部指标是一种无监督的评价方法&#xff0c;它对聚类结果的评价不需要借助样本集的真实标签&#xff0c;仅利用样本集自身 结构信息对聚类结果进行评价&#xff1b;而外部指标是一种有监督的评价方法&#xff0c;它通过对…

简单毛概刷题网页制作 3.0(拖欠近一年版)

原因是大概一年之前学校的毛概期末刷题网站突然崩了&#xff0c;但是一直没有修复。当时眼看着复习时间逐渐被压缩&#xff0c;自己啥也做不了&#xff0c;遂自学前端完成毛概刷题网页一枚。 最早的毛概刷题网站仅仅是 1.0 版本&#xff08;传送门&#xff09;&#xff0c;功能…

Microsoft office Word 批注相关问题解决

Microsoft office word 批注相关问题解决 目录 Microsoft office word 批注相关问题解决1.增添并显示批注2.批注显示及取消操作3.更改批注者姓名4.将Microsoft office Word文档中已批注的名字以及缩写修改为自己需要的4.1将Microsoft office Word文档中已批注的名字修改为自己需…

STM32开发(十八)STM32F103 片内资源 —— 窗口看门狗 WWDG 详解

文章目录 一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解五、结果演示 一、基础知识点 独立看门狗和窗口看门狗的区别&#xff1a; 独立看门狗在系统在待机、停机、睡眠阶段还会起效果&#xff0c;这就会导致在做低功耗的时候&#xff0c;看门狗还是会…

Elasticsearch:定制 Elasticsearch 镜像

在很多时候&#xff0c;我们希望定制我们的 Elasticsearch 镜像&#xff0c;比如&#xff0c;我们需要安装一些额外的插件&#xff0c;或者如果我们想要一个带有同义词文件和自定义配置的 Elasticsearch&#xff1f;或者我们需要一些相应的配置等。我们想在每次的 docker 部署中…

华为实习笔试复盘(1)配送站和客户问题

写在前面 自己玩了很多项目&#xff0c;但是最近准备秋招的过程中&#xff0c;发现自己对于算法和编程语言的基本功夫实在是太欠缺了。 投递了华为的实习岗位&#xff0c;4.26参加机考&#xff0c;一做题就发现了自己很多地方都不会。这里写下笔试后的复盘以警醒自己。 题目 …

服务网关Gateway

前言 API 网关出现的原因是微服务架构的出现&#xff0c;不同的微服务一般会有不同的网络地址&#xff0c;而外部客户端可能需要调用多个服务的接口才能完成一个业务需求&#xff0c;如果让客户端直接与各个微服务通信&#xff0c;会有以下的问题&#xff1a; 破坏了服务无状态…

python毕业设计之django+vue企业员工在线办公OA系统

该系统分用户和管理员。 管理员界面&#xff0c;具有以下功能&#xff1a; &#xff08;1&#xff09;添加用户&#xff1a;管理员添加本系统的用户信息。 &#xff08;2&#xff09;添加部门信息&#xff1a;管理员添加本系统的部门信息。 &#xff08;3&#xff09;添加职位信…

GLM:ChatGLM的基座模型

介绍 ChatGLM-6B&#xff1a;https://github.com/THUDM/ChatGLM-6B &#xff0c;主要是能够让我们基于单卡自己部署。ChatGLM的基座是GLM: General Language Model Pretraining with Autoregressive Blank Infilling论文中提出的模型。 动机 预训练语言吗模型大体可以分为三…

【MySQL约束】数据管理实用指南

1、数据库约束的认识 数据库约束的概念&#xff1a;数据库的约束是关系型数据库的一个重要的功能&#xff0c;它提供了一种“校验数据”合法性的机制&#xff0c;能够保证数据的“完整性”、“准确性”和“正确性” 数据库的约束&#xff1a; not null&#xff1a;不能存储 nul…