springboot项目中的注解 启动项目的方式 解决spring的bean.xml配置不生效 spring的基础JDBC配置
依賴
創(chuàng)建一個(gè) Spring Boot 工程時(shí),可以繼承自一個(gè) spring-boot-starter-parent ,也可以不繼承
先來(lái)看 parent 的基本功能有哪些?
賴,所以我們?cè)趯懸蕾嚂r(shí)才不需要寫版本號(hào)。
配置文件,例如 application-dev.properties 和 application-dev.yml。
如果Spring Boot 項(xiàng)目要繼承自公司內(nèi)部的 parent ,這個(gè)時(shí)候該怎么辦呢?
一個(gè)簡(jiǎn)單的辦法就是我們自行定義 dependencyManagement 節(jié)點(diǎn),然后在里邊定義好版本號(hào),再接下來(lái)在引用依賴時(shí)也就不用寫版本號(hào)了
注解
編寫啟動(dòng)類 控制器
編寫啟動(dòng)類:【項(xiàng)目的入口。】
,在Maven 工程的java 目錄下創(chuàng)建項(xiàng)目的包,包里創(chuàng)建一個(gè)App 類,
代碼如下:
可以直接使用組合注解@Spring BootApplication 來(lái)代替@EnableAutoConfiguration 和@ComponentScan ,
@EnableAutoConfiguration 注解表示開(kāi)啟自動(dòng)化配直。由于項(xiàng)目中添加了spring-boot-starterweb依賴, 因此在開(kāi)啟了自動(dòng)化配置之后會(huì)自動(dòng)進(jìn)行Spring 和SpringMVC 的配置。
在Java 項(xiàng)目的main 方法中,通過(guò)SpringApplication 中的m 方法啟動(dòng)項(xiàng)目。第一個(gè)參數(shù)傳入App.class ,告訴Spring 哪個(gè)是主要組件。第二個(gè)參數(shù)是運(yùn)行時(shí)輸入的其他參數(shù)。
接下來(lái)創(chuàng)建一個(gè)SpringMVC 中的控制器-HelloController,代碼如下:
在控制器中提供了一個(gè)"/hello "接口,此時(shí)需要配置包掃描才能將HelloController 注冊(cè)到SpringMVC 容器中,因此在App 類上面再添加一個(gè)注解@ComponentScan 進(jìn)行包掃描
也可以直接使用組合注解@SpringBootApplication 來(lái)代替@EnableAutoConfiguration 和@ComponentScan ,
啟動(dòng)項(xiàng)目有三種不同的方式
可以直接使用mvn 命令啟動(dòng)項(xiàng)目,命令如下
mvn springboot : run
啟動(dòng)成功后,在瀏覽器地址欄輸入“http://localhost: 8080/hello ”即可看到運(yùn)行結(jié)果
3… 打包啟動(dòng)
當(dāng)然, Spring Boot 應(yīng)用也可以直接打成jar 包運(yùn)行。在生產(chǎn)環(huán)境中,也可以通過(guò)這樣的方式來(lái)
運(yùn)行一個(gè)Spring Boot 應(yīng)用。要將S pring Boot 打成jar 包運(yùn)行,首先需要添加一個(gè)plugin 到pom.xml
文件中,代碼如下:
然后運(yùn)行mvn 命令進(jìn)行打包,代碼如下
mvn package
打包完成后,在項(xiàng)目的target 目錄下會(huì)生成一個(gè)jar 文件,通過(guò)java -jar 命令直接啟動(dòng)這個(gè)jar文件,
即java -jar xxxx.jar
組合注解configuration
@Spring BootApplication 實(shí)際上是一個(gè)組合注解,定義如下:
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan ( excludeFilters= { @Filter(type = FilterType . CUSTOM , classes= TypeExcludeFilter .class), @Filter (type = FilterType.CUSTOM , classes =AutoConfigurationExcludeFilter . class) } ) public @interface Spring BootApplication {}第一個(gè)@SpringBootConfiguration 的定義如下:
@Configuration
public @interface SpringBootConfiguration {}
原來(lái)就是一個(gè)@Configuration ,所以@Spring BootConfiguration 的功能就是表明這是一個(gè)配置
類,開(kāi)發(fā)者可以在這個(gè)類中配置Bean。從這個(gè)角度來(lái)講,這個(gè)類所扮演的角色有點(diǎn)類似于Spring中ApplicationContext.xml 文件的角色。
注解@EnableAutoConfiguration 表示開(kāi)啟自動(dòng)化配置。Spring Boot 中的自動(dòng)化配置是非侵入式的,在任意時(shí)刻,開(kāi)發(fā)者都可以使用自定義配置代替自動(dòng)化配置中的某一個(gè)配置。
③注解@ComponentScan 完成包掃描,也是Spring 中的功能。由于@ComponentScan 注解默認(rèn)掃描的類都位于當(dāng)前類所在包的下面, 因此建議在實(shí)際項(xiàng)目開(kāi)發(fā)中把項(xiàng)目啟動(dòng)類放在根包中
開(kāi)發(fā)者可以創(chuàng)建一個(gè)新的類專門用來(lái)配置Bean ,這樣便于配置的管理。這個(gè)類只需要加上@Configuration 注解即可
@Configuration
public class Myconfig{}
項(xiàng)目啟動(dòng)類中的@ComponentScan 注解,除了掃描@Service , @Repository 、@Component 、@Controller 和@RestController 等之外,也會(huì)掃描@Configuration 注解的類。
@ConfigurationProperties注解可以將對(duì)程序內(nèi)變量的賦值提取到配置文件中。
如:
修改application.yml:
file:
upload-dir: ./assets
啟動(dòng)類加上:
@EnableConfigurationProperties({BlogProperties.class, FileStorageProperties.class})
基于@Transactional注解的聲明式事務(wù)管理
Spring的聲明式事務(wù)管理,是通過(guò)AOP技術(shù)實(shí)現(xiàn)的事務(wù)管理,其本質(zhì)是對(duì)方法前后進(jìn)行攔截,然后在目標(biāo)方法開(kāi)始之前創(chuàng)建或者加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。 聲明式事務(wù)管理最大的優(yōu)點(diǎn)是不需要通過(guò)編程的方式管理事務(wù),因而不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)處理的代碼,只需相關(guān)的事務(wù)規(guī)則聲明,便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中。通常情況下,在開(kāi)發(fā)中使用聲明式事務(wù)處理,不僅因?yàn)槠浜?jiǎn)單,更主要是因?yàn)檫@樣使得純業(yè)務(wù)代碼不被污染,極大地方便了后期的代碼維護(hù)。
和編程式事務(wù)管理相比,聲明式事務(wù)管理唯一不足的地方是,最細(xì)粒度只能作用到方法級(jí)別,無(wú)法做到像編程式事務(wù)管理那樣可以作用到代碼塊級(jí)別。但即便有這樣的需求,也可以通過(guò)變通的方法進(jìn)行解決,例如,可以將需要進(jìn)行事務(wù)處理的代碼塊獨(dú)立為方法。Spring的聲明式事務(wù)管理可以通過(guò)兩種方式來(lái)實(shí)現(xiàn),一是基于XML的方式,一是基于@Transactional注解的方式。 @Transactional注解可以作用于接口、接口方法、類以及類方法上。當(dāng)作用于類上時(shí),該類的所有public方法都將具有該類型的事務(wù)屬性,同時(shí),也可以在方法級(jí)別使用該注解來(lái)覆蓋類級(jí)別的定義。雖然@Transactional注解可以作用于接口、接口方法、類以及類方法上,但是Spring小組建議不要在接口或者接口方法上使用該注解,因?yàn)橹挥性谑褂没诮涌诘拇頃r(shí)它才會(huì)生效。可以使用@Transactional注解的屬性定制事務(wù)行為,具體屬性如表1.3所示。
具體實(shí)現(xiàn)步驟如下。
如何在事務(wù)處理中捕獲異常
聲明式事務(wù)處理的流程是: (1)Spring根據(jù)配置完成事務(wù)定義,設(shè)置事務(wù)屬性。 (2)執(zhí)行開(kāi)發(fā)者的代碼邏輯。 (3)如果開(kāi)發(fā)者的代碼產(chǎn)生異常(如主鍵重復(fù))并且滿足事務(wù)回滾的配置條件,則事務(wù)回滾;否則,事務(wù)提交。
現(xiàn)在的問(wèn)題是,如果開(kāi)發(fā)者在代碼邏輯中加入了try…catch…語(yǔ)句,Spring還能不能在聲明式事務(wù)處理中正常得到事務(wù)回滾的異常信息?答案是不能。這是因?yàn)槟J(rèn)情況下,Spring只在發(fā)生未被捕獲的RuntimeExcetpion時(shí)才回滾事務(wù)。如何在事務(wù)處理中捕獲異常呢?具體修改如下
(1)修改@Transactional注解。 需要將TestServiceImpl類中的@Transactional注解修改為: @Transactional(rollbackFor={Exception.class})
//rollbackFor指定回滾生效的異常類,多個(gè)異常類逗號(hào)分隔;
//noRollbackFor指定回滾失效的異常類
(2)在catch語(yǔ)句中添加“throw new RuntimeException();”語(yǔ)句。 注意:在實(shí)際工程應(yīng)用中,在catch語(yǔ)句中添加“TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();”語(yǔ)句即可。也就是說(shuō),不需要在@Transaction注解中添加rollbackFor屬性。
JDBC配置
spring jdbc的配置
xml配置:
Spring JDBC的XML配置主要使用Spring JDBC模塊的core和dataSource包進(jìn)行Spring數(shù)據(jù)庫(kù)編程。core包是JDBC的核心功能包,包括常用的JdbcTemplate類;dataSource包是訪問(wèn)數(shù)據(jù)源的工具類包。使用Spring JDBC操作數(shù)據(jù)庫(kù),需要對(duì)其進(jìn)行配置。XML配置文件示例代碼如下:
java配置:
package config;import org. springframework. beans. factory. annotation. Value;import org. springframework. context. annotation. Bean;import org. springframework. context. annotation. ComponentScan;import org. springframework. context. annotation. Configuration;import org. springframework. context. annotation. PropertySource;import org. springframework. jdbc. core. JdbcTemplate;import org. springframework. jdbc. datasource. DriverManagerDataSource;Configuration/通過(guò)該注解來(lái)表明該類是一個(gè) Spring的配置,相當(dāng)于一個(gè)xm文件 @ ComponentScan(basePackages="dao")/配置掃描包PropertySourcevalue=(value={"classpath:jdbc. properties"}, ignoreResourceNotFound=true) //配置多個(gè)屬性文件時(shí)value={"classpath jdbc.properties","xx","xxx”}public class SpringJDBCConfig@Value("s{jdbc.url}") //注入屬性文件jdbc. properties中的jdbc.urprivate String jdbcUrl;@Value("$ {jdbc. driverClassName}")private String jdbcDriverClassName;@Value("$ {jdbc. username}")private String jdbcUsername; @Value("sjdbc. password}")private String jdbcPassword; /** *配置數(shù)據(jù)源 **/@Beanpublic DriverManagerDataSource dataSource(){DriverManagerDataSource myDataSource =new DriverManagerDataSource() //數(shù)據(jù)庫(kù)驅(qū)動(dòng)myDataSource. setDriverClassName(jdbcDriverClassName); //相應(yīng)驅(qū)動(dòng)的jdbcUrlmyDataSource. setUrl( jdbcUr1) //數(shù)據(jù)庫(kù)的用戶名myDataSource. setUsername(jdbcUsername); //數(shù)據(jù)庫(kù)的密碼myDataSource. setPassword( jdbcUsername);return myDataSource; /** 配置 JdbcTemplate **/ @Bean( value="jdbcTemplate")public JdbcTemplate getJdbcTemplate(){return new JdbcTemplate( dataSource()); } }上述Java配置示例中,需要事先在classpath目錄(如應(yīng)用的src目錄)下創(chuàng)建屬性文件,代碼如下:
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8 jdbc.username=root jdbc.password=root另外,在數(shù)據(jù)訪問(wèn)層(如Dao類)使用jdbcTemplate時(shí),也需要將jdbcTemplate注入對(duì)應(yīng)的Bean中,代碼如下:
@Repositorypublic class TestDaoImpl implements TestDao{@Autowired //使用配置文件中的JDBC模板private JdbcTemplate jdbcTemplate; }獲取JDBC模板后,要知道如何使用它,需要了解JdbcTemplate類的常用方法——update()和query()方法。
· public int update(String sql,Object args[])
該方法可以對(duì)數(shù)據(jù)表進(jìn)行增加、修改、刪除等操作。使用args[]設(shè)置SQL語(yǔ)句中的參數(shù),并返回更新的行數(shù)。代碼如下: String insertSql=“insert into user values(null,?,?)”;
Object param1[]={“chenheng1”,“男”};
jdbcTemplate.update(sql,param1);
· public List query(String sql,RowMapper rowMapper,Object args[])
該方法可以對(duì)數(shù)據(jù)表進(jìn)行查詢操作。rowMapper將結(jié)果集映射到用戶自定義的類中**(前提是自定義類中的屬性要與數(shù)據(jù)表的字段對(duì)應(yīng)**)。代碼如下:
數(shù)據(jù)庫(kù)配置的屬性文件jdbc.properties,具體內(nèi)容如下:
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8 jdbc.username=root jdbc.password=root在應(yīng)用的src目錄下,創(chuàng)建config包,并在該包中創(chuàng)建配置類SpringJDBCConfig。在該配置類中使用@PropertySource注解讀取屬性文件jdbc.properties,并配置數(shù)據(jù)源和JdbcTemplate,具體代碼如下:
package config;import org.springframework.beans.factory.annotation. Value;import org.springframework.context.annotation.Bean;import org. springframework.context.annotation. ComponentScan;import org.springframework.context.annotation. Configuration;import org.springframework.context.annotation. PropertySource;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.datasource. DriverManagerDataSource; // Configuration通過(guò)該注解來(lái)表明該類是一個(gè) Spring的配置,相當(dāng)于一個(gè)xml文件ComponentScan(basePackages={"dao","service"})//配置掃描包PropertySource(value{"classpath:jdbc. properties"}, ignoreResourceNo=true)public class SpringJDBCConfigvalue("$ {jdbc. url}") //注入屬性文件jdbc. properties中的jdbc.urlprivate String jdbcUrl;value("s{jdb. driverClassName}")private String jdbcDriverClassName;@Value("$ {jdbc. username)")private String jdbcUsername;@Value(" ${jdbc. password}")private String jdbcPassword; //配置數(shù)據(jù)源 /@Beanpublic DriverManagerDataSource dataSource(){DriverManager DataSource myDataSource new DriverManagerDataSource(); //數(shù)據(jù)庫(kù)驅(qū)動(dòng)myDataSource. setDriverClassName( jdbcDriverClassName); /相應(yīng)驅(qū)動(dòng)的jdbcUr11myDataSource. setUrl( jdbcUr1) //數(shù)據(jù)庫(kù)的用戶名myDataSource. setUsername( jdbcUsername); //數(shù)據(jù)庫(kù)的密碼myDataSource. setPassword( jdbcUsername)return myDataSource; } //配置 JdbcTemplate@Bean(value="jdbcTemplate")public JdbcTemplate getJdbcTemplate(){return new JdbcTemplate( dataSource()) }src下創(chuàng)建entity包,創(chuàng)建實(shí)體類MyUser"
package entity;public class Myuser{private Integer uiaiprivate String uname;private string usexi 省略set和get方法public String toString(){return " [uid=" I uid +" uname ="+ uname+, usex "= usex +"]"}}數(shù)據(jù)訪問(wèn)層
src目錄下,創(chuàng)建dao包,在該包中創(chuàng)建數(shù)據(jù)訪問(wèn)接口TestDao和接口實(shí)現(xiàn)類TestDaoImpl。在實(shí)現(xiàn)類TestDaoImpl中使用@Repository注解標(biāo)注此類為數(shù)據(jù)訪問(wèn)層,并使用@Autowired注解依賴注入JdbcTemplate。
TestDaompl.java:
package dao;import java. util. List;import org. springframework.beans.factory.annotation. Autowired;import org. springframework.jdbc.core. BeanPropertyRowMapper;import org. springframework.jdbc.core.JdbcTemplate;import org. springframework.jdbc.core.RowMapper;import org. springframework.stereotype.Repository;import entity. MyUser;@Repositorypublic class TestDaoImpl implements TestDao{@Autowired //使用配置類中的JDBC模板private JdbcTemplate jdbcTemplate; /**更新方法,包括添加、修改、刪除param為sql中的參數(shù),如通配符? **/@Overridepublic int update(String sql, Object[ param){return jdbcTemplate. update(sql, param); }/**查詢方法param為sql中的參數(shù),如通配符? **/@Overridepublic List< MyUser> query(String sql, Object[] param){RowMapper<MyUser> rowMapper= new BeanPropertyRowMapper< MyUser>(MyUser.class);return jdbcTemplate. query(sql, rowMapper); } }創(chuàng)建業(yè)務(wù)邏輯層
src目錄下,創(chuàng)建service包,在該包中創(chuàng)建數(shù)據(jù)訪問(wèn)接口TestService和接口實(shí)現(xiàn)類TestServiceImpl。在實(shí)現(xiàn)類TestServiceImpl中使用**@Service注解標(biāo)注此類為業(yè)務(wù)邏輯層,并使用@Autowired注解依賴注入TestDao。**
TestService.java
TestServiceImpl.java
package service;import java. util.List;import org. springframework. beans. factory. annotation. Autowired;import org. springframework. stereotype. Service;import dao. TestDao;import entity. MyUser;Servicepublic class TestServiceImpl implements TestServiceAutowiredpublic TestDao testDao;Overridepublic void testJDBC(){String insertSql="insert into user values(null,?,?)"; //數(shù)組 param的值與 insertSql語(yǔ)句中的?一一對(duì)應(yīng)Object param1[]={"chenheng11","男"};Object param2[]={"chenheng22","女"};Object param3[] ={"chenheng3", ""}Object param4[] {"chenheng4", ""} //添加用戶testDao. update(insertSql, param1);testDao. update(insertSql, param2);testDao. update(insertSql, param3);testDao. update(insertSql, param4); //查詢用戶String selectSql ="select from user"; List< MyUser>list= testDao. query( selectSql,null);for(MyUser mu: list){System. out. println(mu); } }解決配置不生效
@ImportResource
@ImportResource:導(dǎo)入Spring的配置文件,讓配置文件生效。
示例:
boot.service.HelloService:
放在resource下的bean.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="helloService" class="boot.service.HelloService"></bean> </beans>BootApplicationTests.java
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class) @SpringBootTest public class BootApplicationTests {@AutowiredApplicationContext ioc;@Testpublic void testConfig() {boolean b = ioc.containsBean("helloService");System.out.print(b);}}運(yùn)行結(jié)果:
試圖通過(guò)添加一個(gè)Spring的配置文件bean.xml來(lái)把HelloService注入進(jìn)去。
運(yùn)行測(cè)試類結(jié)果:false
結(jié)果表明IoC容器中并不包含HelloService,即:配置文件bean.xml沒(méi)有生效
解決方式
方式一: 主程序中進(jìn)行配置@ImportResouece注解
先運(yùn)行主程序,然后再啟動(dòng)剛剛的測(cè)試類,現(xiàn)在輸出:
可以看到已經(jīng)是true
方法二:通過(guò)配置類實(shí)現(xiàn),這種方式也是Spring Boot推薦的
@Configuration
注意,這個(gè)config文件一定要在與測(cè)試類一樣的包下,否則不能成功添加組件,導(dǎo)致輸出仍然是false
文件目錄:
(其中MyConfig為配置類,鼠標(biāo)所在位置為測(cè)試類)
@Configuration標(biāo)注這是一個(gè)配置類
通過(guò)@Bean注解,將方法的返回值添加到容器之中,并且容器中這個(gè)組件的id就是方法名
2. 把主程序類中@ImportResource()配置注釋掉
3. 測(cè)試成功,添加了HelloService()組件
Web 容器配置
1.在Spring Boot 項(xiàng)目中,可以內(nèi)置Tomcat 、Jetty 、Undertow 、Netty 等容器。當(dāng)開(kāi)發(fā)者添加了
spring-boot-starter-web 依賴之后, 默認(rèn)會(huì)使用Tomcat 作為Web 容器。如果需要對(duì)Tomcat 做進(jìn)一步的配置,可以在application.properties 中進(jìn)行配置,代ti馬如下:
server .port=8081
server . error .path=/error
server . servlet .session.timeout=30m
server . servlet.context- path=/chapter02
se rver . tomcat.uri encodi ng=utf- 8
server .tomcat.max-threads=500
server . tomcat.basedir=/home/sang/tmp
server.port Web 容器的端口號(hào)。
error.path 當(dāng)項(xiàng)目出錯(cuò)時(shí)跳轉(zhuǎn)去的頁(yè)面。
session.timeout :session 失效時(shí)間, 30m 表示30 分鐘,如果不寫單位, 默認(rèn)單位是秒。
由于Tomcat 中配直session 過(guò)期時(shí)間以分鐘為單位, 因此這里單位如果是秒的話,該時(shí)間會(huì)被轉(zhuǎn)換為一個(gè)不超過(guò)所配直秒數(shù)的最大分鐘數(shù), 例如這里配置了119 ,默認(rèn)單位為秒,則實(shí)際session 過(guò)期時(shí)間為1 分鐘。
? context-path 表示項(xiàng)目名稱, 不配置時(shí),默認(rèn)為/。如果配置了,就要在訪問(wèn)路徑中加上配直的路徑。
? uri-encoding 表示配直Tomcat 請(qǐng)求編碼。
? max - threads 表示Tomcat 最大線程數(shù)。
? basedir 是一個(gè)存放Tomcat 運(yùn)行日志和臨時(shí)文件的目錄,若不配,則默認(rèn)使用系統(tǒng)的臨時(shí)目錄。
2.HTTPS 配置
由于HTTPS 具有良好的安全性,在開(kāi)發(fā)中得到了越來(lái)越廣泛的應(yīng)用, 像微信公眾號(hào)、小程序等的開(kāi)發(fā)都要使用HTTPS 來(lái)完成。對(duì)于個(gè)人開(kāi)發(fā)者而言, 一個(gè)HTTPS 證書的價(jià)格還是有點(diǎn)貴,國(guó)內(nèi)有一些云服務(wù)器廠商提供免費(fèi)的H TTPS 證書, 一個(gè)賬號(hào)可以申請(qǐng)數(shù)個(gè)。不過(guò)在jdk 中提供了一個(gè)Java 數(shù)字證書管理工具keytool , 在\jdk\bin 目錄下,通過(guò)這個(gè)工具可以自己生成一個(gè)數(shù)字證書,
生成命令如下:
? keytool -genkey -alias tomcathttps - keyalg RSA-keysize 2048 - keystore sang. p12-validity 365
? -genkey 表示要?jiǎng)?chuàng)建一個(gè)新的密鑰。
? -alias 表示keystore 的別名。
? -keya lg 表示使用的加密算法是RSA , 一種非對(duì)稱加密算法.
? -keysize 表示密鑰的長(zhǎng)度.
? -keystore 表示生成的密鑰存放位直。
? -validity 表示密鑰的有效時(shí)間,單位為天
總結(jié)
以上是生活随笔為你收集整理的springboot项目中的注解 启动项目的方式 解决spring的bean.xml配置不生效 spring的基础JDBC配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: VUE内置组件 vue使用插槽分发内容
- 下一篇: python 类 对象 魔法方法概念+习