溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

servlet.service()方法怎么調(diào)用

發(fā)布時(shí)間:2021-12-24 17:39:46 來(lái)源:億速云 閱讀:256 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“servlet.service()方法怎么調(diào)用”,在日常操作中,相信很多人在servlet.service()方法怎么調(diào)用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”servlet.service()方法怎么調(diào)用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

Tomcat是從org.apache.catalina.startup.Bootstrap#main()開(kāi)始啟動(dòng). 大致分為三個(gè)步驟,即init、load和start。代碼如下:

Java代碼

public static void main(String args[]) {              try {                  // Attempt to load JMX class                  new ObjectName("test:foo=bar");              } catch (Throwable t) {                  System.out.println(JMX_ERROR_MESSAGE);                  try {                      // Give users some time to read the message before exiting                      Thread.sleep(5000);                  } catch (Exception ex) {                  }                  return;              }              if (daemon == null) {                  daemon = new Bootstrap();                  try {                      daemon.init();   ★1                  } catch (Throwable t) {                      t.printStackTrace();                      return;                  }              }              try {                  String command = "start";                  if (args.length > 0) {                      command = args[args.length - 1];                  }                  if (command.equals("startd")) {                      args[0] = "start";                      daemon.load(args);                      daemon.start();                  } else if (command.equals("stopd")) {                      args[0] = "stop";                      daemon.stop();                  } else if (command.equals("start")) {                      daemon.setAwait(true);                      daemon.load(args);   ★2                       // 反射調(diào)用Catalina的start方法                      daemon.start();        ★3                  } else if (command.equals("stop")) {                      daemon.stopServer(args);                  }              } catch (Throwable t) {                  t.printStackTrace();              }          }

從以上可以很清楚的看出tomcat是通過(guò)參數(shù)的不同進(jìn)行相應(yīng)的命令調(diào)用。

★1 啟動(dòng)、初始化(加載類(lèi))

啟動(dòng)之前要進(jìn)行相應(yīng)的init()初始化,進(jìn)行相應(yīng)的環(huán)境設(shè)置以及包的加,以下是init()方法。(org.apache.catalina.startup.Bootstrap.init())

Java代碼

public void init()              throws Exception          {              setCatalinaHome();//設(shè)置Catalina安裝目錄              setCatalinaBase();//設(shè)置Catalina工作目錄              initClassLoaders();//加載jar包                 // 將classload設(shè)置進(jìn)線程,以便我們使用時(shí)進(jìn)行調(diào)用                    Thread.currentThread().                            setContextClassLoader(catalinaLoader);              SecurityClassLoad.securityClassLoad(catalinaLoader);                  // 加載啟動(dòng)類(lèi)和調(diào)用它的process方法              if (log.isDebugEnabled())                  log.debug("Loading startup class");              Class startupClass =                  catalinaLoader.loadClass                  ("org.apache.catalina.startup.Catalina");              Object startupInstance = startupClass.newInstance();                  // 設(shè)置共享擴(kuò)張類(lèi)加載器              if (log.isDebugEnabled())                  log.debug("Setting startup class properties");              String methodName = "setParentClassLoader";              Class paramTypes[] = new Class[1];              paramTypes[0] = Class.forName("java.lang.ClassLoader");              Object paramValues[] = new Object[1];              paramValues[0] = sharedLoader;              Method method =              startupInstance.getClass().getMethod(methodName,                                                                paramTypes);              method.invoke(startupInstance, paramValues);              catalinaDaemon = startupInstance;          }

在加載jar的時(shí)候,需要初始化classloader,代碼如下:(org.apache.catalina.startup.Bootstrap)

Java代碼

private void initClassLoaders() {              try {                  commonLoader = createClassLoader("common", null);                  catalinaLoader= createClassLoader("server", commonLoader);                  sharedLoader = createClassLoader("shared", commonLoader);              } catch (Throwable t) {                  log.error("Class loader creation threw exception", t);                  System.exit(1);              }          }

tomcat中的加載方式是:

|-------commonLoader (common)-> System Loader

|-------sharedLoader (shared)-> commonLoader -> System Loader

|-------catalinaLoader(server) -> commonLoader -> System Loader

Common是公共類(lèi)加載器,負(fù)責(zé)加載tomcat內(nèi)部和web應(yīng)用程序可以看到的類(lèi)(%CATALINA_HOME%/bin/common下的jar文件),Catalina負(fù)責(zé)加載的是tomcat內(nèi)部使用的類(lèi)(%CATALINA_HOME%/server下的jar文件),這些類(lèi)對(duì)web應(yīng)用程序不可見(jiàn)。Shared負(fù)責(zé)加載的是web應(yīng)用程序之間共享的類(lèi)(%CATALINA_BASE%/shared下的jar文件),這些類(lèi)對(duì)于tomcat內(nèi)部是不可見(jiàn)的。如果%CATALINA_HOME%/conf/catalina.Properties中沒(méi)有指定Common的搜索路徑,則用當(dāng)前的類(lèi)的類(lèi)加載器即系統(tǒng)類(lèi)加載器作為Common。

★2 裝載相應(yīng)的資源

下面主要講解tomcat的load()方法。下圖是Catalina.load方法的時(shí)序圖。

servlet.service()方法怎么調(diào)用

(1) 從上面的時(shí)序圖可以看出首先調(diào)用Catalina類(lèi)的load()方法,具體代碼如下:

(org.apache.catalina.startup.Catalina)。

Java代碼

public void load() {              initDirs();                  // Before digester - it may be needed              initNaming();                  // Create and execute our Digester              Digester digester = createStartDigester();                          try {                  inputSource.setByteStream(inputStream);                  digester.push(this);                  digester.parse(inputSource); //對(duì)server.xml進(jìn)行解析                  inputStream.close();              }             ......              // Start the new server              if (server instanceof Lifecycle) {                  try {                      server.initialize();  //server初始化工作                  } catch (LifecycleException e) {                      log.error("Catalina.start", e);                  }              }              long t2 = System.currentTimeMillis();              log.info("Initialization processed in " + (t2 - t1) + " ms");              }

(2) 在上面的load()方法中需要進(jìn)行server的初始化工作,下圖為Catalina.initialize的時(shí)序圖,從圖中可以看出server初始化所完成的工作。

servlet.service()方法怎么調(diào)用

至此,load方法結(jié)束,初期化的工作結(jié)束,下面開(kāi)始進(jìn)入start方法。

★3 容器啟動(dòng)

容器啟動(dòng)時(shí),會(huì)調(diào)用Catalina.start(),下圖為它的時(shí)序圖。從圖中可以看出StandardService的start方法被調(diào)用后會(huì)分別對(duì)Container和Connector進(jìn)行start方法的調(diào)用。

servlet.service()方法怎么調(diào)用

1. Bootstrap調(diào)用Catalina的start方法

Catalina.start()方法(org.apache.catalina.startup.Catalina.start())

Java代碼

public void start() {          // 啟動(dòng)server          if (server instanceof Lifecycle) {              try {                  ((Lifecycle) server).start();                          ......         }

2. Catalina調(diào)用StandardServer的start方法

StandardServer.start() (org.apache.catalina.core.StandardServer.start() )

Java代碼

public void start() throws LifecycleException {                    synchronized (services) {                  for (int i = 0; i < services.length; i++) {                      if (services[i] instanceof Lifecycle)                          ((Lifecycle) services[i]).start();                  }       }

3. StandardServer調(diào)用StandardService的start方法

Java代碼

org.apache.catalina.core.StandardService.start() )              public void start() throws LifecycleException {                        if (container != null) {                  synchronized (container) {                      if (container instanceof Lifecycle) {                    //  standardEngine的啟動(dòng)                          ((Lifecycle) container).start();                      }                  }             //兩個(gè)connector的啟動(dòng),8080和8009               synchronized (connectors) {                   for (int i = 0; i < connectors.length; i++) {                       if (connectors[i] instanceof Lifecycle)                           ((Lifecycle) connectors[i]).start();                          }               }        }

以上StandardService.start()方法主要實(shí)現(xiàn)了兩個(gè)功能,standardEngine的啟動(dòng)和connector的啟動(dòng),下面分別來(lái)介紹。

下面是standardEngine的啟動(dòng)和connector的啟動(dòng)

● standardEngine的啟動(dòng)

(1) 首先是StandardEngine.start()被調(diào)用

Java代碼

public void start() throws LifecycleException {             // Standard container startup              //進(jìn)行l(wèi)ogger,manager,cluster,realm,resource的啟動(dòng)               super.start();      }

(2) super.start()--->org.apache.catalina.core.ContainerBase#start()

Java代碼

public synchronized void start() throws LifecycleException {      //(省略)  server.xml中配置應(yīng)用組件的啟動(dòng)         //StandardHost容器的啟動(dòng),                Container children[] = findChildren();                for (int i = 0; i < children.length; i++) {                    if (children[i] instanceof Lifecycle)                        ((Lifecycle) children[i]).start();                }                  //StandardPipeline的啟動(dòng)(容器與容器間的管道)                if (pipeline instanceof Lifecycle)                    ((Lifecycle) pipeline).start();       }

(3) StandardHost.start()被調(diào)用

Java代碼

public synchronized void start() throws LifecycleException {      //返回到以上的containerBase#start執(zhí)行pipeline              super.start();       }

(4) StandardPipeline#start

Java代碼

public synchronized void start() throws LifecycleException {             // 將會(huì)調(diào)用HostConfig#start方法               lifecycle.fireLifecycleEvent(START_EVENT, null);                      // Notify our interested LifecycleListeners               lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);        }

(5) HostConfig#start

Java代碼

public void start() {                 //部暑webapps                  deployApps();                   }

(6) HostConfig#deployApps

Java代碼

protected void deployApps() {            File appBase = appBase();            File configBase = configBase();            // Deploy XML descriptors from configBase            deployDescriptors(configBase, configBase.list());            // Deploy WARs, and loop if additional descriptors are found            deployWARs(appBase, appBase.list());            // Deploy expanded folders            deployDirectories(appBase, appBase.list());                  }

(7) deployWARs

Java代碼

protected void deployWARs(File appBase, String[] files) {      ……      deployWAR(contextPath, dir, file);                 }

(8) deployWAR

Java代碼

protected void deployWAR(String contextPath, File war, String file) {      if (context instanceof Lifecycle) {          // (省略)                  Class clazz = Class.forName(host.getConfigClass());                    LifecycleListener listener =                        (LifecycleListener) clazz.newInstance();                    ((Lifecycle) context).addLifecycleListener(listener);                }                context.setPath(contextPath);                context.setDocBase(file);                //以下這一步跟進(jìn)去,,StandardContext的啟動(dòng)                host.addChild(context);                }

(9) StandardContext#start

在Context的啟動(dòng)過(guò)程中,主要完成了以下任務(wù)。

----------------------------------------------------------------------------------------------------------------------

a) 設(shè)置web app的具體目錄webappResources。

b) postWorkDirectory (),創(chuàng)建臨時(shí)文件目錄。Tomcat下面有一個(gè)work目錄,用來(lái)存放臨時(shí)文件。

c) 觸發(fā)START_EVENT事件監(jiān)聽(tīng),在這個(gè)事件監(jiān)聽(tīng)里面會(huì)啟動(dòng)ContextConfig的start()事件,ContextConfig是用來(lái)配置web.xml的。

d) 為context創(chuàng)建welcome files,通常是這三個(gè)啟動(dòng)文件:index.html、index.htm、index.jsp

e) 配置filter

f) 啟動(dòng)帶有的Servlet。

g) 注冊(cè)JMX。

----------------------------------------------------------------------------------------------------------------------

至此,Container啟動(dòng)完畢,下面是connector的啟動(dòng)。

● connector的啟動(dòng)

(1) org.apache.catalina.connector.Connector.start()

Java代碼

public void start() throws LifecycleException {                 // Http11Protocol的啟動(dòng)                  protocolHandler.start();      }

(2) Http11Protocol#start

Java代碼

public void start() throws Exception {      try {                    //到了終點(diǎn)的啟動(dòng)                    endpoint.start();                } catch (Exception ex) {                    log.error(sm.getString("http11protocol.endpoint.starterror"), ex);                    throw ex;                }

(3) JIoEndPoint#start

Java代碼

public void start()                throws Exception {                                                for (int i = 0; i < acceptorThreadCount; i++) {                //這里的acceptor是一個(gè)線程,里面是一個(gè)serversocket的啟動(dòng)                        Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);                        acceptorThread.setPriority(threadPriority);                        acceptorThread.setDaemon(daemon);                        acceptorThread.start();                    }                }

(4) Acceptor#run

Java代碼

public void run() {                    // Accept the next incoming connection from the server socket                       try {                  //這里進(jìn)行了accept(),等待客戶端消息,進(jìn)行接收                           Socket socket = serverSocketFactory.acceptSocket(serverSocket);                           serverSocketFactory.initSocket(socket);                           // Hand this socket off to an appropriate processor                           if (!processSocket(socket)) {                               // Close socket right away                               try {                                   socket.close();                               } catch (IOException e) {                                   // Ignore                               }                           }                       }catch ( IOException x ) {                           if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);                       } catch (Throwable t) {                           log.error(sm.getString("endpoint.accept.fail"), t);                       }        }

至此Connector.start方法調(diào)用完畢。整個(gè)server啟動(dòng)完畢。

本次講解一下Tomcat請(qǐng)求處理的流程,不當(dāng)之處還請(qǐng)comment。

一. Tomcat 總體結(jié)構(gòu)

Tomcat采用模塊化管理,下面是 Tomcat 的總體結(jié)構(gòu)圖:

servlet.service()方法怎么調(diào)用

從上圖中可以看出 Tomcat 的核心是兩個(gè)組件:Connector 和 Container。下面是一些概念的介紹。

① Server

一個(gè)server代表了整個(gè)catalina servlet容器,在Tomcat里面的Server的用處是啟動(dòng)和監(jiān)聽(tīng)服務(wù)端事件(諸如重啟、關(guān)閉等命令)。

② Service

Service是由一個(gè)或多個(gè)Connector與一個(gè)Engine的組合。

③ Connector

Connector將在某個(gè)指定的端口上監(jiān)聽(tīng)客戶的請(qǐng)求,把從socket傳遞過(guò)來(lái)的數(shù)據(jù),封裝成Request,傳遞給Engine來(lái)處理,并從Engine處獲得響應(yīng)并返回給客戶。

Tomcat通常會(huì)用到兩種Connector:

a) Http Connector 在端口8080處偵聽(tīng)來(lái)自客戶browser的http請(qǐng)求。

b) AJP Connector 在端口8009處偵聽(tīng)來(lái)自其它WebServer(Apache)的servlet/jsp代理請(qǐng)求。

二、請(qǐng)求處理過(guò)程解析

1. Connector處理請(qǐng)求

Connector處理請(qǐng)求的流程大致如下:

servlet.service()方法怎么調(diào)用

Connector組件啟動(dòng)后,會(huì)偵聽(tīng)相關(guān)的端口的客戶端請(qǐng)求。

(1) 接受一個(gè)新的連接請(qǐng)求(org.apache.tomcat.util.net.TcpWorkerThread)

Java代碼

void runIt(Object[] perThrData){             Socket s = null;                  try {                      s = endpoint.acceptSocket();  //獲取一個(gè)請(qǐng)求                  } finally {                      if (endpoint.isRunning()) {                          endpoint.tp.runIt(this);        // 此處啟動(dòng)另一個(gè)TcpWorkerTread去接受其他請(qǐng)求,此線程處理已接受的請(qǐng)求                      }                  }                            TcpConnection con = null;            con = (TcpConnection) perThrData[0];            con.setEndpoint(endpoint);            con.setSocket(s);endpoint.getConnectionHandler().processConnection(con,(Object[]) perThrData[1]);          }

(2) 新接收的請(qǐng)求被傳到Http11ConnectionHandler中處理。(org.apache.coyote.http11.Http11Protocol.Http11ConnectionHandler)

Java代碼

void processConnection(TcpConnection connection, Object[] thData){              Http11Processor  processor=null;          processor=(Http11Processor)thData[Http11Protocol.THREAD_DATA_PROCESSOR];            socket=connection.getSocket();                               InputStream in = socket.getInputStream();            OutputStream out = socket.getOutputStream();          processor.setSocket(socket );          processor.process(in, out);        //processor是org.apache.coyote.http11.Http11Processor 的 一個(gè)實(shí)例      }

(3) 在 Http11Processor 中處理 http11 協(xié)議相關(guān)的信息(org.apache.coyote.http11.Http11Processor)

Java代碼

void process(InputStream input, OutputStream output) throws IOException{              ~~略~~              inputBuffer.setInputStream(input);              outputBuffer.setOutputStream(output);              inputBuffer.parseHeaders();            //http11 協(xié)議頭在此方法中被取出              adapter.service(request, response);               //adapter 是org.apache.catalina.connector.CoyoteAdapter 的 一個(gè)實(shí)例      }

接下來(lái)的流程交由容器進(jìn)行處理。

2. 容器處理請(qǐng)求

容器交由Pipeline處理,這個(gè)Pipeline里面會(huì)放置一些vavle,請(qǐng)求沿著pipeline傳遞下去并且vavle對(duì)其進(jìn)行相關(guān)的處理。比如說(shuō)日志等,valve還可以自定義,具體需要查看server.xml配置文件。相關(guān)類(lèi)圖如下:

servlet.service()方法怎么調(diào)用

Tomcat的主要處理組件Engine、Host、Context和Wrapper的實(shí)現(xiàn)都會(huì)實(shí)現(xiàn)Pipeline接口,實(shí)際對(duì)請(qǐng)求的處理是一個(gè)Adpater,Tomcat中Adapter的實(shí)現(xiàn)是CoyoteAdapter,因此容器請(qǐng)求處理的入口是CoyoteAdapter的service方法。

1. CoyoteAdapter.service

--組裝好請(qǐng)求處理鏈

--StandardEngine. getPipeline().getFirst().invoke(request, response);

--StandardEngineValve.invoke

2. StandardEngineValve.invoke

--Host.getPipeline().getFirst().invoke(request, response);

--StandardHostValve.invoke

3. StandardHostValve.invoke

--Context. getPipeline().getFirst().invoke(request, response);

--StandardContextValve.invoke

4. StandardContextValve.invoke

--ServletRequestListener.requestInitialized

--Wrapper.getPipeline().getFirst().invoke(request, response);

--StandardWrapperValve.invoke

-- ServletRequestListener.requestDestroyed

5. StandardWrapperValve.invoke

--組裝Filter+Servlet

--處理請(qǐng)求

(1) Connector傳來(lái)的請(qǐng)求調(diào)用CoyoteAdapter.service()方法。(org.apache.catalina.connector.CoyoteAdapter)

Java代碼

public void service(org.apache.coyote.Request req,                             org.apache.coyote.Response res)            throws Exception {                 ~~略~~          if (request == null) {               request = (Request) connector.createRequest();              request.setCoyoteRequest(req);              response = (Response) connector.createResponse();           response.setCoyoteResponse(res);           //創(chuàng)建request、response對(duì)象                 ~~略~~            }                  try {                 if (postParseRequest(req, request, res, response)) {        connector.getContainer().getPipeline().getFirst().invoke(request, response);      //此處的Container是StandardEngine對(duì)象                  ~~略~~             }        }

(2) 默認(rèn)StandardEngine的Pipeline會(huì)有StandardEngineValve處理單元(參照StandardEngine構(gòu)造函數(shù))。(org.apache.catalina.core.StandardEngineValve)

Java代碼

public final void invoke(Request request, Response response)            throws IOException, ServletException {               // Select the Host to be used for this Request        Host host = request.getHost();            if (host == null) {                 response.sendError                     (HttpServletResponse.SC_BAD_REQUEST,                     sm.getString("standardEngine.noHost",                                   request.getServerName()));                 return;             }               // Ask this Host to process this request             host.getPipeline().getFirst().invoke(request, response);           }

(3) 同樣的,StandardHost的Pipeline會(huì)有StandardHostValve處理單元。StandardHostValve如何處理請(qǐng)求跟StandardEngineValve類(lèi)似,接下來(lái)請(qǐng)求進(jìn)入到StandardContextValve.invoke

(4) 同樣的,StandardContext的Pipeline會(huì)有StandardContextValve處理單元。

Java代碼

public final void invoke(Request request, Response response)                throws IOException, ServletException {                 // Disallow any direct access to resources under WEB-INF or META-INF         MessageBytes requestPathMB = request.getRequestPathMB();                if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))                    || (requestPathMB.equalsIgnoreCase("/META-INF"))                    || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))                   || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {                    String requestURI = request.getDecodedRequestURI();                    notFound(requestURI, response);                    return;                }                  // Wait if we are reloading                while (context.getPaused()) {                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        ;                    }                }                  // Select the Wrapper to be used for this Request                Wrapper wrapper = request.getWrapper();                if (wrapper == null) {                    String requestURI = request.getDecodedRequestURI();                    notFound(requestURI, response);                    return;                }          //ServletRequestListener. requestInitialized        ~~略~~                  wrapper.getPipeline().getFirst().invoke(request, response);        //ServletRequestListener.requestDestroyed        ~~略~~             }

(5) 同樣的,StandardWrapper這個(gè)Pipeline會(huì)有StandardWrapperValve這個(gè)處理單元。在invoke()方法調(diào)用Filter的同時(shí),servlet.service()方法也將會(huì)被調(diào)用。

(org.apache.catalina.core.StandardWrapperValve)

Java代碼

void invoke(Request request, Response response, ValveContext valveContext)                      throws IOException, ServletException{               Servlet servlet = null;                HttpServletRequest hreq = (HttpServletRequest) request.getRequest();           //org.apache.catalina.Request被封裝成javax.servlet.http.HttpServletRequest.                HttpServletResponse hres =(HttpServletResponse) response.getResponse();       // org.apache.catalina.Response被封裝成javax.servlet.http.HttpServletResponse.               servlet = wrapper.allocate();       // 裝載servlet              if ((servlet != null) && (filterChain != null)) {                 filterChain.doFilter(hreq, hres);                   //調(diào)用此servlet的filterchain             }

(6) 調(diào)用servlet的filterchain 處理 request和response

(org.apache.catalina.core.ApplicationFilterChain)

Java代碼

void doFilter(ServletRequest request, ServletResponse response) throws                        IOException, ServletException{                   ~~略~~                 internalDoFilter(request,response);                   ~~略~~             }

(7) 調(diào)用internalDoFilter()處理請(qǐng)求。(org.apache.catalina.core.ApplicationFilterChain)

Java代碼

void internalDoFilter(ServletRequest request, ServletResponse response) throws                              IOException, ServletException{           // 此處省略filter 處理的代碼,filter 被一個(gè)一個(gè)調(diào)用。           // 如果http請(qǐng)求的是一個(gè)jsp頁(yè)面, 下面的 servlet 會(huì)是 org.apache.jasper.servlet.JspServlet 類(lèi)的一個(gè)實(shí)例           // 若是 html 頁(yè)面, 下面的 servlet 會(huì)是 org.apache.catalina.servlets.DefaultServlet 類(lèi)的一個(gè)實(shí)例           if ((request instanceof HttpServletRequest) &&                (response instanceof HttpServletResponse)) {            servlet.service((HttpServletRequest) request, (HttpServletResponse) response);              servlet.service(request, response);             } else {              servlet.service(request, response);            }          }

到此,關(guān)于“servlet.service()方法怎么調(diào)用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI