什么是Servlet?

Servlet是运行在Web服务器中的Java程序。Servlet通常通过HTTP(超文本传输协议)接收和响应来自Web客户端的请求。Java Web应用程序中所有的请求-响应都是由Servlet完成。

Servlet的工作流程

浏览器与服务器之间的请求和响应都是遵循HTTP协议的(上一篇有介绍HTTP)。Tomcat会接受并解析HTTP请求文本,然后封装成HttpServletRequest对象,所有的HTTP头数据都可以通过request相应的方法查询到。Tomcat同时会把响应的数据封装为HttpServletResponse类型的response对象,通过设置response属性可以控制输出内容,然后Tomcat会把request、respnse作为参数,调用Servlet的相关方法,例如doGet、doPost等。

Java Web应用程序请求-响应的典型过程如图:

    

编写Servlet

在编写Servlet时,需要继承HttpServlet类,还要考虑到如何让Web容器找到相应的Servlet。

在Servlet3.0之前编写Servlet时需要部署配置文件web.xml(在上一篇有详细介绍)。

Servlet类的编写:

package servlet;

import javax.Servlet.ServletException;
import javax.Servlet.http.HttpServlet;
import javax.Servlet.http.HttpServletRequest;
import javax.Servlet.http.HttpServletResponse;
import java.io.IOException; public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }
}

配置文件的编写:

  <servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>

有没有觉得这样非常麻烦。。。所以在Servlet3.0以后可以使用@WebServlet()注解的方式来告诉Tomcat哪些Servlet会提供服务以及额外信息,而不需要配置文件。

package 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(
name = "HelloServlet", //Servlet内部名,可以随便设置
urlPatterns = "/login", //用户请求用的URL名称
loadOnStartup = 1 //Servlet初始化顺序,默认为-1,设置为大于0点值,数字越小越先执行
)
public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }
}

Servlet的原理

Servlet API

    

  1. Servlet

    此接口定义了初始化Servlet的方法、为请求提供服务的方法和从服务器移除Servlet的方法,这些方法称为生命周期方法。此外该接口还提供了getServletConfig方法和getServletInfo方法,Servlet可使用前一种方法获得任何启动信息,而后一种方法允许Servlet返回有关其自身的基本信息,比如作者、版本和版权。

    • init(ServletConfig config)

      生命周期方法,由Web容器调用,初始化该Servlet。

    • service(ServletRequest req, ServletResponse res)

      生命周期方法,由Web容器调用,以允许Servlet响应某个请求。此方法仅在Servlet的 init() 方法成功完成之后调用。

    • destroy()

      生命周期方法,由Web容器调用,销毁该Servlet。

    • getServletConfig()

      返回ServletConfig对象,该对象包含此Servlet的初始化和启动参数。返回的ServletConfig对象是传递给 init()方法的对象。此接口的实现负责存储ServletConfig对象,以便此方法可以返回该对象。实现此接口的GenericServlet类已经这样做了。

    • getServletInfo()

      返回有关Servlet的信息,比如作者、版本和版权。此方法返回的是纯文本,不应该是任何种类的标记。

  2. GenericServlet

    定义一般的、与协议无关的Servlet。GenericServlet实现Servlet和ServletConfig接口。GenericServlet的主要目的就是将初始化Servlet的Init方法传入的ServletConfig对象封装起来,GenericServlet也包括了Servlet与ServletConfig所定义方法的简单实现,实现内容主要是通过ServletConfig来取得一些相关信息。GenericServlet在实现Servlet的init方法时,还调用了无参的init()方法,如果有一些初始时需要运行的操作,可以在你编写的Servlet中重写这个无参init方法(),而不是重写有参数的init()方法,原因在下面的Servlet生命周期里有详细的介绍。

       public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
    }
  3. HttpServlet

    继承于GenericServlet,提供将要被子类化以创建适用于 Web 站点的HTTP Servlet的抽象类。HttpServlet的子类至少必须重写一个方法,该方法通常是以下这些方法之一:

    • doGet,如果Servlet支持HTTP GET请求
    • doPost,用于HTTP POST请求
    • doPut,用于HTTP PUT请求
    • doDelete,用于HTTP DELETE请求
    • init 和 destroy,用于管理Servlet的生命周期内保存的资源
    • getServletInfo,Servlet使用它提供有关其自身的信息
  4. MyServlet

    这是你自己编写的Servlet,继承HttpServlet后重写其中的doGet方法或doPost方法即可接收和响应客户端的Http请求。

Servlet生命周期

生命周期:Servlet从创建到消亡的一段时间

Web容器为Servlet创建一个ServletConfig,调用init()时,Servlet才是一个真正的Servlet,之前还只是一个普通的对象(调用构造函数后)。在调用构造函数和init方法之间,Servlet处在薛定谔状态(介于两者之间的一种状态),如果在Servlet状态,你可能有一些Servlet初始化代码,比如得到Web应用配置信息,或请求信息,那么你就会失败。但是只要记住一点,Servlet的构造函数中不放任何东西即可。

   

  1. init()

    默认情况下,Servlet在第一次被访问的时候,才会执行init方法。 有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至是做一些比较耗时的工作。那么这个时候,初次访问,可能会在init方法中逗留太久的时间。 那么有没有方法可以让这个初始化的时机提前一点?

    • 在web.xml中配置, 使用load-on-startup元素来指定Servlet的启动时机, 初始值为-1,它的值必须是一个整数,我们设置的时候一般为0和大于0的整数,表示在容器启动的时候就加载和初始化Servlet,值越小,Servlet的优先级就越高,启动的时机就越早,当值相同时,由Web容器自己选择优先加载。

      <servlet>
      <servlet-name>HelloServlet</servlet-name>
      <servlet-class>servlet.HelloServlet</servlet-class>
      <load-on-startup>2</load-on-startup>
      </servlet>
    • 在注解中添加loadOnStartup属性,与上面一样。

      @WebServlet(
      name = "HelloServlet", //Servlet内部名,可以随便设置
      urlPatterns = "/login", //用户请求用的URL名称
      loadOnStartup = 1 //Servlet初始化顺序,默认为-1
      )
  2. service

    当一个请求到来的时候,容器会开始一个新线程,或者从线程池中分配一个线程,并调用service()方法,再由service()考虑调用哪一个方法响应请求。

  3. destroy

    当Servlet从服务器中移除或者服务器关闭的时候Servlet对象会被销毁,里面的destroy方法就会执行,然后垃圾回收就会将其回收掉。

四大对象

ServletConfig

Web容器使用的Servlet配置对象,该对象在初始化期间将信息传递给Servlet。通过ServletConfig可以得到一些初始化信息。每个Servlet都有一个属于自己的ServletConfig。

获取方式:getServletConfig()。

ServletConfig对象只有以下四个方法:

  • getInitParameter(String name):根据name返回指定初始化参数的值,如果参数不存在,则返回null。
  • getInitParameterNames():以 String对象的Enumeration的形式返回Servlet的初始化参数的名称,如果 Servlet 没有初始化参数,则返回一个空的Enumeration。
  • getServletContext():返回ServletContext对象的引用。
  • getServletName():返回此Servlet实例的名称,默认是类名。

在使用这些方法之前,需要知道怎么为Servlet添加初始化参数。

web.xml中添加参数:

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>kindleheart</param-value>
</init-param>
<init-param>
<param-name>phone</param-name>
<param-value>110</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

@WebServlet注解中添加参数:

@WebServlet(
name = "HelloServlet", //Servlet内部名,可以随便设置
urlPatterns = "/login", //用户请求用的URL名称
loadOnStartup = 1, //Servlet初始化顺序,默认为-1
initParams = { //添加初始化参数
@WebInitParam(name = "name", value = "kindleheart"),
@WebInitParam(name = "phone", value = "110")
}
)

使用上面四个方法:

public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到ServletConfig对象
ServletConfig ServletConfig = this.getServletConfig();
//getInitParameter
System.out.println(ServletConfig.getInitParameter("name"));
System.out.println(ServletConfig.getInitParameter("phone"));
//getInitParameterNames
Enumeration<String> names = ServletConfig.getInitParameterNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
System.out.println(ServletConfig.getInitParameter(name));
}
//getServletContext
ServletContext ServletContext = ServletConfig.getServletContext();
//getServletName
System.out.println(ServletConfig.getServletName());
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}

ServletContext

Servlet上下文,定义一组方法,Servlet使用这些方法与Web容器进行通信,例如获取文件的 MIME 类型、分发请求或写入日志文件。

每个Web工程下只有一个ServletContext,所有Servlet共用一个ServletContext,ServletContext对象包含在 ServletConfig对象中,ServletConfig对象在初始化Servlet时由Web容器提供给Servlet。

获取方式:getServletContext()、getServletConfig().getServletContext,这两种方式本质上是一样的,都是由ServletConfig在GenericServlet类中返回得到。

ServletRequest对象的应用:

  1. 获取全局参数

    上面的init-param是配置在Servlet标签下的,所以只能由这个Servlet来读取,如果想所有的Servlet都能读取,就需要用到上下文参数,context-param配置在web-app标签下,同样的在获取全局配置参数之前我们先在web.xml中添加全局参数。

      <context-param>
    <param-name>name</param-name>
    <param-value>kindleheart</param-value>
    </context-param>
    <context-param>
    <param-name>phone</param-name>
    <param-value>110</param-value>
    </context-param>

    读取方式与ServletConfig读取初始化参数完全一样。

  2. 获取Web应用中的资源

       protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 告诉客户端该文件不是直接解析,而是以附件形式打开(下载)
    response.setHeader("Content-Disposition", "attachment;filename=" + "tutu.jsp"); //获取文件的绝对路径,再得到输入流
    // String path = this.getServletContext().getRealPath("download/" + "tutu.jsp");
    // InputStream in = new FileInputStream(path);
    //直接得到输入流
    InputStream in = getServletContext().getResourceAsStream("download/tutu.jsp"); // 获得输出流,通过response获得的输出流,用于向客户端写内容
    ServletOutputStream out = response.getOutputStream();
    // 文件拷贝代码
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len = in.read(buffer)) != -1) {
    out.write(buffer, 0, len);
    }
    in.close();
    out.close();
    }
  3. 在Servlet上下文存取数据

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //在Servlet上下文添加属性
    getServletContext().setAttribute("name","图图");
    //在Servlet上下文获取这个属性值
    String name = (String) getServletContext().getAttribute("name");
    }

HttpServletRequest

客户端发来的请求被封装成一个HttpServletRequest对象。所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件,客户端IP地址,甚至是客户端操作系统都包含在内。

HttpServletRequest对象的应用:

  1. 获取请求头信息

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取所有请求头信息
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
    String name = headerNames.nextElement();
    String value = request.getHeader(name);
    System.out.println(name + ":" + value);
    }
    }
  2. 获取表单传来的数据

    <form action="login" method="post">
    姓名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="checkbox" name="hobby" value="打球">打球
    <input type="checkbox" name="hobby" value="游泳">游泳
    <input type="checkbox" name="hobby" value="滑雪">滑雪<br>
    <input type="submit" value="提交">
    </form>
     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //设置字符编码为UTF-8
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    //一个name对应一个值
    String username = request.getParameter("username");
    String password = request.getParameter("password"); //一个name对应多个值
    Map<String, String[]> map = request.getParameterMap();
    Set<String> keySet = map.keySet();
    for(String key : keySet) {
    System.out.println("key=" + key + "的值的总数有" + map.get(key).length);
    for(String value : map.get(key)) {
    System.out.println(value);
    }
    }
    }
  3. 请求转发

    在Web应用中,经常需要多个Servlet共同处理请求,那么就需要使用请求转发。请求转发是通过RequestDispatcher对象的forword(req, res)来实现的。这个动作是在Web容器中进行的,浏览器并不知道请求被转发。当forward跳转时,地址栏的访问地址不改变,跳转后的Servlet或Jsp能使用上一个Servlet里的属性,经常用于Servlet处理业务逻辑,然后Jsp来显示处理结果。

       protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //在request域中写入属性
    request.setAttribute("username","kindleheart");
    request.setAttribute("password","123");
    //请求转发,index.jsp可以使用该Servlet里的属性
    request.getRequestDispatcher("index.jsp").forward(request, response);
    }

HttpServletResponse

服务器使用HttpServletResponse来对浏览器进行响应。

HttpServletResponse的应用:

  1. 设置响应头

    在前面的ServletContext上下文获取资源时,浏览器是默认直接显示该资源的,如果你想下载而不是直接显示,就会需要设置响应头,让浏览器知道你要下载而不是显示。

    // 告诉客户端该文件不是直接解析,而是以附件形式打开(下载)
    response.setHeader("Content-Disposition", "attachment;filename=" + "tutu.jsp");
  2. 使用getWriter输出字符

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    response.getWriter().println("输出字符");
    }
  3. 使用getOutputStream

    还是在前面的 ServletContext 获取资源中,需要把资源以输出流的形式进行下载,那就需要用到getOutputStream来以二进制形式写入。

    // 获得输出流,通过response获得的输出流,用于向客户端写内容
    ServletOutputStream out = response.getOutputStream();
  4. 重定向

    HttpServletRequence的sendRedirect要求浏览器重新请求一个URL,称为重定向。重定向是利用服务器返回的状态码决定的,浏览器在访问服务器的时候,服务器会返回一个状态码。可以使用HttpServletResponse的setStatus方法设置状态码。如果服务器返回301,或者302,那么浏览器会到新的网址请求资源,地址栏上的访问地址会改变。重定向和请求转发不一样。因为是重新访问地址,所以重定向后的Servlet或Jsp不能使用之前Servlet的属性。

    状态码 意义
    1xx 信息状态码。表示该请求已经被接受。正在被处理。
    2xx 正确状态码。表示该请求已经被正确接受且处理,没有错误发生。例如,200表示一切正确。
    3xx 重定向状态码。例如301,302表示该资源已经不存在或换了地址,需要重新定向到一个新的资源。
    4xx 请求错误。例如401表示没有访问权限,404表示资源不存在,405表示访问方式错误。
    5xx 服务器错误。例如500表示程序出现异常而中途停止运行。

    使用:

    //重定向到index.jsp
    response.sendRedirect("index.jsp");

    sendRedirect方法其实是在响应中设置了Status和Location标头,所以使用以下代码就可以实现重定向,这也是重定向的原理。

    //设置状态码
    response.setStatus(301);
    //定位跳转的位置
    response.setHeader("Location", "index.jsp");
  5. 自动刷新

    response对象可以使用setHeader设置方法响应头来实现自动刷新,自动刷新不仅可以实现一段时间跳转到其他页面,还可以实现一段时间后自动刷新本页面。

    response.getWriter().println("注册成功!3秒之后会跳转到主页");
    response.setHeader("refresh", "3;index.jsp");

    其中3代表3秒,index.jsp是指定的跳转网址的URL,如果URL设置的路径为Servlet自己的路径,就会每隔3秒刷新自己一次。

重定向与请求转发的区别

本质区别:请求转发只发出了一次请求,而重定向发出了多次请求。

  • 请求转发:地址栏是初次发出请求的地址

    重定向:地址栏不再是初次发出的请求地址,地址栏为最后响应的那个地址

  • 请求转发:在最终的Servlet中,request对象和中转的那个request是同一个对象

    重定向:在最终的Servlet中,request对象和中转的那个request不是同一个对象

  • 请求转发:只能转发给当前WEB应用的资源

    重定向:可以重定向到任何资源

    response.sendRedirect("http://www.baidu.com");是可以的,请求转发就不行。

  • 请求转发:/ 代表的是当前WEB应用的根目录(http://localhost:8080/项目名称/)

    重定向: / 代表的是当前WEB站点的根目录(http://localhost:8080/)

注意:这两条跳转语句不能同时出现在一个页面中,否则会报IllegalStateException - if the response was already committed的错误。

Servlet中文乱码问题

出现乱码问题的原因是Web容器默认是以ISO-8859-1进行字符编码的。而一般使用的过程中都是以UTF-8的格式,那么就会出现乱码问题。

  • HttpServletRequest出现中文乱码

    • POST请求

      //设置request的字符编码格式为utf-8
      request.setCharacterEncoding("utf-8");
    • GET请求

      String value = request.getParameter("value");
      value = new String(value.getBytes("iso-8859-1"), "utf-8");
      System.out.println(value);
  • HttpServletResponse出现中文乱码

    //设置response的字符编码格式为utf-8
    response.setContentType("text/html;charset=utf-8");

如果要接收中文数据,并在响应时通过浏览器正确显示中文,那么这两个方法需要同时进行设置。

Servlet是否为线程安全

线程安全问题指的是多线程在并发执行时会不会出现问题。由于Web容器只会创建一个Servlet实例,所以多个用户发起请求时,会有多个线程处理Servlet代码,因此Servlet是线程不安全的。

考虑以下代码:

@WebServlet(name = "ThreadSafeServlet", urlPatterns = "/ThreadSafeServlet")
public class ThreadSafeServlet extends HttpServlet {
private String name;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
name = request.getParameter("name");
try {
Thread.sleep(10000);//使线程沉睡10秒
} catch (Exception e) {
e.printStackTrace();
}
response.getWriter().println("name:" + name);
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}

10秒内在两个不同的浏览器窗口中的表单输入name并提交,假如在A浏览器中输入111,B浏览器中输入222,最后会发现A和B浏览器显示的name都是222。这是因为在第一个线程睡眠时,第二个线程修改了name的值,所有最后显示都是222,那么就产生了线程不安全问题。

实际上Servlet,Context上下文作用域,HttpSession都是线程不安全的,只有request请求和局部变量是线程安全的。

Java Web(二) Servlet详解的更多相关文章

  1. Java Web(一) Servlet详解!!

    这篇文章到上一篇,距离的有点遥远呀,隔了大概有两个月把,中间在家过了个年,哈哈~ 现在重新开始拾起,最近在看一本个人觉得很棒的书,<Java Web 整合开发王者归来>,现在写的这一系列基 ...

  2. (转)Java Web(一) Servlet详解!!

    https://www.cnblogs.com/whgk/p/6399262.html 这篇文章到上一篇,距离的有点遥远呀,隔了大概有两个月把,中间在家过了个年,哈哈~ 现在重新开始拾起,最近在看一本 ...

  3. Java Web(5)-Servlet详解(下)

    一.HttpServletRequest 类 1. HttpServletRequest 类作用? 每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解 ...

  4. Java Web(5)-Servlet详解(上)

    一.Servlet 1. 什么是Servlet Servlet 是 JavaEE 规范之一,规范就是接口 Servlet 就 JavaWeb 三大组件之一,三大组件分别是:Servlet 程序.Fil ...

  5. java web之Filter详解

    java web之Filter详解 2012-10-20 0 个评论 作者:chenshufei2 收藏 我要投稿 .概念: Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,W ...

  6. java web.xml配置详解(转)

    源出处:java web.xml配置详解 1.常规配置:每一个站的WEB-INF下都有一个web.xml的设定文件,它提供了我们站台的配置设定. web.xml定义: .站台的名称和说明 .针对环境参 ...

  7. 《Tomcat与Java Web开发技术详解》思维导图

    越想构建上层建筑,就越觉得底层基础很重要.补课系列. 书是良心书,就是太基础了,正适合补课. [纯文字版] Tomcat与Java Web开发技术详解 Servlet Servlet的生命周期 初始化 ...

  8. Java web.xml 配置详解

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  9. java web.xml配置详解

    1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Servl ...

随机推荐

  1. Oracle 12C ORA-65096: 公用用户名或角色名无效

    先说基本用法: 先按11G之前进行 conn / as sysdba; create user test identifed by test; ORA-65096: 公用用户名或角色名无效. 查官方文 ...

  2. String,StringBuilder区别,一个是常量,一个是可变量

    String str="这就是爱的呼唤,这就是爱的奉献!!"; //这个str是不可变的字符串序列,要变会生成新的字符串,原字符串不变,是常量 StringBuilder sBui ...

  3. MATLAB矩阵操作

  4. jenkins之从0到1利用Git和Ant插件打war包并自动部署到tomcat(第三话):创建一个自由风格的项目(非maven),实现自动打war包

    上一节把git和ant安装在虚拟机,并在jenkins上做了相关配置,接下来就可以真正开始构建一个项目了 1.新建一个自由风格的项目,因为是用ant打包,所以不要选择构建maven项目 2.配置源码管 ...

  5. linux: 安装jdk(java)

    作为Java开发人员,在Linux下安装一些开发工具是必备技能,本文以安装jdk为例,详细记录了每一步的操作命令,以供参考. 0.下载jdk8 登录网址:http://www.oracle.com/t ...

  6. Bayesian generalized linear model (GLM) | 贝叶斯广义线性回归实例

    一些问题: 1. 什么时候我的问题可以用GLM,什么时候我的问题不能用GLM? 2. GLM到底能给我们带来什么好处? 3. 如何评价GLM模型的好坏? 广义线性回归啊,虐了我快几个月了,还是没有彻底 ...

  7. php实现队列

    <?php //双向队列的实现 class DoubleEndedQueue{ public $elements; public function __construct(){//析构函数,创建 ...

  8. 在线linux 平台

    1.http://www.shiyanlou.com/[实验楼] 2.http://bellard.org/jslinux/[大牛平台]

  9. DRF之权限认证,过滤分页,异常处理

    1. 认证Authentication 在配置文件中配置全局默认的认证方案 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_f ...

  10. python基础之 反射,md5加密 以及isinstance, type, issubclass内置方法的运用

    内容梗概: 1. isinstance, type, issubclass 2. 区分函数和方法 3. 反射(重点) 4. md5加密 1. isinstance, type, issubclass1 ...