Servlet知识点总结

目录

#创建并运行web项目

#Servlet的工作流程

#Servlet的生命周期

##实例和初始化时机

##就绪/调用/服务阶段

##销毁时机

#Tomcat 与 Servlet 是如何工作的

#HttpServletRequest对象

#接收请求常用方法

#解决请求乱码问题

#请求转发

#request作用域

#响应数据

#解决响应乱码问题

#重定向

#注意区别请求转发和重定向

#Cookie对象

##标识符 JSESSIONID Session

##ServletContext对象

###ServletContext对象的获取

##Servlet的三大域对象

#文件上传和下载

##文件上传

##文件下载

###超链接下载

###后台下载


@[TOC]

#创建并运行web项目

##1.Servlet的实现

    新建java文件-->添加web项目-->重写Servlet方法-->Tomcat部署web项目-->运行服务器

注意:Servlet类继承HttpServlet类时IDE会报错,因为HttpServlet类在Tomcat/lib文件夹的servlet-api.jar包下。所以需要new一个project library,文件选到刚刚说到的servlet-api.jar包,然后新创建的类就可以正常继承HttpServlet啦。

##2.重写Servlet方法

   满足 Servlet 规范只是让我们的类能够满足接收请求的要求,接收到请求后需要对请求进行分析,以 及进行业务逻辑处理,计算出结果,则需要添加代码,在规范中有一个叫做 service的方法,专门用来做 请求处理的操作,业务代码则可以写在该方法中。

##3.设置注解

在完成好了一切代码的编写后,还需要向服务器说明,特定请求对应特定资源。 开发servlet项目,使用@WebServlet将一个继承于javax.servlet.http.HttpServlet 的类定义为Servlet 组件。在Servlet3.0中 , 可以使用@WebServlet注解将一个继承于javax.servlet.http.HttpServlet的类 标注为可以处理用户请求的 Servlet。

 

 ##4.发布项目并启动服务

    到此,需要编写和配置的地方已经完成,项目已经完整了,但是如果需要外界能够访问, 还需要将项 目发布到服务器上并运行服务器。

1. 设置项目的站点名(项目对外访问路径)

2. 设置项目的Tomcat配置

3. 启动服务器

##5.访问并查看结果

   在项目正确发布到服务器上之后,用户即可通过浏览器访问该项目中的资源。注意 url 的 格式正确, tomcat 的端口为 8080。 

#Servlet的工作流程

1. 通过请求头获知浏览器访问的是哪个主机

2. 再通过请求行获取访问的是哪个一个web应用

3. 再通过请求行中的请求路径获知访问的是哪个资源

4. 通过获取的资源路径在配置中匹配到真实的路径,

5. 服务器会创建servlet对象,(如果是第一次访问时,创建servlet实例,并调用init方法进行初始化 操作)

6. 调用service(request, response)方法来处理请求和响应的操作

7. 调用service完毕后返回服务器 由服务器讲response缓冲区的数据取出,以http响应的格式发送给浏览器

#Servlet的生命周期

Servlet没有 main()方法,不能独立运行,它的运行完全由 Servlet 引擎来控制和调度。 所谓生命周 期,指的是 servlet 容器何时创建 servlet 实例、何时调用其方法进行请求的处理、 何时并销毁其实例的 整个过程。

##实例和初始化时机

当请求到达容器时,容器查找该 servlet 对象是否存在,如果不存在,则会创建实例并进行初始 化。

##就绪/调用/服务阶段

有请求到达容器,容器调用 servlet 对象的 service()方法,处理请求的方法在整个生命周期中可以被 多次调用; HttpServlet 的 service()方法,会依据请求方式来调用 doGet()或者 doPost()方法。但 是, 这两个 do 方法默认情况下,会抛出异常,需要子类去 override。

##销毁时机

当容器关闭时(应用程序停止时),会将程序中的 Servlet 实例进行销毁。 上述的生命周期可以通过 Servlet 中的生命周期方法来观察。在 Servlet 中有三个生命周 期方法, 不由用户手动调用,而是在特定的时机有容器自动调用,观察这三个生命周期方法 即可观察到 Servlet 的生命周期。

#Tomcat 与 Servlet 是如何工作的

1. Web Client 向 Servlet 容器(Tomcat)发出 Http 请求

2. Servlet 容器接收 Web Client 的请求

3. Servlet 容器创建一个 HttpServletRequest 对象,将 Web Client 请求的信息封装到这个对象 中 4. Servlet 容器创建一个 HttpServletResponse 对象

5. Servlet 容器调HttpServlet 对象service 方法,把 Request 与 Response 作为参数,传给 HttpServlet

6. HttpServlet 调用 HttpServletRequest 对象的有关方法,获取 Http 请求信息

7. HttpServlet 调用 HttpServletResponse 对象的有关方法,生成响应数据

8. Servlet 容器把 HttpServlet 的响应结果传给 Web Client

#HttpServletRequest对象

HttpServletRequest 对象:主要作用是用来接收客户端发送过来的请求信息,例如:请求的参数,发 送的头信息等都属于客户端发来的信息,service()方法中形参接收的是 HttpServletRequest 接口的实例 化对象,表示该对象主要应用在 HTTP 协议上,该对象是由 Tomcat 封装好传递过来。

#接收请求常用方法

// 获取客户端请求的完整URL (从http开始,到?前面结束)
    String url = req.getRequestURL().toString();
    System.out.println("获取客户端请求的完整URL:" + url);
    //获取请求时的部分路径(从项目站点名开始,到“?”前面结束
    String uri=req.getRequestURI();
    System.out.println("获取请求时的部分路径:"+uri);
    //获取请求时的参数字符串(从“?‘后面开,到最后的字符串)
    String queryString =req.getQueryString();
    System.out.println("获取请求时的参数字符串:"+queryString);
    //获取请求方法(Get和Post)
    String method =req.getMethod();
    System.out.println("获取请求方法:"+method);
    //获取当前协议版本(Http/1.1)
    String prototol =req.getProtocol();
    System.out.println("获取当前协议版本:"+prototol);
    //获取项目站点名(项目对外访问路径)
    String webapp =req.getContextPath();
    System.out.println("获取项目站点名:"+webapp);
//1.获取指定名称的参数值,返回字符串(重点)
    String uname=req.getParameter("uname");
    String upwd=req.getParameter("upwd");
    System.out.println("uname="+uname);
    System.out.println("upwd="+upwd);

    //2.获取指定名称参数的所有参数值,返回字符串数组(用于复选框传值)
    String[] hobbys=req.getParameterValues("hobby");
    for(String hobby:hobbys)
      System.out.println("爱好:"+hobby);

#解决请求乱码问题

方法一

req.setCharacterEncoding("UTF-8");

这种方式只针对 POST 有效(必须在接收所有的数据之前设定)

方法二

new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");

借助了String 对象的方法,该种方式对任何请求有效,是通用的。 Tomcat8起,以后的GET方式请求是不会出现乱码的。

#请求转发

请求转发,是一种服务器的行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保 存,地址栏中的 URL 地址不会改变,得到响应后,服务器端再将响应发送给客户端,从始至终只有一个 请求发出。

请求转发跳转的特点
1.服务端行为
2.地址栏不发生改变
3.从始至终只有一个请求
4.request数据可以共享
 
@WebServlet("/sr03")
public class Servlet03 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uname=req.getParameter("uname");
        System.out.println("uname03="+uname);

        req.getRequestDispatcher("sr04").forward(req,resp);  //请求转发跳转
@WebServlet("/sr04")
public class Servlet04 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uname=req.getParameter("uname");

        System.out.println("uname04="+uname);
    }
}

跳转后sr04也能接收(共享)到来自sr03的参数值

#request作用域

通过该对象可以在一个请求中传递数据,作用范围:在一次请求中有效,即服务器跳转有效。

设置域对象内容

@WebServlet("/sr05")
public class Servlet05 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet05...");

        //设置域对象内容
        req.setAttribute("name","admin");
        req.setAttribute("age",18);
        List<String> list=new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        req.setAttribute("list",list);

        req.getRequestDispatcher("index.jsp").forward(req,resp);
    }
}

 获取域对象内容

@WebServlet("/sr06")
public class Servlet06 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet06...");

        String name= (String) req.getAttribute("name");
        System.out.println("name="+name);
        Integer age= (Integer) req.getAttribute("age");
        System.out.println("age="+age);
        List<String> list= (List<String>) req.getAttribute("list");
        System.out.println(list.get(1));

    }
}

注意:区分和了解List和ArrayList

#响应数据

接收到客户端请求后,可以通过 HttpServletResponse 对象直接进行响应,响应时需要获取输出流。 有两种形式:

getWriter() 获取字符流(只能响应回字符)

getOutputStream() 获取字节流(能响应一切数据)

响应回的数据到客户端被浏览器解析。

注意:两者不能同时使用,只能相应一个请求

1.字符输出流

//getwrite 字符输出流(输出字符串)
    //获取字符输出流
    PrintWriter write=resp.getWriter();
    write.write("Hello");

2.字节输出流

//getOutputStream() 字节输出流(输出一切数据)
    ServletOutputStream out=resp.getOutputStream();
    out.write("Hi".getBytes());

#解决响应乱码问题

同时设置服务端和客户端的编码格式

方法一:分别设置

//设置服务端的编码格式
    resp.setCharacterEncoding("UTF-8");
    //设置客户端的编码格式和响应的MIME类型
    resp.setHeader("content-type","text/html;charset=UTF-8");

方法二:用一句同时设置

//同时设置客户端和服务端的编码格式
    resp.setContentType("text/html;charset=UTF-8");

#重定向

重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务器接收处理后,服务器会 进行响应,在响应的同时,服务器会给客户端一个新的地址(下次请求的地址 response.sendRedirect(url);),当客户端接收到响应后,会立刻、马上、自动根据服务器给的新地址 发起第二个请求,服务器接收请求并作出响应,重定向完成。

@WebServlet("/s04")
public class Servlet04 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("Servlet04...");
    /*重定向

    * 服务端指导,客户端行为
    * 存在两次请求
    * 地址栏会发生改变
    * request对象并不共享
    *
    * */
    resp.sendRedirect("s05");
  }

#注意区别请求转发和重定向

#Cookie对象

Cookie是浏览器提供的一种技术,通过服务器的程序能将一些只须保存在客户端,或者在客户端进行 处理的数据,放在本地的计算机上,不需要通过网络传输,因而提高网页处理的效率,并且能够减少服 务器的负载,但是由于 Cookie 是服务器端保存在客户端的信息, 所以其安全性也是很差的。例如常见 的记住密码则可以通过 Cookie 来实现。

有一个专门操作Cookie的类 javax.servlet.http.Cookie。随着服务器端的响应发送给客户端,保存 在浏览器。当下次再访问服务器时把Cookie再带回服务器。

Cookie 的格式:键值对用“=”链接,多个键值对间通过“;”隔开。

##Cookie对象的创建和发送

通过 new Cookie("key","value");来创建一个 Cookie 对象,要想将 Cookie 随响应发送到客户端,需 要先添加到 response 对象中,response.addCookie(cookie);此时该 cookie 对象则随着响应发送至了 客户端。在浏览器上可以看见。

//创建Cookie
    Cookie cookie=new Cookie("name","admin");
    //发送Cookie
    resp.addCookie(cookie);

##Cookie的获取

在服务器端只提供了一个 getCookies()的方法用来获取客户端回传的所有 cookie 组成的一个数组,如 果需要获取单个 cookie 则需要通过遍历,getName()获取 Cookie 的名称,getValue()获取 Cookie 的 值。

//Cookie的获取
    //返回的是Cookie数组
    Cookie[] Cookies = req.getCookies();
    //遍历Cookie数组
    if (Cookies != null && Cookies.length > 0) {
      for (Cookie cookie : Cookies) {
        System.out.println("name=" + cookie.getName());
        System.out.println("value=" + cookie.getValue());
      }

##Cookie设置到期时间

除了 Cookie 的名称和内容外,我们还需要关心一个信息,到期时间,到期时间用来指定该 cookie 何 时失效。默认为当前浏览器关闭即失效。我们可以手动设定 cookie 的有效时间(通过到期时间计算), 通过 setMaxAge(int time);方法设定 cookie 的最大有效时间,以秒为单位。

到期时间的取值

负整数

若为负数,表示不存储该 cookie。 cookie 的 maxAge 属性的默认值就是-1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那 么 cookie 就会消失。

正整数

若大于 0 的整数,表示存储的秒数。 表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算 关闭浏览器,就算重启客户端电脑,cookie 也会存活相应的时间。

若为 0,表示删除该 cookie。 cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是说,如果原来浏览器已经保存 了这个 Cookie,那么可以通过 Cookie 的 setMaxAge(0)来删除这个 Cookie。 无论是在浏览器内 存中,还是在客户端硬盘上都会删除这个 Cookie。

/*
    到期时间:
    负整数(默认值是-1),表示只在浏览器存活,关闭浏览器就失效
    0:表示删除该cookie
    正整数:表示存活的秒数,会将数据存储到磁盘中
    */
    Cookie cookie1=new Cookie("name1","jack");
    cookie1.setMaxAge(-1);
    resp.addCookie(cookie1);

    Cookie cookie2=new Cookie("name2","micgo");
    cookie2.setMaxAge(0);
    resp.addCookie(cookie2);


    Cookie cookie3=new Cookie("name3","Xboss");
    cookie3.setMaxAge(60);
    resp.addCookie(cookie3);

##Cookie的注意点

1. Cookie保存在当前浏览器中。 在一般的站点中常常有记住用户名这样一个操作,该操作只是将信息保存在本机上,换电脑以后这 些信息就无效了。而且 cookie 还不能跨浏览器。

2. Cookie存中文问题 Cookie 中不能出现中文,如果有中文则通过 URLEncoder.encode()来进行编码,获取时通过 URLDecoder.decode()来进行解码。

String name = "姓名";
String value = "张三";
// 通过 URLEncoder.encode()来进行编码
name = URLEncoder.encode(name);
value = URLEncoder.encode(value);
// 创建Cookie对象
Cookie cookie = new Cookie(name,value);
// 发送Cookie对象
response.addCookie(cookie);

3. 同名Cookie问题 如果服务器端发送重复的Cookie那么会覆盖原有的Cookie。

4. 浏览器存放Cookie的数量 不同的浏览器对Cookie也有限定,Cookie的存储有是上限的。Cookie是存储在客户端(浏览器) 的,而且一般是由服务器端创建和设定。后期结合Session来实现回话跟踪。

情景一:当前服务器下任何项目的任意资源都可获取Cookie对象

情景二:当前项目下的资源可获取Cookie对象 (默认不设置Cookie的path)

情景三:指定项目下的资源可获取Cookie对象

情景四:指定目录下的资源可获取Cookie对象

 Cookie cookie01=new Cookie("name01","admin");
    cookie01.setPath("/");
    resp.addCookie(cookie01);

    Cookie cookie02=new Cookie("name02","micgo");
    cookie02.setPath("/Sc01/c04");
    resp.addCookie(cookie02);

    Cookie cookie03=new Cookie("name03","NIU");
    cookie03.setPath("/Sc01/c03");
    resp.addCookie(cookie03);

    Cookie cookie04=new Cookie("name04","cow");
    cookie04.setPath("/Sc01");
    resp.addCookie(cookie04);

总结:当访问的路径包含了cookie的路径时,则该请求将带上该cookie;如果访问路径不包含 cookie路径,则该请求不会携带该cookie

#HttpSession对象

HttpSession对象是 javax.servlet.http.HttpSession 的实例,该接口并不像 HttpServletRequest 或 HttpServletResponse 还存在一个父接口,该接口只是一个纯粹的接口。这因为 session 本身就属于 HTTP 协议的范畴。

对于服务器而言,每一个连接到它的客户端都是一个 session,servlet 容器使用此接口创建 HTTP 客 户端和 HTTP 服务器之间的会话。会话将保留指定的时间段,跨多个连接或来自用户的页面请求。一个 会话通常对应于一个用户,该用户可能多次访问一个站点。可以通过此接口查看和操作有关某个会话的 信息,比如会话标识符、创建时间和最后一次访问时间。在整个 session 中,最重要的就是属性的操作。

session 无论客户端还是服务器端都可以感知到,若重新打开一个新的浏览器,则无法取得之前设置 的 session,因为每一个 session 只保存在当前的浏览器当中,并在相关的页面取得

Session 的作用就是为了标识一次会话,或者说确认一个用户;并且在一次会话(一个用户的多次请 求)期间共享数据。我们可以通过 request.getSession()方法,来获取当前会话的 session 对象。

##标识符 JSESSIONID Session

既然是为了标识一次会话,那么此次会话就应该有一个唯一的标志,这个标志就是 sessionId。

每当一次请求到达服务器,如果开启了会话(访问了 session),服务器第一步会查看是否从客户端 回传一个名为 JSESSIONID 的 cookie,如果没有则认为这是一次新的会话,会创建 一个新的 session 对 象,并用唯一的 sessionId 为此次会话做一个标志。如果有 JESSIONID 这 个cookie回传,服务器则会根 据 JSESSIONID 这个值去查看是否含有id为JSESSION值的session 对象,如果没有则认为是一个新的会 话,重新创建一个新的 session 对象,并标志此次会话; 如果找到了相应的 session 对象,则认为是之 前标志过的一次会话,返回该 session 对象,数据达到共享。

这里提到一个叫做 JSESSIONID 的 cookie,这是一个比较特殊的 cookie,当用户请求服务器时,如果 访问了 session,则服务器会创建一个名为 JSESSIONID,值为获取到的 session(无论是获取到的还是 新创建的)的 sessionId 的 cookie 对象,并添加到 response 对象中,响应给客户端,有效时间为关闭 浏览器。 所以 Session 的底层依赖 Cookie 来实现。

##ServletContext对象

每一个 web 应用都有且仅有一个ServletContext 对象,又称 Application 对象,从名称中可知,该对象是与应用程序相关的。在 WEB 容器启动的时候,会为每一个 WEB 应用程序创建一个对应的 ServletContext 对象。 该对象有两大作用,第一、作为域对象用来共享数据,此时数据在整个应用程序中共享; 第二、该对 象中保存了当前应用程序相关信息。例如可以通过 getServerInfo() 方法获取当前服务器信息 , getRealPath(String path) 获取资源的真实路径等。、

###ServletContext对象的获取

获取 ServletContext 对象的途径有很多。

比如: 1. 通过 request 对象获取

ServletContext servletContext = request.getServletContext();

2. 通过 session 对象获取

ServletContext servletContext = request.getSession().getServletContext();

3. 通过 servletConfig 对象获取,在 Servlet 标准中提供了 ServletConfig 方法

ServletConfig servletConfig = getServletConfig();
ServletContext servletContext = servletConfig.getServletContext();

4. 直接获取,Servlet 类中提供了直接获取 ServletContext 对象的方法

ServletContext servletContext = getServletContext();

常用方法

// 获取项目存放的真实路径

String realPath = request.getServletContext().getRealPath("/");

// 获取当前服务器的版本信息

String serverInfo = request.getServletContext().getServerInfo();

##Servlet的三大域对象

1. request域对象 在一次请求中有效。请求转发有效,重定向失效。

2. session域对象 在一次会话中有效。请求转发和重定向都有效,session销毁后失效。

3. servletContext域对象 在整个应用程序中有效。服务器关闭后失效。

#文件上传和下载

##文件上传

文件上传涉及到前台页面的编写和后台服务器端代码的编写,前台发送文件,后台接收并保存文件, 这才是一个完整的文件上传。

前台页面

在做文件上传的时候,会有一个上传文件的界面,首先我们需要一个表单,并且表单的请求方式为 POST;其次我们的 form 表单的 enctype 必须设为"multipart/form-data",即 enctype="multipart/form-data",意思是设置表单的类型为文件上传表单。默认情况下这个表单类 型是 "application/x-www-form-urlencoded", 不能用于文件上传。只有使用了multipart/form-data 才 能完整地传递文件数据。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文件上传</title>
</head>
<body>
<!--
文件上传表单
1. 表单提交类型 method="post"
2. 表单类型 enctype="multipart/form-data"
3. 表单元素类型 文件域设置name属性值
普通的表单项 type="text"
文件项 type="file"
-->
<form method="post" action="upload" enctype="multipart/form-data">
  姓名:<input type="text" name="uname" > <br>
  文件:<input type="file" name="myfile" > <br>
  <button type="submit">提交</button>
</form>
</body>
</html>

后台实现

使用注解 @MultipartConfig 将一个 Servlet 标识为支持文件上传。 Servlet 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。

@WebServlet("/upload")
@MultipartConfig // 如果是文件上传表单,一定要加这个注解
public class UpLoad01 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse
    response) throws ServletException, IOException {
// 设置请求的编码格式
    request.setCharacterEncoding("UTF-8");
// 获取普通表单项 (文本框)
    String uname = request.getParameter("uname"); // "uname"代表的是文本框的name属性值
// 通过 getPart(name) 方法获取Part对象 (name代表的是页面中file文件域的name属性值)
    Part part = request.getPart("myfile");
// 通过Part对象,获取上传的文件名
    String fileName = part.getSubmittedFileName();
    System.out.println(fileName);
// 获取上传文件需要存放的路径 (得到项目存放的真实路径)
    String realPath = request.getServletContext().getRealPath("/");
    System.out.println(realPath);
// 将文件上传到指定位置
    part.write(realPath + fileName);
  }
}

##文件下载

###超链接下载

<!-- 当超链接遇到浏览器不识别的资源时,会自动下载 -->
<a href="downLoad/hello.txt">文本文件</a>
<a href="downLoad/luffy.jpg">图片文件</a>
<a href="downLoad/1.rar">压缩文件</a>
<hr>
<!-- 当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行下载 -->
<a href="downLoad/hello.txt" download>文本文件</a>
<a href="downLoad/luffy.jpg" download="路飞.jpg">图片文件</a>

###后台下载

前端

<form action="downloadServlet" >
  文件名:<input type="text" name="filename" placeholder="请输入要下载的文件">
  <button>下载</button>

</form>

后端代码

@WebServlet("/downloadServlet")
public class download extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求的编码
    req.setCharacterEncoding("UTF-8");
// 获取文件下载路径
    String path = getServletContext().getRealPath("/downLoad/");
// 获取要下载的文件名
    String name = req.getParameter("filename");
//参数的非空判断 trim():去除字符串的前后空格
    if(name==null||"".equals(name.trim())){
      resp.getWriter().write("请输入文件名");
      resp.getWriter().close();
      return;
    }

// 通过路径得到file对象
    File file = new File(path + name);
// 判断file对象是否存在,且是否是一个标准文件
    if (file.exists() && file.isFile()) {
// 设置响应类型 (浏览器无法使用某种方式或激活某个程序来处理的类型)
      resp.setContentType("application/x-msdownload");
// 设置头信息
      resp.setHeader("Content-Disposition", "attachment;filename=" +
        name);
// 得到输入流
      InputStream is = Files.newInputStream(file.toPath());
// 得到输出流
      ServletOutputStream os = resp.getOutputStream();
// 定义byte数组
      byte[] car = new byte[1024];
// 定义长度
      int len = 0;
// 循环 输出
      while ((len = is.read(car)) != -1) {
        os.write(car, 0, len);
      }
// 关闭流 释放资源
      os.close();
      is.close();
    } else {
      System.out.println("文件不存在,下载失败!");
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xboss、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值