初探SpringMVC,走進SpringMVC的世界

1.Springmvc入門

1.1.Springmvc是什麼

SpringMVC是Spring中的一個組件,目前(2019)在互聯網公司用的不少,是必需學習的一門框架技術!SpringMVC用於web層,至關於controller(等價於傳統的servlet和struts的action,或者hendler),用來處理用戶請求。舉個例子,用戶在地址欄輸入http://網站域名/login,那麼springmvc就會攔截到這個請求,而且調用controller層中相應的方法,(中間可能包含驗證用戶名和密碼的業務邏輯,以及查詢數據庫操做,但這些都不是springmvc的職責),最終把結果返回給用戶,而且返回相應的頁面(固然也能夠只返回json/xml等格式數據)。springmvc就是作前面和後面過程的活,與用戶打交道!!springmvc須要有spring的jar包做爲支撐才能跑起來,因此學好Spring也是很是重要的!javascript

Spring web mvc和Struts2都屬於表現層的框架,它是Spring框架的一部分,咱們能夠從Spring的總體結構中看得出來,以下圖:
在這裏插入圖片描述css

1.2.Springmvc處理流程

以下圖所示:
在這裏插入圖片描述html

1.3.入門程序

需求:使用瀏覽器顯示商品列表前端

1.3.1.建立web工程

springMVC是表現層框架,須要搭建web工程開發。
建立動態web工程:java

輸入工程名,選擇配置Tomcat(若是已有,則直接使用),以下圖:程序員

在這裏插入圖片描述

選擇成功,點擊Finish,以下圖:
在這裏插入圖片描述
選擇剛剛設置成功的Tomcat,以下圖:
在這裏插入圖片描述web

以下圖選擇web的版本是2.5,能夠自動生成web.xml配置文件,spring

在這裏插入圖片描述

建立效果以下圖:
在這裏插入圖片描述數據庫

1.3.2.導入jar包

從課前資料中導入springMVC的jar包,以下圖:
在這裏插入圖片描述編程

複製jar到lib目錄,工程直接加載jar包,以下圖:
在這裏插入圖片描述

1.3.3.加入配置文件

建立config資源文件夾,存放配置文件,以下圖:
在這裏插入圖片描述

1.3.3.1.建立springmvc.xml

建立SpringMVC的核心配置文件springmvc.xml
SpringMVC自己就是Spring的子項目,對Spring兼容性很好,不須要作不少配置。
這裏只配置一個Controller掃描就能夠了,讓Spring對頁面控制層Controller進行管理。

建立springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
</beans>
1.3.3.2.springmvc.xml中配置處理器適配器HandlerAdapter

由於處理器Handler要根據適配器的要求來開發,因此咱們先配置一下適配器HandlerAdapter,在springmvc.xml中配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 處理器適配器:HandlerAdapter。全部處理器適配器都實現了HandlerAdapter接口-->
    <!-- SimpleControllerHandlerAdapter適配器能執行實現了Controller接口的Handler 
    因此,如今配置了這個適配器的話,全部的處理器Handler必需要實現Controller接口才行。
-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> 
</beans>
1.3.3.3.springmvc.xml中配置處理器映射器HandlerMapping

在這裏插入圖片描述

1.3.3.4.web.xml中配置視圖解析器ViewResolver

配置視圖解析器ViewResolver,這樣就能夠解析jsp了
最終jsp物理地址:前綴+邏輯視圖名+後綴

配置視圖解析器ViewResolver代碼:

<!-- 視圖解釋器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 前綴 -->
            <property name="prefix" value="/WEB-INF/jsp/"/>
              <!-- 後綴 -->
            <property name="suffix" value=".jsp"/>
        </bean>
1.3.3.5.web.xml中整體效果代碼

web.xml中整體要包含:

一、springmvc.xml的 「頭」

二、組件掃描配置處理器handler(controller)

三、處理器適配器HandlerAdapter

四、處理器映射器HandlerMapping

五、視圖解析器ViewResolver

web.xml中整體效果代碼以下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
        
  <!-- 掃描@Controler  @Service   -->
        <context:component-scan base-package="com.gx.springmvc"/>
      
        <!-- 處理器映射器 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
      
        <!-- 處理器適配器 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
       
        <!-- 視圖解釋器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 前綴 -->
            <property name="prefix" value="/WEB-INF/jsp/"/>
              <!-- 後綴 -->
            <property name="suffix" value=".jsp"/>
        </bean>
   </beans>

配置文件須要的約束文件,位置以下圖:
在這裏插入圖片描述

建立包com.gx.springmvc.controller

1.3.3.6.在web.xml中配置前端控制器DispatcherServlet

配置SpringMVC的前端控制器DispatcherServlet
在web.xml中

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>springmvc-first</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

    <!-- 配置SpringMVC前端控制器 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定SpringMVC配置文件 -->
        <!-- SpringMVC的配置文件的默認路徑是/WEB-INF/${servlet-name}-servlet.xml -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <!-- 設置全部以action結尾的請求進入SpringMVC -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>

從上面的配置中能夠看出,和之前學習servlet時候的配置基本上如出一轍,前端控制器就至關於一個servlet

重點注意:

一、配置contextConfigLocation:用來加載springmvc的配置文件(配置處理器映射器、適配器等)

不配置contextConfigLocation,則默認加載WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml

因此處理器映射器和處理器適配器都會配在classpath下咱們指定的springmvc.xml中。
  
二、DispatcherServlet的攔截方式,主要有三種攔截方式,以下:

方式一: *.action , 能夠訪問以.action結尾的地址,由DispatcherServlet進行解析。此方法最簡單,不會致使靜態資源(jpg,js,css)被攔截。【開發中常用】
方式二:/ ,全部訪問的地址都由DispatcherServlet進行解析,此方法能夠實現REST風格的url,不少互聯網類型的應用使用這種方式。可是此方法會致使靜態文件(jpg,js,css)被攔截後不能正常顯示,因此對靜態文件的解析須要配置不讓DispatcherServlet進行解析。【開發中建議使用】

方式三: * ,這樣配置是不對的,使用這種配置,最重要轉發到一個jsp頁面時,仍然會由DispatcherServlet解析jsp地址,不能根據jsp頁面找到Handler,會報錯。【開發中不建議使用】

1.3.4.加入jsp頁面

jsp建立到工程的/WEB-INF/jsp目錄下,jsp以下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查詢商品列表</title>
</head>
<body> 
<form action="${pageContext.request.contextPath }/item/queryitem.action" method="post">
查詢條件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查詢"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
    <td>商品名稱</td>
    <td>商品價格</td>
    <td>生產日期</td>
    <td>商品描述</td>
    <td>操做</td>
</tr>
<c:forEach items="${itemList }" var="item">
<tr>
    <td>${item.name }</td>
    <td>${item.price }</td>
    <td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
    <td>${item.detail }</td>
    
    <td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>

</tr>
</c:forEach>

</table>
</form>
</body>
</html>

1.3.5.實現顯示商品列表頁

1.3.5.1.建立pojo

分析頁面,查看頁面須要的數據,以下圖:
在這裏插入圖片描述

建立商品pojo

public class Item {
    // 商品id
    private int id;
    // 商品名稱
    private String name;
    // 商品價格
    private double price;
    // 商品建立時間
    private Date createtime;
    // 商品描述
    private String detail;

建立帶參數的構造器
set/get。。。
}
1.3.5.2.建立普通java類ItemController

一、ItemController是一個普通的java類,不須要實現任何接口。

二、須要在類上添加@Controller註解,在1.3.3.1.建立springmvc.xml中已經配置 掃描了Controller包,因此直接交由Spring管理

三、在方法上面添加@RequestMapping註解,裏面指定請求的url。其中「.action」能夠加也能夠不加。

四、因爲是入門程序,就暫時不鏈接數據庫,modelAndView.addObject給其頁面設置並賦值( 利用集合)

@Controller
public class ItemController {

    // @RequestMapping:裏面放的是請求的url,和用戶請求的url進行匹配
    // action能夠寫也能夠不寫
        // 建立頁面須要顯示的商品數據
    @RequestMapping(value = "/item/itemlist.action")
    public ModelAndView itemList(){
        List<Items> list= new ArrayList<Items>();
        list.add(new Items (1,"XiaoMi 9",233f,new Date(),"hhh1"));
        list.add(new Items (2,"XiaoMi 8",233f,new Date(),"hhh1"));
        list.add(new Items (3,"XiaoMi 7",233f,new Date(),"hhh1"));
        list.add(new Items (4,"XiaoMi 6",233f,new Date(),"hhh1"));

        // 建立ModelAndView,用來存放數據和視圖
        ModelAndView modelAndView = new ModelAndView();
        // 設置數據到模型中
        modelAndView.addObject("itemList", list); //第一個參數要對應JSP中的${value}
        // 設置視圖jsp,須要設置視圖的物理地址
        modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");

        return modelAndView;
    }
}

1.3.6.啓動項目測試

啓動項目,瀏覽器訪問地址
http://localhost:8080/springMVC/item/itemlist.action
效果以下圖:
在這裏插入圖片描述

1.3.7.org.springframework.web.servlet.DispatcherServlet noHandlerFound

固然並非每一個小白都能一次就測試失敗的,很幸運,你就是萬中無一的小白QAQ,我沒猜錯的話,兄嘚,你報了org.springframework.web.servlet.DispatcherServlet noHandlerFound
警告: No mapping found for HTTP request with URI [/springMVC/iteam/itemlist.action] in DispatcherServlet with name 'springMVC'
若是異常了,95%是這個異常,不要問我爲何,廠長是我表鍋..咳咳,這個異常就比較易出現,我就舉幾個出現該異常的狀況吧,中槍的自覺雙擊關注評論666

一、在 web.xml 中對 springDispatcherServlet 的配置出錯

二、Handler 類沒有加上 @Controller 註解,處理器將不會掃描該類是否使用了 @RequestMapping 註解。

三、@RequestMapping 的值和在瀏覽器輸入的地址不一致

四、訪問靜態資源時,請求會被 DispatcherServlet 攔截器攔截

五、檢查配置文件,必定是有些地方路徑沒有對應上

若是入門程序成功了,那麼恭喜恭喜,請進行下一步的探索

2.springMVC架構

2.1springMVC的架構圖

咳咳..兄臺你是否是很好奇上面的springMVC程序爲何能夠那樣用呢?好奇就對了,那就須要分析一下springMVC的架構圖了,嚶嚶嚶QAQ

在這裏插入圖片描述

2.2.架構流程

一、用戶發送請求至前端控制器DispatcherServlet

二、DispatcherServlet收到請求調用HandlerMapping處理器映射器。

三、處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(若是有則生成)一併返回給DispatcherServlet。

四、DispatcherServlet經過HandlerAdapter處理器適配器調用處理器

五、執行處理器(Controller,也叫後端控制器)。

六、Controller執行完成返回ModelAndView

七、HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet

八、DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器

九、ViewReslover解析後返回具體View

十、DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)。

十一、DispatcherServlet響應用戶

2.3.springmvc組件說明

在springmvc的各個組件中,處理器映射器、處理器適配器、視圖解析器稱爲springmvc的三大組件

如下組件一般使用框架提供實現:

DispatcherServlet:前端控制器
用戶請求到達前端控制器,它就至關於mvc模式中的c,dispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,dispatcherServlet的存在下降了組件之間的耦合性。

HandlerMapping:處理器映射器
HandlerMapping負責根據用戶請求url找到Handler即處理器,springmvc提供了不一樣的映射器實現不一樣的映射方式,例如:配置文件方式,實現接口方式,註解方式等。

Handler:處理器
Handler 是繼DispatcherServlet前端控制器的後端控制器,在DispatcherServlet的控制下Handler對具體的用戶請求進行處理。
因爲Handler涉及到具體的用戶業務請求,因此通常狀況須要程序員根據業務需求開發Handler。

HandlAdapter:處理器適配器
經過HandlerAdapter對處理器進行執行,這是適配器模式的應用,經過擴展適配器能夠對更多類型的處理器進行執行。
下圖是許多不一樣的適配器,最終均可以使用usb接口鏈接
在這裏插入圖片描述

ViewResolver:視圖解析器
View Resolver負責將處理結果生成View視圖,View Resolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果經過頁面展現給用戶。

View:視圖
springmvc框架提供了不少的View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。咱們最經常使用的視圖就是jsp。

通常狀況下須要經過頁面標籤或頁面模版技術將模型數據經過頁面展現給用戶,須要由程序員根據業務需求開發具體的頁面。

須要用戶開發的組件有handler、view

2.4.默認加載的組件(瞭解)

咱們沒有作任何配置,就可使用這些組件
由於框架已經默認加載這些組件了,配置文件位置以下圖:
在這裏插入圖片描述

代碼以下:

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

2.5.組件掃描器

組件掃描器主要做用:使用組件掃描器省去在spring容器配置每一個Controller類的繁瑣

使用< context:component-scan >自動掃描標記@Controller的控制器類,

組件掃描器在springmvc.xml配置文件中配置以下:

<!-- 配置controller掃描包,多個包之間用,分隔 -->
<context:component-scan base-package="cn.itcast.springmvc.controller" />

2.6.註解映射器和適配器

2.6.1.配置處理器映射器

註解式處理器映射器,對類中標記了@ResquestMapping的方法進行映射。根據@ResquestMapping定義的url匹配@ResquestMapping標記的方法,匹配成功返回HandlerMethod對象給前端控制器。
HandlerMethod對象中封裝url對應的方法Method。

從spring3.1版本開始,廢除了DefaultAnnotationHandlerMapping的使用,推薦使用RequestMappingHandlerMapping完成註解式處理器映射。

在springmvc.xml配置文件中配置以下:

<!-- 配置處理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />

註解描述:
@RequestMapping:定義請求url處處理器功能方法的映射

2.6.2.配置處理器適配器

註解式處理器適配器,對標記@ResquestMapping的方法進行適配。

從spring3.1版本開始,廢除了AnnotationMethodHandlerAdapter的使用,推薦使用RequestMappingHandlerAdapter完成註解式處理器適配。

在springmvc.xml配置文件中配置以下:

<!-- 配置處理器適配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
2.6.3.註解驅動

直接配置處理器映射器和處理器適配器比較麻煩,可使用註解驅動來加載。
SpringMVC使用< mvc:annotation-driven >自動加載RequestMappingHandlerMapping和RequestMappingHandlerAdapter
能夠在springmvc.xml配置文件中使用< mvc:annotation-driven >替代註解處理器和適配器的配置。

<!-- 註解驅動 -->
<mvc:annotation-driven />

2.7.視圖解析器

視圖解析器使用SpringMVC框架默認的InternalResourceViewResolver,這個視圖解析器支持JSP視圖解析
在springmvc.xml配置文件中配置以下:

<!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> 
        "/WEB-INF/jsp/test.jsp" -->
    <!-- 配置視圖解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置邏輯視圖的前綴 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 配置邏輯視圖的後綴 -->
        <property name="suffix" value=".jsp" />
    </bean>

邏輯視圖名須要在controller中返回ModelAndView指定,好比邏輯視圖名爲ItemList,則最終返回的jsp視圖地址: 「WEB-INF/jsp/itemList.jsp」

最終jsp物理地址:前綴+邏輯視圖名+後綴

2.7.1.修改Handler (ItemController )

修改ItemController中設置視圖的代碼
@RequestMapping:裏面放的是請求的url,和用戶請求的url進行匹配
// action能夠寫也能夠不寫

package com.gx.springmvc;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;


import com.gx.po.Items;
@Controller
public class ItemController {
    @RequestMapping(value = "/item/itemlist.action")
    public ModelAndView itemList(){
        List<Items> list= new ArrayList<Items>();
        list.add(new Items (1,"XiaoMi 9",233f,new Date(),"hhh1"));
        list.add(new Items (2,"XiaoMi 8",233f,new Date(),"hhh1"));
        list.add(new Items (3,"XiaoMi 7",233f,new Date(),"hhh1"));
        list.add(new Items (4,"XiaoMi 6",233f,new Date(),"hhh1"));
        
        ModelAndView mav= new ModelAndView();
        
        mav.addObject("itemList",list);
        mav.setViewName("itemList");
        return mav;
    }
}
2.7.2.效果

效果和以前同樣,以下圖:
在這裏插入圖片描述
到這裏兄嘚,springMVC的入門程序以及SpringMVC架構就有了必定的瞭解!是否是以爲頗有成就感

啊? 拉倒吧! 我都很差意思說了.可是我是阻止不了你驕傲的心. 那就頂我,讓我感覺感覺你的驕傲!哈哈

哈...哈哈..啊..咳咳..嗝氣了QAQ...

2.8結語

我但願各位最好是按照以上思路本身去動手敲一遍,走一個流程,切勿眼高手低(你會發現一動手就bug成堆),學編程最忌諱的就是眼高手低!!!

若是本文對你有一點點幫助,那麼請點個讚唄,謝謝~

最後,如有不足或者不正之處,歡迎指正批評,感激涕零!若是有疑問歡迎留言,絕對第一時間回覆!

歡迎各位關注個人公衆號,一塊兒探討技術,嚮往技術,追求技術,說好了來了就是盆友喔...

在這裏插入圖片描述

相關文章
相關標籤/搜索