maven搭建ssm初級框架

喜歡的朋友能夠關注下,粉絲也缺。

前言:html

想必你們對smm框架已經熟悉的不能再熟悉了,它是由Spring、SpringMVC、MyBatis三個開源框架整合而成,常做爲數據源較簡單的web項目的框架。咱們在通常的項目都能用到它,本身搭建一個smm也挺方便的。下面我就給你們介紹一下如何搭建一個初級的ssm框架。java

下面吧demo的下載貢獻給你們,須要的能夠去下載mysql

https://download.csdn.net/download/dsn727455218/10524640git

正文:github

1.建立一個maven項目,這個這裏我就不作介紹了,很簡單的,拿eclipse舉例,下載maven插件就行,已經maven本地倉庫。web

2.準備須要得jar包,maven倉庫有能夠直接引用的,沒有的能夠動態的下載。redis

3.mybatis配置文件spring

<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:property-placeholder location="classpath:remote/db.properties" ignore-unresolvable="true" />
    <!-- 配置數據源 使用的是Druid數據源 -->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="driverClassName" value="${jdbc.driver}" />
 
        <!-- 初始化鏈接大小 -->
        <property name="initialSize" value="0" />
        <!-- 鏈接池最大使用鏈接數量 -->
        <property name="maxActive" value="20" />
 
        <!-- 鏈接池最小空閒 -->
        <property name="minIdle" value="0" />
        <!-- 獲取鏈接最大等待時間 -->
        <property name="maxWait" value="60000" />
        <property name="poolPreparedStatements" value="true" />
        <property name="maxPoolPreparedStatementPerConnectionSize" value="33" />
        <!-- 用來檢測有效sql -->
        <property name="validationQuery" value="${validationQuery}" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個鏈接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />
        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded鏈接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true" />
        <!-- 監控數據庫 -->
        <property name="filters" value="mergeStat" />
    </bean>
 
    <!-- myBatis文件內嵌 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自動掃描entity目錄, 省掉Configuration.xml裏的手工配置 -->
        <property name="configLocation" value="classpath:spring/myBatis-config.xml" />
        <property name="mapperLocations" value="classpath:com/demo/mapper/*.xml" />
        <!-- 配置PageHelper攔截實現分頁 -->
<!-- <property name="plugins"> -->
<!-- <array> -->
<!-- <bean id="sqlInterceptor" class="com.shou6.filter.SqlInterceptor"> -->
<!-- 攔截的sql語句 -->
<!-- <property name="sql_Intercept" value="^\s*select[\s\S]*$" /> -->
<!-- 不攔截的sql語句 ^\s*select\s+count\s*\\(\s*(?:\*|\w+)\s*\)\s+[\s\S]+$ -->
<!-- <property name="sql_Not_Intercept" value="^\s*select\s+[\s\S]+\S+_enable=1\s+[\s\S]+$" /> -->
<!-- </bean> -->
<!-- <bean class="com.github.pagehelper.PageHelper"> -->
<!-- <property name="properties"> -->
<!-- <value> -->
<!-- dialect=mysql -->
<!-- 該參數默認爲false,設置爲true時,會將RowBounds第一個參數offset當成pageNum頁碼使用,和startPage中的pageNum效果同樣 -->
<!-- offsetAsPageNum=true -->
<!-- 該參數默認爲false,設置爲true時,使用RowBounds分頁會進行count查詢 -->
<!-- rowBoundsWithCount=true -->
<!-- 設置爲true時,若是pageSize=0或者RowBounds.limit = 0就會查詢出所有的結果(至關於沒有執行分頁查詢,可是返回結果仍然是Page類型) -->
<!-- <property name="pageSizeZero" value="true"/> -->
 
<!-- 3.3.0版本可用 - 分頁參數合理化,默認false禁用 -->
<!-- 啓用合理化時,若是pageNum<1會查詢第一頁,若是pageNum>pages會查詢最後一頁 -->
<!-- 禁用合理化時,若是pageNum<1或pageNum>pages會返回空數據 -->
<!-- PageHelper.startPage(currentPage, pageSize, true)//第三個參數爲true時,該設置的「pageNum>pages會查詢最後一頁」才生效 -->
<!-- reasonable=false -->
<!-- 3.5.0版本可用 - 爲了支持startPage(Object params)方法 -->
<!-- 增長了一個`params`參數來配置參數映射,用於從Map或ServletRequest中取值 -->
<!-- 能夠配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默認值 -->
<!-- 不理解該含義的前提下,不要隨便複製該配置 <property name="params" value="pageNum=start;pageSize=limit;"/> -->
<!-- </value> -->
<!-- </property> -->
<!-- </bean> -->
<!-- </array> -->
<!-- </property> -->
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.demo.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
 
</beans>

4.myBatis-config:自動掃描實體類sql

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 
    
    <!-- 經過別名簡化對類的使用 -->
    <typeAliases>
        <!-- 經過package, 能夠直接指定package的名字, mybatis會自動掃描你指定包下面的javabean, 而且默認設置一個別名,默認的名字爲非限定類名來做爲它的別名。 -->
        <package name="com.demo.entity" />
    </typeAliases>
</configuration>

5.application-trans:事務管理數據庫

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- 配置事務管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
 
    <!-- 攔截器方式配置事物 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 傳播行爲 -->
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
        </tx:attributes>
    </tx:advice>
    
    <!-- 方式1:註解方式配置事物管理 -->
    <!-- <tx:annotation-driven transaction-manager="txAdvice" /> -->
    
    <!-- 方式2:Spring Aop配置事務管理 expose-proxy="true":解決非事務方法調用本類事務方法時事務不起做用 -->
    <aop:config expose-proxy="true">
        <aop:pointcut id="txPoint" expression="execution(* com.demo.service.impl.*.*(..))" />  
        <aop:advisor pointcut-ref="txPoint" advice-ref="txAdvice" /> 
    </aop:config>
    
</beans>

5.application:核心配置文件

<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- xsi:schemaLocation儘可能不配版本號,這樣會默認從本地加載xsd文件,斷網不會致使加載出錯 -->
    
    <!--引入配置屬性文件,使用@Value獲取值 -->
<!-- <bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> -->
<!-- <property name="locations"> -->
<!-- <list> -->
<!-- <value>classpath:nofilter.properties</value> -->
<!-- <value>classpath:config/param-injection.properties</value> -->
<!-- </list> -->
<!-- </property> -->
<!-- <property name="fileEncoding" value="UTF-8"/> -->
<!-- </bean> -->
    
<!-- <import resource="application-quartz.xml"/> -->
    <import resource="application-mybatis.xml"/>
<!-- <import resource="application-redis.xml"/> -->
    
    <!--自動掃描含有@Service將其注入爲bean -->
    <context:component-scan base-package="com.demo.service" />
    
    <import resource="application-trans.xml"/>
    
    <!-- 用於持有ApplicationContext,能夠使用BeanMgrUtil.getBean('xxxx')的靜態方法獲得spring bean對象 -->  
<!-- <bean class="com.shou6.utils.tools.BeanMgrUtil" lazy-init="false" /> -->
    
</beans>

6.spring-mvc:核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" 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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 
    <!-- spring全局異常捕獲 -->
<!-- <bean class="com.shou6.utils.exception.ExceptionHandler" /> -->
 
    <!-- AOP攔截controller注意:須要把切面類和controller 放在同一個spring的xml配置文件中 -->
    <context:component-scan base-package="com.demo.controller"/>
<!-- <context:component-scan base-package="com.shou6.filter"/> -->
 
    <!-- 對@AspectJ切面的bean建立代理(不設置則@Aspect註解的切面將無效) -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
 
    <!-- Jackson轉換器 -->
    <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>application/json;charset=UTF-8</value>
                <value>text/html;charset=UTF-8</value><!-- 避免IE出現下載JSON文件的狀況 -->
            </list>
        </property>
    </bean>
 
    <!-- String轉換器(爲配合APP支付異步通知) -->
    <bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
        <constructor-arg value="UTF-8" index="0"></constructor-arg><!--避免出現亂碼 -->
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
                <value>text/xml;charset=UTF-8</value>
            </list>
        </property>
    </bean>
 
    <!-- 啓動Spring MVC的註解功能,完成請求和返回的POJO-json/xml自動轉換 -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <!-- json轉換器 -->
                <ref bean="mappingJacksonHttpMessageConverter" />
                <ref bean="stringHttpMessageConverter" />
            </list>
        </property>
    </bean>
 
    <!-- 對模型視圖名稱的解析,即在模型視圖名稱添加先後綴 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <!-- 解決默認返回均是application/json格式問題 -->
        <property name="contentType" value="text/html;charset=UTF-8" />
        <property name="prefix" value="/" />
        <property name="suffix" value=".jsp" />
    </bean>
 
    <!-- 配置多文件上傳 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding">
            <value>UTF-8</value>
        </property>
        <property name="maxUploadSize">
            <!-- 上傳文件大小限制爲5M,5120*1000b -->
            <value>5120000</value>
        </property>
        <property name="maxInMemorySize">
            <value>4096</value>
        </property>
    </bean>
 
</beans>

7.log4j:日誌配置文件

# Rules reminder: # DEBUG &lt; INFO &lt; WARN &lt; ERROR &lt; FATAL # Global logging configuration log4j.rootLogger=debug,stdout # My logging configuration... log4j.logger.cn.jbit.mybatisdemo=DEBUG ## Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n log4j.logger.org.apache.ibatis=DEBUG ## log4j.logger.org.apache.jdbc.SimpleDataSource=DEBUG log4j.logger.org.apache.ibatis.jdbc.ScriptRunner=DEBUG ## log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapclientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG #base log config log4j.rootLogger=INFO,CONSOLE,INFO_FILE,ERROR_FILE log4j.addivity.org.apache=true #console config log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Threshold=INFO log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[%d{HH\:mm\:ss ms}]-%5p (%F\:%L)\:%m%n # information logs config log4j.appender.INFO_FILE=org.apache.log4j.DailyRollingFileAppender log4j.appender.INFO_FILE.File=..\\logs\\OSS-INFO.log log4j.appender.INFO_FILE.Threshold=INFO log4j.appender.INFO_FILE.Append=true log4j.appender.INFO_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.INFO_FILE.layout.ConversionPattern=[%d{HH\:mm\:ss ms}]-[%p]\:%m -&gt;%l %n # error logs config log4j.appender.ERROR_FILE=org.apache.log4j.DailyRollingFileAppender log4j.appender.ERROR_FILE.File=..\\logs\\OSS-ERROR.log log4j.appender.ERROR_FILE.Threshold=ERROR log4j.appender.ERROR_FILE.Append=true log4j.appender.ERROR_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ERROR_FILE.layout.ConversionPattern=[%d{HH\:mm\:ss ms}]-[%p]\:%m -&gt;%l %n # fail bill logs config log4j.logger.FAIL_BILL=INFO, FAIL_BILL log4j.appender.FAIL_BILL=org.apache.log4j.DailyRollingFileAppender log4j.appender.FAIL_BILL.File=..\\logs\\FAIL_BILL.log log4j.appender.FAIL_BILL.Threshold=FAIL_BILL log4j.appender.FAIL_BILL.Append=true log4j.appender.FAIL_BILL.layout=org.apache.log4j.PatternLayout log4j.appender.FAIL_BILL.layout.ConversionPattern=[%d{HH\:mm\:ss ms}]\:%m %n

8.web:項目啓動加載spring配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>MyDemo</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/application.xml</param-value>
  </context-param>
  
  <!-- 監聽spring -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <!-- 啓動系統服務 -->
<!-- <listener> -->
<!-- <listener-class>com.shou6.init.ServerInitHandler</listener-class> -->
<!-- </listener> -->
  
   <!-- 防止內存泄漏 -->
  <listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  </listener>
  
  <!-- 編碼過濾 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 
  <!-- spring mvc -->
  <servlet>
    <description>spring mvc servlet</description>
    <servlet-name>mvcServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value> classpath:spring/spring-mvc.xml </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvcServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
    <url-pattern>*.mdo</url-pattern>
  </servlet-mapping>
  
</web-app>

所須要的配置文件就這麼多,固然你須要redis,quartz也能夠加入配置。

下面我就來測試一下

在項目中我建立BaseMapper做爲一個父類接口,只須要繼承就能夠調用其方法,是爲了方便重複建立方法;BaseService也是一樣的道理。

首先咱們建立一個實體類User:

/** * @author dsn * * @version 建立時間:2018年7月5日 上午11:30:00 */
package com.demo.entity; /** * @author dsn * @version 建立時間:2018年7月5日 上午11:30:00 */
public class User { /** * @return the id */
    public int getId() { return id; } /** * @param id * the id to set */
    public void setId(int id) { this.id = id; } /** * @return the username */
    public String getUsername() { return username; } /** * @param username * the username to set */
    public void setUsername(String username) { this.username = username; } /** * @return the userpass */
    public String getUserpass() { return userpass; } /** * @param userpass * the userpass to set */
    public void setUserpass(String userpass) { this.userpass = userpass; } /** * @return the name */
    public String getName() { return name; } /** * @param name * the name to set */
    public void setName(String name) { this.name = name; } private int id; private String username; private String userpass; private String name; }

 

建立一個dao層接口:繼承BaseMapper引入實體類User

/** * @author dsn * * @version 建立時間:2018年7月5日 上午11:35:10 */
package com.demo.dao; import com.demo.entity.User; /** * @author dsn * @version 建立時間:2018年7月5日 上午11:35:10 */
public interface UserMapper extends BaseMapper<User> { }

 

建立一個service接口:繼承BaseService引入實體類User

/** * @author dsn * * @version 建立時間:2018年7月5日 上午11:35:36 */
package com.demo.service; import com.demo.entity.User; /** * @author dsn * @version 建立時間:2018年7月5日 上午11:35:36 */
public interface UserService extends BaseService<User> { }

 

建立一個Mapper文件:UserMapper.xml,這裏我寫一個insert的語句以及一個select語句,須要注意的是column須要與實體類User字段對應以及對應的type

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.demo.dao.UserMapper" >
  <resultMap id="userResultMap" type="com.demo.entity.User" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="userpass" property="userpass" jdbcType="VARCHAR" />
  </resultMap>
  <select id="selectList" parameterType="User" resultMap="userResultMap"> select id,username,userpass,name from user <where> disable='1' <if test="key!=null"> and ( username = #{key,jdbcType=VARCHAR} or name = #{key,jdbcType=VARCHAR} ) </if>
    </where>
  </select>
  <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into user(name,username,userpass) values(#{name},#{username},#{userpass}) </insert>
</mapper>

接下來咱們建立一個UserAction:這是做爲controller控制器,處理全部的訪問請求以及邏輯

/** * @author dsn * * @version 建立時間:2018年7月5日 上午11:47:26 */
package com.demo.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.demo.entity.User; import com.demo.service.UserService; /** * @author dsn * @version 建立時間:2018年7月5日 上午11:47:26 */ @Controller @RequestMapping("user") public class UserAction { @Resource private UserService userService; @ResponseBody @RequestMapping(value = "/adduser") public String addactivity(User user, String msg) throws Exception { int insert = userService.insert(user); if (insert == 1) { msg = "插入成功"; } else { msg = "插入失敗"; } return msg; } }

 

啓動項目,用postman測試一下,完美收官。

下面吧demo的下載貢獻給你們,須要的能夠去下載

https://download.csdn.net/download/dsn727455218/10524640

 

 

若有須要能夠加我Q羣【308742428】你們一塊兒討論技術。

後面會不定時爲你們更新文章,敬請期待。

喜歡的朋友能夠關注下,粉絲也缺。

相關文章
相關標籤/搜索