<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java Web 拾遺

      許是年紀(jì)大了,老是回憶起以前的點(diǎn)點(diǎn)滴滴。翻看當(dāng)初的代碼,如同偶遇多年未見(jiàn)的前女友,曾經(jīng)一起深入交流的情誼在頷首之間消散,令人煩躁。

      今天就來(lái)聊聊老生常談的 Java Web 開(kāi)發(fā)。緣于一個(gè)簡(jiǎn)單的Spring Boot項(xiàng)目改造,筆者看著一坨注解和配置,苦于拾掇記憶的痛苦,擇其一二記錄,紀(jì)念逝去的青春。

      本文對(duì)新手有一定幫助,大家笑過(guò)勿噴。

      JSP + JavaBean

      筆者學(xué)生時(shí)代接觸了JSP,作為遠(yuǎn)古產(chǎn)物,現(xiàn)在已難覓蹤跡,但與它一同出現(xiàn)的JavaBean,卻一直留傳了下來(lái)。

      在任何開(kāi)發(fā)模式下,都需要一套規(guī)范,JavaBean 就是符合這些規(guī)范的類(lèi)/對(duì)象,比如:

      • 所有字段為 private(不允許外部直接訪(fǎng)問(wèn),避免以后重命名/刪除等操作引發(fā)依賴(lài)故障)
      • 提供默認(rèn)構(gòu)造方法(方便外部實(shí)例化)
      • 提供 getter 和 setter(自定義屬性的讀寫(xiě)邏輯)
      • 實(shí)現(xiàn) serializable 接口(序列化支持)

      注意,JavaBean 不是 POJO,因?yàn)樗枰椒ā⑹录忍幚砗晚憫?yīng)業(yè)務(wù)。它包含所有的數(shù)據(jù)和業(yè)務(wù)邏輯,開(kāi)發(fā)時(shí)在 HTML 中嵌入后端代碼調(diào)用它們,如下所示:

      <%@ page language="java" import="java.util.*,com.cy.bean.*" pageEncoding="utf-8"%>
      <%
      String path = request.getContextPath();
      %>
      
      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
      <html>
        <head>
          <base href="<%=path%>">
        </head>
      
        <body>
          <%CheckUserBean cub=new CheckUserBean(); %>
        <jsp:useBean id="user" class="com.cy.bean.UserBean" scope="request"></jsp:useBean>
        <jsp:getProperty property="name" name="user"/>
        <jsp:setProperty property="password" name="user"/>
        <%if(cub.checkUser(user)) {%>
        <jsp:forward page="success.jsp"></jsp:forward>
        <%}else{%>
        <jsp:forward page="fail.jsp"></jsp:forward>
        <%} %>
        </body>
      </html>
      

      上述有 UserBean 和 CheckUserBean 兩個(gè) JavaBean,其中 UserBean 用于展示數(shù)據(jù)及接收用戶(hù)輸入,CheckUserBean 用于判斷用戶(hù)是否合法。

      后來(lái),JavaBean 的一些特征被開(kāi)發(fā)人員沿用下來(lái),同時(shí)概念簡(jiǎn)化為Bean,推廣至更多的框架。對(duì)大部分后起的語(yǔ)言(比如 C#)來(lái)說(shuō),因?yàn)橛?Java 幫忙踩的坑,它們往往在語(yǔ)言設(shè)計(jì)之初就提供了語(yǔ)言特性來(lái)更方便自然地貼合這些規(guī)范。

      Servlet

      JSP + JavaBean 的模式有一個(gè)明顯的缺點(diǎn),即隱性的頁(yè)面跳轉(zhuǎn)(數(shù)據(jù)流轉(zhuǎn)),提高了開(kāi)發(fā)過(guò)程中的出錯(cuò)概率,比如同一個(gè)頁(yè)面可能由多個(gè)不同頁(yè)面跳轉(zhuǎn)過(guò)來(lái),而相應(yīng)的數(shù)據(jù)結(jié)構(gòu)并不相同,開(kāi)發(fā)人員要考慮所有可能的情況,并提供相應(yīng)的 JavaBean 承接這些數(shù)據(jù)。同樣隨著業(yè)務(wù)發(fā)展,這種跳轉(zhuǎn)或數(shù)據(jù)結(jié)構(gòu)都會(huì)經(jīng)常發(fā)生變更,開(kāi)發(fā)維護(hù)成本極高。

      于是增加了Servlet(一般繼承自HttpServlet,該類(lèi)定義了幾個(gè)簡(jiǎn)單明了的方法,此處不贅述)來(lái)處理請(qǐng)求、填充 JavaBean/調(diào)用 JavaBean 方法、選擇返回哪個(gè)視圖等,并且加上了路由的配置,形成了基礎(chǔ)的MVC模式。

      路由的配置在web.xml中,如下:

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app>
          <!-- other configrations -->
      
          <!-- 聲明 servlet -->
          <servlet>
              <servlet-name>login</servlet-name>
              <servlet-class>com.cy.servlet.LoginServlet</servlet-class>
          </servlet>
          <!-- 路由配置 -->
          <servlet-mapping>
              <servlet-name>login</servlet-name>
              <url-pattern>/login</url-pattern>
          </servlet-mapping>
      
      </web-app>
      

      值得一提的是,出現(xiàn)了Filter(過(guò)濾器)的概念,即在 servlet 處理請(qǐng)求之前和返回響應(yīng)之后的中間處理器,可以提供與業(yè)務(wù)無(wú)關(guān)的通用功能,比如身份校驗(yàn)、限流、異常處理等。這種 AOP 理念非常好,也一直保留至今。

      同樣, Filter 也需要配置,如下:

      <web-app>
          <!-- other configrations -->
      
           <filter>
               <filter-name>jsp</filter-name>
               <filter-class>com.cy.filter.DemoFilter</filter-class>
           </filter>
           <filter-mapping>
               <filter-name>jsp</filter-name>
               <url-pattern>/*</url-pattern>
           </filter-mapping>
      
      </web-app>
      

      注意,Servlet 須運(yùn)行于 Servlet 容器(如Tomcat)中。

      Struts

      為了提高開(kāi)發(fā)效率,在 Servlet 基礎(chǔ)上,提供了一些通用模塊和工具,制定一套規(guī)范,形成一個(gè)框架,最知名的當(dāng)屬Struts,它有 1、2 兩個(gè)版本。這兩個(gè)版本并非簡(jiǎn)單的升級(jí),而是整個(gè)設(shè)計(jì)的更替。

      Struts1

      Struts1 使用一個(gè)單例核心ActionServlet接收所有請(qǐng)求,請(qǐng)求數(shù)據(jù)轉(zhuǎn)化為ActionForm,然后依據(jù)配置(struts-config.xml中的ActionMapping)分發(fā)給不同的Action。Action 一般只包含一個(gè) excute 方法用于處理業(yè)務(wù)。

      Struts1 很明顯的缺點(diǎn)導(dǎo)致現(xiàn)在基本沒(méi)人會(huì)去用:

      • 配置繁瑣
      • ActionServlet 單例模式,須考慮線(xiàn)程安全
      • 依賴(lài) Web 容器,單元測(cè)試不方便

      Struts2

      于是Struts2被推出。

      它使用Interceptor(攔截器) + Controller(即 Struts1 中的 Action)的模式,使得整個(gè)處理流程擴(kuò)展性大大提高了。

      同時(shí)它擯棄了單例模式,每次都會(huì)實(shí)例化新的 Controller 處理請(qǐng)求(其中可包含任意多的方法用以執(zhí)行不同業(yè)務(wù)),不用擔(dān)心線(xiàn)程安全問(wèn)題,缺點(diǎn)是并發(fā)量高的時(shí)候?qū)ο髮?shí)例激增內(nèi)存吃緊。

      框架借助本身的攔截機(jī)制,將請(qǐng)求和響應(yīng)數(shù)據(jù)映射為 POJO,實(shí)現(xiàn)了 Controller 對(duì)HttpServletRequestHttpServletResponse這樣的原生 Servlet 對(duì)象的剝離,即 Controller 不依賴(lài)于 Web 容器,可以方便地單元測(cè)試了。

      還記得上面 Servlet 的過(guò)濾器嗎,Struts2 攔截器和它的原理一樣,只不過(guò)前者面對(duì)所有請(qǐng)求,后者針對(duì)的是某個(gè)具體的 Controller。當(dāng)然,Struts2 同時(shí)使用了兩者。

      相比 Struts1,Struts2 有了質(zhì)的飛躍,然而沒(méi)過(guò)幾年,它的榮光也被后起之秀所掩蓋。

      Spring MVC

      說(shuō)起Spring MVC,不得不先說(shuō)說(shuō)Spring

      Spring

      Spring是 Java 平臺(tái)流行的 IOC 和 AOP 框架,雖然它本身不針對(duì)特定的使用場(chǎng)景,但是 Java 平臺(tái)的 Web 基因一開(kāi)始就影響著它,所以我們慣常使用它來(lái)開(kāi)發(fā)后端服務(wù)。Spring 官方有專(zhuān)門(mén)的子項(xiàng)目Spring Web,Spring MVC 就是 Spring Web 的子模塊。Spring Web 包含很多其它模塊,如Spring WebFlux、Spring Web Service、Spring WebSocket等。

      Java 后半程在移動(dòng)端大放異彩,有另一個(gè) IOC 框架Dagger在背后默默支持,可參看筆者寫(xiě)的
      從零開(kāi)始擼一個(gè)App-Dagger2
      ,此處不贅述。

      IOC

      我們可以通過(guò)在 XML 文件(使用ClassPathXmlApplicationContext加載)中配置 Bean,然后在代碼中使用@Autowired@Resource(來(lái)自 JSR-250,JDK 內(nèi)置)注入 Bean 實(shí)例(作用域可通過(guò)scope設(shè)置,默認(rèn)是單例)。

      XML 配置稍顯繁瑣,Sping2.5 開(kāi)始支持注解注入,只要在 XML 中配置<context:component-scan>(對(duì)應(yīng)的有@ComponentScan注解),Spring 便會(huì)自動(dòng)掃描指定包中的所有類(lèi),查找如@Component,@Service,@Repository,@Controller等注解修飾的類(lèi),并創(chuàng)建相應(yīng)的 Bean。當(dāng)然,這種方式只能配置本項(xiàng)目?jī)?nèi)的類(lèi)。

      為了使注解方式可以注入第三方類(lèi),從 3.0 開(kāi)始,Spring 引入了@Configuration。使用 @Configuration 注解修飾的類(lèi)(使用AnnotationConfigApplicationContext加載)中,可使用@Bean注解修飾返回 Bean 的方法。我們?nèi)粢獜?fù)用它處定義的配置類(lèi),可使用@Import注解,它的作用類(lèi)似于將多個(gè) XML 配置文件導(dǎo)入到單個(gè)文件。

      XML 配置和注解配置也可以混用,比如使用@ImportResource注解引入 XML 文件。

      AOP

      Spring 還是提供了 AOP 功能。

      AOP 分為靜態(tài) AOP 和動(dòng)態(tài) AOP。靜態(tài) AOP 是將切面代碼直接編譯到源代碼中,如 Java 平臺(tái)的AspectJ實(shí)現(xiàn);動(dòng)態(tài) AOP 是指將切面代碼運(yùn)行時(shí)動(dòng)態(tài)織入。Spring 的 AOP 為動(dòng)態(tài) AOP,實(shí)現(xiàn)的技術(shù)為 JDK 提供的動(dòng)態(tài)代理技術(shù)CGLIB(動(dòng)態(tài)字節(jié)碼增強(qiáng)技術(shù)),兩者區(qū)別如下:

      • JDK 動(dòng)態(tài)代理利用攔截器(必須實(shí)現(xiàn) InvocationHandler)加上反射機(jī)制生成一個(gè)代理接口的匿名類(lèi),在調(diào)用具體方法前調(diào)用 InvokeHandler 來(lái)處理;CGLIB 利用ASM框架,將目標(biāo)類(lèi)生成的 class 文件加載進(jìn)來(lái),通過(guò)修改其字節(jié)碼生成子類(lèi)來(lái)處理。
      • JDK 動(dòng)態(tài)代理的目標(biāo)類(lèi)必須實(shí)現(xiàn)某個(gè)接口,只有接口中的方法才能夠被代理;CGLIB 無(wú)此限制,但是因?yàn)椴捎玫氖抢^承模式,所以目標(biāo)類(lèi)或方法不能為 final。
      • 在 Java1.8 之后,大部分場(chǎng)景下,JDK 動(dòng)態(tài)代理的效率都要優(yōu)于 CGLIB。

      兩者盡管實(shí)現(xiàn)技術(shù)不一樣,但都是基于代理模式,都是生成一個(gè)代理對(duì)象。

      Spring 會(huì)根據(jù)目標(biāo)類(lèi)是否實(shí)現(xiàn)接口來(lái)決定使用 JDK 動(dòng)態(tài)代理還是 CGLIB,當(dāng)然在符合條件時(shí)也可以強(qiáng)制使用 CGLIB(<aop:aspectj-autoproxy proxyt-target-class="true"/>)。

      Spring AOP 涉及到的注解包括@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing、@Around、@EnableAspectJAutoProxy等,此處不詳述。


      Spring MVC 同樣是基于 Servlet,像是 IOC 版的 Struts2,當(dāng)然由于 IOC 的引入,兩者的概念和組件大相徑庭,但是處理請(qǐng)求的主干是一致的。

      Spring MVC 支持的頁(yè)面渲染實(shí)現(xiàn),并不包含 JSP。而是Thymeleaf、Freemarker等。

      Spring Boot

      最后來(lái)談?wù)?Spring Boot,它是建立在 Spring 之上的一個(gè)快速開(kāi)發(fā)框架,旨在簡(jiǎn)化 Spring 應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程。它通過(guò)提供默認(rèn)配置、Starter dependencies等特性,極大地減少了項(xiàng)目的配置工作。

      同樣的,它不獨(dú)屬于 Web 開(kāi)發(fā),但我們主要還是在 Web 領(lǐng)域使用它。

      @ConfigurationProperties

      在 Spring Boot 項(xiàng)目中,我們常將大量的參數(shù)配置在 application.properties(Spring) 或 application.yml 文件中,然后通過(guò)@Value取值,如下:

      @Value("${db.userName}")
      private String userName;
      

      其實(shí)通過(guò)@ConfigurationProperties注解,我們可以更清爽地獲取這些參數(shù)值:

      //@Component 注入
      @ConfigurationProperties(prefix="db")
      public class DbConfiguration{
        public String userName;
      }
      

      @ConfigurationProperties 并不表示成為 Spring Bean,除非配置類(lèi)同時(shí)標(biāo)注 @Component 之類(lèi)的注解,或者在使用方標(biāo)注@EnableConfigurationProperties注解(建議后者,即按需索取,而非全局可見(jiàn)):

      @EnableConfigurationProperties(DbConfiguration.class)
      public class Invoker{
      
          @Autowired
          DbConfiguration dbConfiguration;
      }
      

      spring.factories

      如果你正在編寫(xiě)一個(gè)基于 Spring 的類(lèi)庫(kù),其中很多對(duì)象都是以 Bean 的形式注入使用的,所以你當(dāng)然希望使用這個(gè)類(lèi)庫(kù)的第三方項(xiàng)目可以將這些對(duì)象事先加載到容器中。

      你可以在 ReadMe 中寫(xiě)明“XX 類(lèi)及 XXX 類(lèi) 及……必須在項(xiàng)目啟動(dòng)時(shí)實(shí)例化到容器中”,如此使用方知道他必須采用 XML 或 @Configuration 等方式寫(xiě)上一大段和業(yè)務(wù)無(wú)關(guān)的配置代碼。

      或者你可以使用 spring.factories 方案。spring.factories 其實(shí)是 Spring boot 提供的SPI機(jī)制,使用方的項(xiàng)目(需要在入口類(lèi)中標(biāo)注@EnableAutoConfiguration注解)會(huì)基于SpringFactoriesLoader檢索ClassLoader中所有 jar(包括ClassPath下的所有模塊)引入的META-INF/spring.factories文件,基于文件中的接口自動(dòng)加載對(duì)應(yīng)的 @Configuration 修飾的類(lèi)并且注冊(cè)到容器中。

      spring.factories 為模塊化、配置化提供了基石,我們經(jīng)常引用的諸如“xxx-spring-boot-starter”的類(lèi)庫(kù),基本上就是使用了該方案。

      ps:自 Spring Boot 3.0 始,由META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports替代 META-INF/spring.factories,內(nèi)容格式有所變化,原理不變。

      Spring Boot 3.0 是一個(gè)比較大的改版,影響最大的改動(dòng)是必須使用 JDK17 及以上版本。


      由于我們常將 @ComponentScan、@SpringBootConfiguration(同 @Configuration)、@EnableAutoConfiguration 一起使用,Spring Boot 干脆出了一個(gè)@SpringBootApplication注解,將三者合一。


      Spring Boot 對(duì) AOP 的使用進(jìn)行了一些改動(dòng),此處不贅述。

      內(nèi)置常見(jiàn)的服務(wù)器(如 Tomcat、Jetty),無(wú)需單獨(dú)部署。


      Spring Boot 雖然是一個(gè)非常成熟的拆箱即用框架,但在微服務(wù)場(chǎng)景下就顯得過(guò)于笨重了。后續(xù)有緣的話(huà)筆者會(huì)再來(lái)聊聊 Java 平臺(tái)更適合微服務(wù)運(yùn)行的幾個(gè)框架。

      posted @ 2024-09-25 10:35  萊布尼茨  閱讀(658)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产太嫩了在线观看| 国产一区日韩二区欧美三区| 日韩中文字幕免费在线观看| 人妻中文字幕亚洲一区| 国产精品久久久久久久久人妻| 99热久久这里只有精品| 国产伦一区二区三区久久| 亚洲产国偷v产偷v自拍色戒| 99福利一区二区视频| 在线观看国产成人av片| 日本深夜福利在线观看| 亚洲18禁一区二区三区| 国产精品美女一区二区三| 国产偷国产偷亚洲综合av| 不卡在线一区二区三区视频| 亚洲国产精品一二三区| 免费国产拍久久受拍久久| 久久久欧美国产精品人妻噜噜 | 国产69精品久久久久99尤物| 麻豆蜜桃av蜜臀av色欲av| 中文字幕一区日韩精品| 久久蜜臀av一区三区| 国产成人无码区免费内射一片色欲| 欧美www在线观看| 亚洲中文字幕国产综合| 蜜臀av午夜精品福利| 亚洲蜜桃av一区二区三区| 中文字幕av无码不卡| 免费无码又爽又刺激成人| 国产亚洲视频免费播放| 免费AV片在线观看网址| 亚洲老妇女亚洲老熟女久| 玩弄放荡人妻少妇系列| 一本精品中文字幕在线| 精品无码成人片一区二区| 亚洲日本国产精品一区| 巨胸不知火舞露双奶头无遮挡| 亚洲av无码精品色午夜蛋壳| 国产高清精品在线91| 国产普通话对白刺激| a男人的天堂久久a毛片|