中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

南昌簡(jiǎn)單做網(wǎng)站/我想找一個(gè)營(yíng)銷團(tuán)隊(duì)

南昌簡(jiǎn)單做網(wǎng)站,我想找一個(gè)營(yíng)銷團(tuán)隊(duì),平面設(shè)計(jì)師資格證怎么考,精美網(wǎng)站界面依賴包 新建一個(gè)工程,包含兩個(gè) module: springboot 模塊,表示 springboot 源碼實(shí)現(xiàn);user 模塊,表示業(yè)務(wù)系統(tǒng),使用 springboot 模塊; 依賴包:Spring、SpringMVC、Tomcat 等&#xff…

依賴包

新建一個(gè)工程,包含兩個(gè) module:

springboot 模塊,表示 springboot 源碼實(shí)現(xiàn);
user 模塊,表示業(yè)務(wù)系統(tǒng),使用 springboot 模塊;

依賴包:Spring、SpringMVC、Tomcat 等,引入依賴如下:

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.18</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>9.0.60</version></dependency>
</dependencies>

在 user 模塊下引入依賴:

<dependencies><dependency><groupId>org.example</groupId><artifactId>springboot</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>

定義對(duì)應(yīng)的 controller 和 service:

@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("test")public String test(){return userService.test();}
}

最終希望通過(guò)啟動(dòng) MyApplication 的 main 方法,啟動(dòng)項(xiàng)目,能訪問(wèn)到 UserController。

核心注解和核心類

SpringBoot 的核心類和注解:

@SpringBootApplication,這個(gè)注解是加在應(yīng)用啟動(dòng)類上的,也就是 main 方法所在的類;
SpringApplication,這個(gè)類中有個(gè) run() 方法,用來(lái)啟動(dòng) SpringBoot 應(yīng)用的;

所以,自定義類和注解以實(shí)現(xiàn)上面的功能。
@FireSpringBootApplication 注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
public @interface FireSpringBootApplication {
}

FireSpringApplication 啟動(dòng)類:

public class FireSpringApplication {public static void run(Class clazz){}
}

在 MyApplication 中使用:

@FireSpringBootApplication
public class MyApplication {public static void main(String[] args) {FireSpringApplication.run(MyApplication.class);}
}

run 方法

需要在 run 方法中啟動(dòng) tomcat,通過(guò) tomcat 接收請(qǐng)求;
DispatchServlet 綁定 spring 容器,DispatchServlet 接收到請(qǐng)求后需要在 spring 容器中找到一個(gè) controller 中對(duì)應(yīng)的方法;

run 方法中需要實(shí)現(xiàn)的邏輯:

  1. 創(chuàng)建一個(gè) Spring 容器
  2. 創(chuàng)建 Tomcat 對(duì)象
  3. 生成 DispatcherServlet 對(duì)象,并且和前面創(chuàng)建出來(lái)的 Spring 容器進(jìn)行綁定
  4. 將 DispatcherServlet 添加到 Tomcat 中
  5. 啟動(dòng) Tomcat

創(chuàng)建 Spring 容器

public class FireSpringApplication {public static void run(Class clazz){AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();applicationContext.register(clazz);applicationContext.refresh();}
}

run 方法中傳入的即使 MyApplication 類,被解析為 Spring 容器的配置類;
默認(rèn)會(huì)將 MyApplication 所在的包作為掃描路徑,從而掃描到 UserController 和 UserService,所以在 spring 容器啟動(dòng)后就會(huì)存在兩個(gè) bean 了;

啟動(dòng) Tomcat

使用內(nèi)嵌的 Tomact,即 Embed-Tomcat,啟動(dòng)代碼如下:

public static void startTomcat(WebApplicationContext applicationContext){Tomcat tomcat = new Tomcat();Server server = tomcat.getServer();Service service = server.findService("Tomcat");Connector connector = new Connector();// 綁定端口connector.setPort(8081);Engine engine = new StandardEngine();engine.setDefaultHost("localhost");Host host = new StandardHost();host.setName("localhost");String contextPath = "";Context context = new StandardContext();context.setPath(contextPath);context.addLifecycleListener(new Tomcat.FixContextListener());host.addChild(context);engine.addChild(host);service.setContainer(engine);service.addConnector(connector);// 添加DispatcherServlet,并且綁定一個(gè)Spring容器tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext));// 設(shè)置Mapping關(guān)系context.addServletMappingDecoded("/*", "dispatcher");try {tomcat.start();} catch (LifecycleException e) {e.printStackTrace();}}

在 run 方法中調(diào)用 startTomcat 方法啟動(dòng) tomcat:

public static void run(Class clazz){AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();applicationContext.register(clazz);applicationContext.refresh();// 啟動(dòng)tomcatstartTomcat(applicationContext);}

到此,一個(gè)簡(jiǎn)單的 SpringBoot 就寫(xiě)出來(lái)了,運(yùn)行 MyApplication 正常啟動(dòng)項(xiàng)目,通過(guò)瀏覽器就可以訪問(wèn) UserController 了。

實(shí)現(xiàn) Tomcat 和 Jetty 的切換

前面代碼中默認(rèn)啟動(dòng)的是 Tomcat,現(xiàn)在想改成這樣子:

  1. 如果項(xiàng)目中有 Tomcat 的依賴,那就啟動(dòng) Tomcat
  2. 如果項(xiàng)目中有 Jetty的依賴就啟動(dòng) Jetty
  3. 如果兩者都沒(méi)有則報(bào)錯(cuò)
  4. 如果兩者都有也報(bào)錯(cuò)

這個(gè)邏輯希望 SpringBoot 自動(dòng)實(shí)現(xiàn),對(duì)于程序員用戶而言,只要在 Pom 文件中添加相關(guān)依賴就可以了,想用 Tomcat 就加 Tomcat 依賴,想用 Jetty 就加 Jetty 依賴。
Tomcat 和 Jetty 都是應(yīng)用服務(wù)器,或者是 Servlet 容器,可以定義接口來(lái)表示它們,這個(gè)接口交 WebServer(SpringBoot 源碼中也叫這個(gè))。
定義接口如下:

public interface WebServer {public void start();}

Tomcat 實(shí)現(xiàn)類:

public class TomcatWebServer implements WebServer{@Overridepublic void start() {System.out.println("啟動(dòng)Tomcat");}
}

Jetty 實(shí)現(xiàn)類:

public class JettyWebServer implements WebServer{@Overridepublic void start() {System.out.println("啟動(dòng)Jetty");}
}

在 FireSpringApplication 中的 run 方法中,去獲取對(duì)應(yīng)的 WebServer,然后啟動(dòng)對(duì)應(yīng)的 webServer。
代碼如下:

public static void run(Class clazz){AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();applicationContext.register(clazz);applicationContext.refresh();// 自動(dòng)獲取配置的Tomcat或者Jetty容器WebServer webServer = getWebServer(applicationContext);webServer.start();}public static WebServer getWebServer(ApplicationContext applicationContext){return null;
}

模擬實(shí)現(xiàn)條件注解

首先實(shí)現(xiàn)一個(gè)條件注解@FireConditionalOnClass,對(duì)應(yīng)代碼如下:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Conditional(FireOnClassCondition.class)
public @interface FireConditionalOnClass {String value() default "";
}

注意核心為@Conditional(FireOnClassCondition.class)中的 FireOnClassCondition,因?yàn)樗攀钦嬲脳l件邏輯:

public class FireOnClassCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(FireConditionalOnClass.class.getName());String className = (String) annotationAttributes.get("value");try {context.getClassLoader().loadClass(className);return true;} catch (ClassNotFoundException e) {return false;}}
}

具體邏輯為,拿到@FireConditionalOnClass中的 value 屬性,然后用類加載器進(jìn)行加載,如果加載到了所指定的這個(gè)類,那就表示符合條件,如果加載不到,則表示不符合條件。

模擬實(shí)現(xiàn)自動(dòng)配置類

配置類代碼如下:

@Configuration
public class WebServiceAutoConfiguration {@Bean@FireConditionalOnClass("org.apache.catalina.startup.Tomcat")public TomcatWebServer tomcatWebServer(){return new TomcatWebServer();}@Bean@FireConditionalOnClass("org.eclipse.jetty.server.Server")public JettyWebServer jettyWebServer(){return new JettyWebServer();}
}

表示org.apache.catalina.startup.Tomcat存在,則有 tomcatWebServer 這個(gè)bean;
表示org.eclipse.jetty.server.Server存在,則有 jettyWebServer 這個(gè)bean;

FireSpringApplication#getWebServer()方法實(shí)現(xiàn):

public static WebServer getWebServer(ApplicationContext applicationContext){// key為beanName, value為Bean對(duì)象Map<String, WebServer> webServers = applicationContext.getBeansOfType(WebServer.class);if (webServers.isEmpty()) {throw new NullPointerException();}if (webServers.size() > 1) {throw new IllegalStateException();}// 返回唯一的一個(gè)return webServers.values().stream().findFirst().get();
}

這樣整體 SpringBoot 啟動(dòng)邏輯就是這樣的:

  1. 創(chuàng)建一個(gè) AnnotationConfigWebApplicationContext 容器
  2. 解析 MyApplication 類,然后進(jìn)行掃描
  3. 通過(guò) getWebServer 方法從 Spring 容器中獲取 WebServer 類型的 Bean
  4. 調(diào)用 WebServer 對(duì)象的 start 方法

發(fā)現(xiàn)自動(dòng)配置類

WebServiceAutoConfiguration 需要被 SpringBoot 發(fā)現(xiàn),可以通過(guò) SPI 機(jī)制實(shí)現(xiàn),比較 JDK 自帶的 SPI 來(lái)實(shí)現(xiàn)。

在 springboot 項(xiàng)目中的 resources 目錄下添加目錄META-INF/services和文件 org.example.springboot.AutoConfiguration,文件內(nèi)容為org.example.springboot.WebServiceAutoConfiguration。

接口:

public interface AutoConfiguration {
}

WebServiceAutoConfiguration 實(shí)現(xiàn)該接口:

@Configuration
public class WebServiceAutoConfiguration implements AutoConfiguration {@Bean@FireConditionalOnClass("org.apache.catalina.startup.Tomcat")public TomcatWebServer tomcatWebServer(){return new TomcatWebServer();}@Bean@FireConditionalOnClass("org.eclipse.jetty.server.Server")public JettyWebServer jettyWebServer(){return new JettyWebServer();}
}

再利用 spring 中的@Import技術(shù)來(lái)導(dǎo)入這些配置類,我們?cè)?code>@FireSpringBootApplication的定義上增加如下代碼:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
@Import(FireImportSelect.class)
public @interface FireSpringBootApplication {
}

FireImportSelect:

public class FireImportSelect implements DeferredImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {ServiceLoader<AutoConfiguration> serviceLoader = ServiceLoader.load(AutoConfiguration.class);List<String> list = new ArrayList<>();for (AutoConfiguration autoConfiguration : serviceLoader) {list.add(autoConfiguration.getClass().getName());}return list.toArray(new String[0]);}
}

如此,Spring 容器可以裝載 WebServiceAutoConfiguration 配置類了,對(duì)于 user 模塊而言,不需要修改代碼就可以自動(dòng)識(shí)別 Tomcat 和 Jetty 了。

總結(jié)

到此,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單版本的 SpringBoot,因?yàn)?SpringBoot 首先是基于 Spring 的,而且提供的功能也更加強(qiáng)大,后面會(huì)對(duì)這些功能進(jìn)行更深入的剖析。

http://www.risenshineclean.com/news/277.html

相關(guān)文章:

  • 網(wǎng)站程序前臺(tái)/西安百度競(jìng)價(jià)托管公司
  • 做網(wǎng)站待遇/什么是企業(yè)營(yíng)銷型網(wǎng)站
  • 做網(wǎng)站每頁(yè)面費(fèi)用/bing搜索引擎國(guó)際版
  • 企業(yè)網(wǎng)站建設(shè)話術(shù)/營(yíng)銷網(wǎng)站
  • wordpress pdf生成/手機(jī)端網(wǎng)站優(yōu)化
  • 工信部外國(guó)網(wǎng)站備案/b站在線觀看人數(shù)在哪
  • wordpress 時(shí)尚主題/駐馬店百度seo
  • 嘉興網(wǎng)站排名優(yōu)化價(jià)格/北京網(wǎng)站
  • 網(wǎng)站建設(shè)部門(mén)/網(wǎng)站軟件下載
  • 建立收費(fèi)網(wǎng)站/網(wǎng)絡(luò)銷售面試問(wèn)題有哪些
  • 做搞基視頻網(wǎng)站/網(wǎng)絡(luò)營(yíng)銷的案例有哪些
  • 網(wǎng)站怎么做下載連接/百度長(zhǎng)尾關(guān)鍵詞挖掘
  • 網(wǎng)站彈窗客服代碼/刷推廣鏈接
  • 政府網(wǎng)站公眾號(hào)建設(shè)方案/谷歌瀏覽器 安卓下載2023版
  • wordpress tutorial/seo優(yōu)化排名服務(wù)
  • 網(wǎng)站被谷歌降權(quán)/廣州seo招聘網(wǎng)
  • 網(wǎng)站聊天怎么做/最新軍事報(bào)道
  • 成都微信端網(wǎng)站建/蘇州seo按天扣費(fèi)
  • 網(wǎng)站沒(méi)有百度快照/全網(wǎng)絡(luò)品牌推廣
  • 制作企業(yè)網(wǎng)站需要注意的事項(xiàng)/地推是什么
  • 資料填寫(xiě)網(wǎng)站類型怎么做/新聞發(fā)稿公司
  • 免費(fèi)建網(wǎng)站撫順/win10優(yōu)化大師有用嗎
  • 萬(wàn)盛網(wǎng)站建設(shè)公司/當(dāng)下最流行的營(yíng)銷方式
  • 下載好看影視大全極速版/seo是什么工作內(nèi)容
  • 重慶響應(yīng)式網(wǎng)站建設(shè)公司/哪個(gè)軟件可以自動(dòng)排名
  • python源碼分享網(wǎng)站/深度搜索
  • 龍華網(wǎng)站建設(shè)方案表/免費(fèi)海報(bào)模板網(wǎng)站
  • 關(guān)鍵詞seo優(yōu)化/優(yōu)化大師官方免費(fèi)下載
  • 百度指數(shù) 網(wǎng)站/杭州優(yōu)化公司哪家好
  • 哈爾濱市建設(shè)網(wǎng)站/寧波網(wǎng)絡(luò)推廣產(chǎn)品服務(wù)