7、servlet(上)

一、Servlet技术

1.1 Servlet概述

  • 1、Servlet 是 JavaEE 规范之一。规范就是接口
  • 2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
  • 3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收通过 HTTP(超文本传输协议)客户端发送过来的请求,并响应数据给客户端。

1.2 手动实现Servlet 程序

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。

1、编写一个类去实现 Servlet 接口
2、实现 service 方法,处理请求,并响应数据
3、到 web.xml 中去配置 servlet 程序的访问地址

Servlet程序的示例代码:

public class HelloServlet implements Servlet {
    
    /**
     * service 方法是专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("你访问了servlet");
    }
	
	//......
}

web.xml中的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--servlet标签给Tomcat配置Servlet程序-->
    <servlet>
        <!--servlet-name标签给Servlet程序起一个别名(一般是类名)-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是Servlet程序的全类名-->
        <servlet-class>com.zb.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--servlet-mapping标签给servlet程序配置访问地址-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个Servlet程序使用-->
        <servlet-name>HelloServlet</servlet-name>
        <!--
            url-pattern标签配置访问地址                                     <br/>
               / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径          <br/>
               /hello 表示地址为:http://ip:port/工程路径/hello              <br/>
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

1.3 url地址到 Servlet 程序的访问

在这里插入图片描述

  1. 当创建一个TestServlet文件的时候,需要在web.xml中配置TestServlet文件。

    public class DataServlet extends HttpServlet {
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    	}
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    	}
    }
    
  2. 为什么需要在web.xml中配置TestServlet。让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用

      <servlet>
      	<!-- 给servlet取名字,一般跟我们写的servlet类名相同 -->
      	<servlet-name>TestServlet</servlet-name>
      	<!-- servlet的全限定类名,也就是servlet的位置 -->
      	<servlet-class>com.jd.TestServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      	<!-- 跟上面的servlet名字相同 -->
      	<servlet-name>TestServlet</servlet-name>
      	<!-- 浏览器通过该url找到servlet。/一定要加,相当于项目名称 -->
      	<url-pattern>/TestServlet</url-pattern>
      </servlet-mapping>
    

映射步骤:首先浏览器通过127.0.0.1/test/TestServlet来找到web.xml中的url-pattern。2.匹配到了url-pattern后,就会找到第二步servlet的名字TestServlet,知道了名字,就可以通过servlet-name找到第三步,也就能够知道servlet的位置了。然后到其中找到对应的处理方式进行处理。

1.4 GET和POST请求的分发处理(了解)

public class HelloServlet implements Servlet {
    //service 方法是专门用来处理请求和响应的
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //类型转换(因为它有getMethod()方法)
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        //获取请求的方法
        String method = httpServletRequest.getMethod();
        System.out.println(method);
        if("GET".equals(method)){
            doGet();
        }else if("POST".equals(method)){
            System.out.println("POST方法");
            doPost();
        }
    }

    /**
     * 执行get请求操作
     */
    public void doGet(){
        System.out.println("GET请求");
    }

    /**
     * 执行post请求操作
     */
    public void doPost(){
        System.out.println("POST请求");
    }
}

1.5 通过继承HttpServlet实现Servlet程序

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。

1、	编写一个类去继承 HttpServlet 类
2、	根据业务需要重写 doGet 或 doPost 方法
3、	到 web.xml 中的配置 Servlet 程序的访问地址 Servlet 类的代码:

Servlet 类的代码:

public class HelloServlet2 extends HttpServlet {

    //doGet()在get请求的时候调用
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2的doGet方法");
    }

    //doPost在post请求的时候调用
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2的doPost方法");
    }
}

web.xml 中的配置:

<servlet>
    <servlet-name>HelloServlet2</servlet-name>
    <servlet-class>com.zb.servlet.HelloServlet2</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>HelloServlet2</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>

1.6 Servlet类的继承体系

在这里插入图片描述

二、Servlet生命周期(重点)

好的博客:Servlet的生命周期:https://blog.csdn.net/zhouym_/article/details/90741337

servlet的生命周期就是从servlet出现到销毁的全过程。主要分为以下几个阶段:
加载类—>实例化(为对象分配空间)—>初始化(为对象的属性赋值)—>请求处理(服务阶段)—>销毁

服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(),该servlet对象去处理所有客户端请求,service(ServletRequest req,ServletResponse res)方法中执行,最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。其中加载阶段无法观察,但是初始化、服务、销毁阶段是可以观察到的

public class HelloServlet3 extends HttpServlet {
    public HelloServlet3() {
        System.out.println("1 构造器方法");
    }
    @Override
    public void init() throws ServletException {
        System.out.println("2 init初始化方法");
    }
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("3 处理servlet请求时调用servlet方法");
    }
    @Override
    public void destroy() {
        System.out.println("4 销毁阶段调用destroy方法");
    }
}

在这里插入图片描述

2.1 init()方法

init( ) 当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用。我们可以利用init()方法来执行相应的初始化工作,同时也可用于获取web.xml中的数据

init()方法初始化有两个方式

1、启动tomcat后,当第一次访问servlet类的时候,会调用init方法
2、启动tomcat直接调用init方法,这种方式需要配置web.xml文件。

在servlet的配置当中,<load-on-startup>5</load-on-startup>的含义是:

A、标记容器是否在启动的时候就加载这个servlet。
B、当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
C、当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。
D、正数的值越小,启动该servlet的优先级越高。

配置方式:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	
	<!-- 配置第一个servlet -->
	<servlet>
		<!-- 给servlet取一个名字,名字按照变量命名规范可以自定义名字。 -->
		<servlet-name>OneServlet</servlet-name>
		<!-- 说明这个类在项目中的路径 ,包含这个类所在的包名和这个类的类名如下面的配置:
		test05是类所在的包名,OneServlet是类名-->
		<servlet-class>test05.OneServlet</servlet-class>
		
		<!-- 配置初始化方式为tomcat容器启动后自动初始化该servlet类 -->
		<load-on-startup>1</load-on-startup>
		
	</servlet>
	
	<!-- 配置如何访问这个servlet -->
	<servlet-mapping>
		<!-- 引用上面servlet类定义的名字 -->
		<servlet-name>OneServlet</servlet-name>
		<!-- 配置url访问这个servlet类的名字,名字按照变量命名规范可以自定义名字。
		如下配置:/one,这个名字会在访问OneServlet类时候使用 
		例如:127.0.0.1:8080/项目名称/one-->
		<url-pattern>/one</url-pattern>
	</servlet-mapping>
	
</web-app>

init(ServletConfig config)方法 和 init()方法

  • Servlet接口部分源码

    在这里插入图片描述

init(ServletConfig)中参数ServletConfig,代表的是配置信息。即在web.xml中配置的信息。这是供tomcat调用的

  • GenericServlet抽象类部分源码(GenericServlet抽象类实现了Servlet接口)

    在这里插入图片描述

即:当容器(tomcat)帮忙调用init(ServletConfig config)并且给传过来一个参数config,这个方法把参数对象的引用指向类的成员变量this.config,并且调用类的 this.init()方法。如果我们在写Servlet类时只要重写init(ServletConfig config)就可以了,但是init()不就成了多余的了吗?实际上init()方法是为了防止程序员在写Servlet类重写 init(ServletConfig config)时忘记写super.init(ServletConfig config),这样就容易造成出现空指针异常。而这就要求我们最好不要重写init(ServletConfig config)。

2.2 service()方法

service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。

//任何请求优先到达service方法,通过该方法确定执行doGet还是doPost
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	// TODO Auto-generated method stub
	super.service(req, resp);//将这行代码注释将不执行doget或dopost方法
}

//a连接 form指定method标签属性get,异步不写或者指定为get
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}

//form指定method标签属性get,异步指定为post
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}

HttpServlet源码分析

  • service()方法源码解析:

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取http request的method参数,其实就是html的form标签  
            //中method属性对应的字符串 
            String method = req.getMethod();
            long errMsg;
            //判断请求方式
            if(method.equals("GET")) {
                //获取最后被修改时间 
                errMsg = this.getLastModified(req);
                if(errMsg == -1L) {
                /**如果servlet不支持http request header的if-modified-since属性 
                 * 则继续处理 
                 **/  
                    this.doGet(req, resp);
                } else {
                   //如果支持这个属性 
                    long ifModifiedSince;
                    try {
                        ifModifiedSince = req.getDateHeader("If-Modified-Since");
                    } catch (IllegalArgumentException var9) {
                        ifModifiedSince = -1L;
                    }
                   /** 
                    * 如果客户端的文件最后修改时间和服务器端的文件最后修改时间一致则返回304不需要修改状态 
                    * 这样服务器就不返回html,浏览器读取本地缓存文件,否则重新获取服务器端的对应html文件 
                    **/  
                    if(ifModifiedSince < errMsg / 1000L * 1000L) {
                        this.maybeSetLastModified(resp, errMsg);
                        this.doGet(req, resp);
                    } else {
                        resp.setStatus(304);
                    }
                }
            } else if(method.equals("HEAD")) {
                errMsg = this.getLastModified(req);
                this.maybeSetLastModified(resp, errMsg);
                this.doHead(req, resp);
            } else if(method.equals("POST")) {
                this.doPost(req, resp);
            } else if(method.equals("PUT")) {
                this.doPut(req, resp);
            } else if(method.equals("DELETE")) {
                this.doDelete(req, resp);
            } else if(method.equals("OPTIONS")) {
                this.doOptions(req, resp);
            } else if(method.equals("TRACE")) {
                this.doTrace(req, resp);
            } else {
                //如果请求不是以上的所有请求方式,该方法就会响应501错误,也就是不支持这种请求
                String errMsg1 = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[]{method};
                errMsg1 = MessageFormat.format(errMsg1, errArgs);
                resp.sendError(501, errMsg1);
            }
        }
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            HttpServletRequest request;
            HttpServletResponse response;
            try {
                request = (HttpServletRequest)req;
                response = (HttpServletResponse)res;
            } catch (ClassCastException var6) {
                throw new ServletException("non-HTTP request or response");
            }
            this.service(request, response);
    }
    
    
  • doGet()和doPost()方法源码解析:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取协议 
            String protocol = req.getProtocol();
            //获取http.method_get_not_supported的国际化字符串
            String msg = lStrings.getString("http.method_get_not_supported");
            if(protocol.endsWith("1.1")) {
            //如果是HTTP/1.1,返回405禁止访问方法错误
                resp.sendError(405, msg);
            } else {
            //如果不是HTTP/1.1,返回400错误的请求错误  
                resp.sendError(400, msg);
            }
     }
     
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_post_not_supported");
            if(protocol.endsWith("1.1")) {
                resp.sendError(405, msg);
            } else {
                resp.sendError(400, msg);
            } 
    }
    

两个方法如果不被重写,那执行时默认会调用HttpServlet的代码,首先获取协议,然后获取国际化字符串,最后判断协议,如果协议为HTTP/1.1,返回405禁止访问方法错误,//如果不是HTTP/1.1,返回400错误的请求错误。

2.3 destory()方法

destory,当要销毁Servlet时(即web工程停止时),Servlet容器就会调用这个方法。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。

//Servlet对象销毁之前调用,用于释放资源。由于servlet方法式单例,仅仅创建一次,所以该方法只执行一次
//Tomcat服务器关闭时调用,项目重新发布前调用
@Override
public void destroy() {
	super.destroy();
	System.out.println("destroy"+this);
}

三、ServletConfig类

Servlet程序和ServletConfig 对象都是由Tomcat负责创建,我们负责使用。
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个 Servlet 程序创建时,就创建一个对应的ServletConfig对象

ServletConfig类的三大作用

1、可以获取 Servlet 程序的别名 servlet-name 的值
2、获取初始化参数 init-param
3、获取 ServletContext 对象

Servlet中的代码:

public class HelloServlet3 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        //获取ServletConfig对象
        ServletConfig config = getServletConfig();//调用父类的方法
//        1、可以获取Servlet程序的别名servlet-name的值
        System.out.println("HelloServlet程序的别名是:" + config.getServletName());
//        2、获取初始化参数init-param
        System.out.println("初始化参数username的值是:" + config.getInitParameter("username"));
        System.out.println("初始化参数url的值是:" + config.getInitParameter("url"));
//        3、获取ServletContext对象
        System.out.println(config.getServletContext());
    }
    //也可以在通过重写init(ServletConfig config)方法获取配置信息,但要加上super.init(config);
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);//如果重写了该方法则必须调用父类的init(ServletConfig config)
//        1、可以获取Servlet程序的别名servlet-name的值
        System.out.println("HelloServlet程序的别名是:" + config.getServletName());
//        2、获取初始化参数init-param
        System.out.println("初始化参数username的值是:" + config.getInitParameter("username"));
        System.out.println("初始化参数url的值是:" + config.getInitParameter("url"));
//        3、获取ServletContext对象
        System.out.println(config.getServletContext());
    }
}

web.xml中的配置:

<servlet>
    <servlet-name>HelloServlet3</servlet-name>
    <servlet-class>com.zb.servlet.HelloServlet3</servlet-class>
    <!--init-param是初始化参数-->
    <init-param>
        <!--参数名-->
        <param-name>username</param-name>
        <!--参数值-->
        <param-value>root</param-value>
    </init-param>
    <init-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/test</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>HelloServlet3</servlet-name>
    <url-pattern>/hello3</url-pattern>
</servlet-mapping>

四、ServletContext类

什么是ServletContext?

1、ServletContext 是一个接口,它表示 Servlet 上下文对象
2、一个 web 工程,只有一个 ServletContext 对象实例。
3、ServletContext 对象是一个域对象。
4、ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

什么是域对象?

域对象,是可以像 Map 一样存取数据的对象,叫域对象。这里的域指的是存取数据的操作范围,整个 web 工程。

存数据 		取数据 				删除 				数据
Map 			put() 				get() 				remove()
域对象 		setAttribute() 		getAttribute() 		removeAttribute();

ServletContext类的四个作用

1、获取 web.xml 中配置的上下文参数 context-param
2、获取当前的工程路径,格式: /工程路径
3、获取工程部署后在服务器硬盘上的绝对路径
4、像Map一样存取数据

  • ServletContext 功能1-3

    ServletContext 演示代码:

    public class ContextServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取ServletContext对象
            ServletContext context = getServletConfig().getServletContext();
    //        1、获取web.xml中配置的上下文参数context-param
            String username = context.getInitParameter("username");
            System.out.println("context-param参数username的值是:"+username);
            System.out.println("context-param参数password的值是:"+context.getInitParameter("password"));
    //        2、获取当前的工程路径,格式: /工程路径
            System.out.println("当前工程路径:"+context.getContextPath());//"/06_servlet"
    //        3、获取工程部署后在服务器硬盘上的绝对路径
    //        '/' 斜杠被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录
            System.out.println("工程部署的路径是:"+context.getRealPath("/"));//E:\idea_workspace\shangguigu_JavaWeb\out\artifacts\06_servlet_war_exploded\
            System.out.println("工程下img目录1.jpg的绝对路径是:"+context.getRealPath("/img/1.jpg"));
        }
    }
    

    web.xml中的配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <!--context-param是上下文参数(它属于整个web工程)-->
        <context-param>
            <param-name>username</param-name>
            <param-value>context</param-value>
        </context-param>
        <context-param>
            <param-name>password</param-name>
            <param-value>root</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>ContextServlet</servlet-name>
            <servlet-class>com.zb.servlet.ContextServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>ContextServlet</servlet-name>
            <url-pattern>/context</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • ServletContext像Map一样存取数据:

    ContextServlet1代码:

    public class ContextServlet1 extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取ServletContext对象
            ServletContext context = getServletContext();
            System.out.println("设置之前数据key1的值是:" + context.getAttribute("key1"));//null
            context.setAttribute("key1","value1");//在整个web工程中都可以获取该数据
            System.out.println("数据key1的值是:" + context.getAttribute("key1"));//value1
        }
    }
    

五、HTTP协议

  • 什么是协议?
    协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。

  • 所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。
    HTTP 协议中的数据又叫报文。

5.1 请求的HTTP协议格式

客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为GET请求,和POST请求两种
  • GET请求

    1. 请求行
      (1) 请求的方式: GET
      (2) 请求的资源路径[+?+请求参数]
      (3) 请求的协议的版本号: HTTP/1.1
    2. 请求头
      key : value 组成 不同的键值对,表示不同的含义。

    在这里插入图片描述

  • POST请求

    1. 请求行
      (1) 请求的方式: POST
      (2) 请求的资源路径[+?+请求参数]
      (3) 请求的协议的版本号: HTTP/1.1
    2. 请求头
      (1) key : value 不同的请求头,有不同的含义
      (2)空行
    3. 请求体 ===>>> 就是发送给服务器的数据

    在这里插入图片描述

  • 常用请求头的说明

    Accept: 表示客户端可以接收的数据类型
    Accpet-Languege: 表示客户端可以接收的语言类型
    User-Agent: 表示客户端浏览器的信息
    Host: 表示请求时的服务器 ip 和端口号

  • 哪些是GET请求,哪些是POST请求

    1. GET 请求有哪些:
      1. form 标签 method=get
      2. a 标签
      3. link 标签引入 css
      4. Script 标签引入 js 文件
      5. img 标签引入图片
      6. iframe 引入 html 页面
      7. 在浏览器地址栏中输入地址后敲回车
    2. POST 请求有哪些:
      1. form 标签 method=post

5.2 响应的HTTP协议格式

  1. 响应行
    (1) 响应的协议和版本号
    (2) 响应状态码
    (3) 响应状态描述符
  2. 响应头
    (1) key : value 不同的响应头,有其不同含义
    (2)空行
  3. 响应体 ---->>> 就是回传给客户端的数据

在这里插入图片描述

常用的响应码说明

200 	表示请求成功
302 	表示请求重定向
404 	表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
500 	表示服务器已经收到请求,但是服务器内部错误(代码错误)

MIME 类型说明

  • MIME 是 HTTP 协议中数据类型。
  • MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。
  • 常见的 MIME 类型:
文件MIME 类型
超文本标记语言文本.html , .htm text/html
普通文本.txt text/plain
RTF 文本.rtf application/rtf
GIF 图形.gif image/gif
JPEG 图形.jpeg,.jpg image/jpeg
au 声音文件.au audio/basic
MIDI 音乐文件mid,.midiaudio/midi,audio/x-midi
RealAudio 音乐文件.ra,.ram audio/x-pn-realaudio
MPEG 文件.mpg,.mpeg video/mpeg
AVI 文件.avi video/x-msvideo
GZIP 文件.gz application/x-gzip
TAR 文件.tar application/x-tar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值