Spring MVC官方文檔學習筆記(二)之DispatcherServlet

来源:https://www.cnblogs.com/shame11/archive/2023/05/31/17392835.html
-Advertisement-
Play Games

1. 多線程程式在一個核的CPU運行 ![image.png](https://cdn.nlark.com/yuque/0/2023/png/35902537/1685453577663-714d9c16-e8a3-4828-bb86-86dfa10c8e52.png#averageHue=%23f ...


1.DispatcherServlet入門

(1) Spring MVC是以前端控制器模式(即圍繞著一個中央的Servelt, DispatcherServlet)進行設計的,這個DispatcherServlet為請求的處理提供了一個共用的演算法,即它都會將實際的請求處理工作委托給那些可配置的組件進行執行,說白了,DispatcherServlet的作用就是進行統一調度,並控制請求的處理流程,和其他的Servlet一樣,DispatcherServlet需要根據Servlet規範,使用基於Java的配置或在web.xml中進行聲明,與此同時,DispatcherServlet會使用Spring相關配置來發現它在請求映射、視圖解析、異常處理等方面所需要的組件,而實際的工作也會交由這些組件進行執行,下麵列出了註冊DispatcherServlet的一些方式

@Configuration
@ComponentScan("cn.example.springmvc.boke")
public class WebConfig {
}

//使用基於Java的配置,註冊並初始化一個DispatcherServlet
public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //聲明一個Spring-web容器
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(WebConfig.class);

        //創建並註冊DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ctx);
        //動態的添加Servlet
        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet", servlet);
        registration.setLoadOnStartup(1);
        //指定由DispatcherServlet攔截所有請求(包括靜態資源,但不攔截.jsp)
        registration.addMapping("/");
    }
}

上述是基於Java的配置,我們還可以基於web.xml來配置DispatcherServlet,如下

<web-app ....>
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

(2) 現在DispatcherServlet有了,我們還需要@Controller與@RequestMapping註解,來標註某個訪問應該由誰進行處理,如下,而到此為止,我們就已經完全不需要編寫HttpServlet相關的內容了,可見通過DispatcherServlet幫助我們免去了冗雜的Servlet映射配置

@Controller
public class DemoController {
    @RequestMapping("/demo")
    @ResponseBody
    public String get(HttpServletRequest request) {
        return "aaa";
    }
}

啟動容器,訪問 http://localhost:8080/springmvc/demo, 頁面顯示aaa,說明訪問正常,這便是我們的第一個Spring MVC項目

2.Spring容器的層次結構

(1) 根容器與Servlet子容器

通常情況下,一個web應用中有一個唯一的WebApplicationContext容器就足夠了,但Spring還允許我們配置具有父子關係的根容器和它的Servlet子容器,來形成一個層次結構,如上圖所示,可以很清楚的看到,Spring將表示層相關的組件全部放到了子容器中,而將公共的與基礎服務有關的組件全部放到了根容器中,這樣的話,當我們需要註冊多個DispatcherServlet並共用那些基礎服務組件的時候,不必重覆註冊Service和Dao了,因為每個Servlet子容器都可以從這個根容器中獲取到Service和Dao,這便是層次結構的意義

當然,Spring也支持單容器配置,如開頭中的示例那樣,此外我們可以通過繼承AbstractAnnotationConfigDispatcherServletInitializer來配置父子容器,如下

//配置父子容器,其中容器使用基於註解的配置方式
public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //配置 DispatcherServlet 攔截的路徑
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    //設置根容器的配置類
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }

    //設置子容器的配置類
    //如果不想形成父子容器,那麼只需將下麵這個getServletConfigClasses()方法返回null即可
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }
}

//由於我們採用的是父子容器,因此這就要求我們編寫父子容器的配置文件時,根容器的配置文件(RootConfig)配置非web組件的bean,而子容器的配置文件(WebConfig)配置web組件的bean,同時,也要防止同一組件在不同容器中分別註冊初始化,從而出現兩個相同bean
//根容器配置類,使用excludeFilters排除掉@Controller註解標註的類和@Configuration註解標註的類,這裡之所以要排除掉@Configuration註解標註的類,是為了防止根容器掃描到子容器的配置類WebConfig
@Configuration
@ComponentScan(value = "cn.example.springmvc.boke",
                excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class),
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)
                })
public class RootConfig {
}

//子容器配置類,使用includeFilters指定只掃描由@Controller註解標註的類
@Configuration
@ComponentScan(value = "cn.example.springmvc.boke",
        includeFilters = @ComponentScan.Filter(value = Controller.class, type = FilterType.ANNOTATION))
public class WebConfig {
}

也可以基於web.xml來配置父子容器,如下

<web-app ....>
    <!-- ContextLoaderListener用於配置根容器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 設置根容器的xml配置文件路徑 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springroot.xml</param-value>
    </context-param>

    <!-- DispatcherServlet用於配置子容器 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 設置子容器的xml配置文件路徑 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springweb.xml</param-value>
        </init-param>
    </servlet>
    
    <!-- 設置 DispatcherServlet 攔截的路徑  -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3.特殊類型的bean

(1) 前面已經提過了,DispatcherServlet會將實際的請求處理過程委托給那些特殊的組件來乾,而它本身起一個統一分配與調度的作用,這些特殊的組件已經由Spring提供了預設的實現,但同時Spring也允許我們自己實現替換它們,下表列出了由 DispatcherServlet檢測到的這些特殊的Bean類型

Bean類型 說明
HandlerMapping 處理器映射器,主要就是將請求路徑(uri)映射到能處理該請求的處理器(handler),DispatcherServlet在接收到請求後,該請求會交由誰來處理?這個匹配查找的工作不是由DispatcherServlet來做的,而是交由HandlerMapping負責的,而至於Handler,我們可以把它理解為在@Controller註解所標註的類中的一個標註了@RequestMapping註解的方法,所謂的匹配本質上就是匹配@RequestMapping註解中所聲明的值罷了。註意:HandlerMapping在查找匹配到對應的Handler後,並不是直接返回這個Handler,而是返回這個Handler的包裝對象HandlerExecutionChain,而這個HandlerExecutionChain其實就是 Handler + 該請求所涉及到的攔截器 所組合而成的一個對象。
兩個主要的HandlerMapping實現類分別是RequestMappingHandlerMapping(標註了@RequestMapping註解的方法)和SimpleUrlHandlerMapping(若在xml中顯式的配置了請求路徑與Controller的對應關係,則會使用該處理器映射器)
HandlerAdapter 幫助 DispatcherServlet 調用映射匹配到的HandlerExecutionChain,換句話說,DispatcherServlet獲得HandlerExecutionChain後,它不會進行調用執行,而是交由HandlerAdapter來調用執行HandlerExecutionChain
HandlerExceptionResolver 解決異常的策略,用於定義在請求映射,參數綁定或方法執行時若發生異常,該怎麼處理
ViewResolver Handler方法執行後,將返回的邏輯視圖名(通常為一個String字元串)解析為真正的視圖(如.jsp 、.html等),併進行視圖渲染,渲染完成後,將視圖返回給DispatcherServlet
LocaleResolver, LocaleContextResolver 用於解析客戶的Locale,實現國際化功能
ThemeResolver 解析你的web應用可使用的主題(theme),主題是一系列靜態資源的集合(比如說css文件,圖片等)
MultipartResolver 專門用於處理文件上傳
FlashMapManager 專門用於保存和管理FlashMap,而這個FlashMap是用來在重定向時傳遞參數的,因為redirect重定向是不能傳遞參數的,此時就可以藉助FlashMap

4.Web MVC配置

(1) 我們可以自定義在上一節中所列出來的那些特殊的bean,DispatcherServlet會檢查它們,如果沒有,那麼它將會使用DispatcherServlet.properties中所列出的預設類型的bean,如下

5.Servlet 配置

(1) 在Servlet環境中,我們可以選擇以編程式的方式或基於web.xml的方式來配置Servlet容器,在本篇開頭的位置也提到過了,如下是一個基於編程式的例子

public class IocInit implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //創建一個基於xml配置的容器
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("classpath:springmvc.xml");

        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

WebApplicationInitializer是由Spring MVC提供的一個介面,Spring MVC會確保該介面的實現類們會被正確調用以初始化Servlet容器,WebApplicationInitializer有一個抽象基類為AbstractDispatcherServletInitializer,通過繼承該基類可以使得註冊DispatcherServlet更加容易

(2) 除了上面的例子之外,還可以使用基於java的Spring配置,如下,前面也提到過了

public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    //創建一個基於註解配置的容器
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }
}

(3) 除此之外,還可以繼承AbstractDispatcherServletInitializer

public class IocInit extends AbstractDispatcherServletInitializer {
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("classpath:springmvc.xml");
        return cxt;
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }
}

上面列出了常見的3種創建ioc容器的方式,我們可以根據自己的需要來進行選擇

(4) AbstractDispatcherServletInitializer還提供了一種便捷的方式來創建Filter實例,並且這些Filter實例會被自動映射到DispatcherServlet上,如下

public class IocInit extends AbstractDispatcherServletInitializer {

    //...
    
    //這些Filter會被自動映射到DispatcherServlet上,並且會根據它們的類型來為其添加一個預設名稱
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
                new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}

此外,如果我們希望需要進一步的定製DispatcherServlet,我們可以重寫createDispatcherServlet方法

6.請求處理

(1) DispatcherServlet按照如下的方式來處理請求:

  • 搜索WebApplicationContext並將其作為一個屬性綁定到請求中,這樣在請求的後續處理過程中我們就可以直接從請求中拿到ioc容器,如下
@Controller
public class DemoController {
    @RequestMapping("/demo")
    @ResponseBody
    public String get(HttpServletRequest httpServletRequest) {
        //從請求中獲取到WebApplicationContext,這個ioc容器被綁定到了請求的DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE屬性上
        WebApplicationContext ctx = (WebApplicationContext)httpServletRequest.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
        return "aaa";
    }
}
  • Locale解析器也被綁定到了請求上,以便後續處理流程中進行使用

  • Theme解析器也被綁定到了請求上,以便後續處理流程中進行使用

  • 如果我們指定了multipart文件解析器,那麼Spring會檢查請求中是否含有multipart文件,如果有,那麼該請求會被包裹在一個MultipartHttpServletRequest中,以便後續處理流程中進行進一步處理

  • 針對請求搜索恰當的handler,如果搜索到的話,與該handler相關的執行鏈(HandlerExecutionChain)將會被執行,以準備渲染模型(model)

  • 如果有模型返回,那麼視圖(view)就會被渲染,否則,如果沒有模型返回,那麼視圖就不會被渲染

(2) 在WebApplicationContext中的HandlerExceptionResolver類型的bean將被用來解決請求處理過程中拋出的異常,這些異常解析器允許自定義處理異常的邏輯

(3) 我們可以在web.xml中的標簽使用標簽來添加Servlet初始化參數,這樣就能達到定製DispatcherServlet的目的,下麵列出了DispatcherServlet常見的初始化參數

參數 說明
contextClass 設置web容器,該容器必須是ConfigurableWebApplicationContext的實現類,預設為XmlWebApplicationContext
contextConfigLocation 該參數值將會被傳遞至由上面contextClass指定的容器,通常用於指明配置文件(xml文件,@Configuration註解標註的類)的路徑,容器會到指定位置載入配置文件
namespace 容器的命名空間,預設為[servlet-name]-servlet
throwExceptionIfNoHandlerFound 決定當一個請求沒有找到其對應的handler時,是否會拋出NoHandlerFoundException異常,若設置為true,則表示拋出異常,然後我們就可以用HandlerExceptionResolver來捕獲該異常,並像處理其他異常一樣進行該處理。在預設情況下,該值被設置為false,因此在預設情況下,如果一個請求沒有找到其對應的handler,那麼DispatcherServlet會將響應狀態碼設置為404(NOT_FOUND)而不會引發異常,因此我們會在頁面上看到一個 "404 - 未找到" 頁面,最後註意,如果defaultServletHandling也被配置了,那麼這些不正常的請求會被轉發到defaultServlet進行處理,且永遠不會出現404

具體的配置例子如下

<web-app ....>

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置容器,容器需要實現ConfigurableWebApplicationContext介面,此處我們選擇了XmlWebApplicationContext,這也是Spring的預設配置 -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.XmlWebApplicationContext</param-value>
        </init-param>

        <!-- 因為我們上面選用的是XmlWebApplicationContext,一個基於xml配置的容器,因此通過contextConfigLocation屬性來設置容器的xml配置文件路徑 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springweb.xml</param-value>
        </init-param>

        <!-- 如下是配置一個基於註解的容器 -->
<!--        <init-param>-->
<!--            <param-name>contextClass</param-name>-->
<!--            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>-->
<!--        </init-param>-->
        <!-- 因為是基於註解的容器,因此通過contextConfigLocation屬性來設置Configuration配置類的路徑 -->
<!--        <init-param>-->
<!--            <param-name>contextConfigLocation</param-name>-->
<!--            <param-value>cn.example.springmvc.boke.config.Config</param-value>-->
<!--        </init-param>-->

        <!-- 設置WebApplicationContext的命名空間 -->
        <init-param>
            <param-name>namespace</param-name>
            <param-value>app</param-value>
        </init-param>

        <!-- 註意,單單將這個值設置為true,並不會生效(即不會拋出NoHandlerFoundException異常),原因是Spring會預設加上ResourceHttpRequestHandler這個handler來進行處理,也就不會出現no handler的情況了,因此我們還需要配置spring.resources.add-mappings=false,這樣在發生no handler時才會拋出NoHandlerFoundException異常 -->
        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <!-- 設置 DispatcherServlet 攔截的路徑  -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

7.攔截器

(1) 攔截器必須實現HandlerInterceptor介面,該介面提供了3個方法,分別為

  • preHandle(..): 在handler執行之前執行

  • postHandle(..): 在handler執行之後執行

  • afterCompletion(..): 在整個請求完成後執行

preHandle方法返回一個boolean值,通過該方法我們可以決定是繼續還是中斷執行鏈的執行,若返回true,則執行鏈繼續執行,若返回false,則DispatcherServlet會認為攔截器本身已經處理了該請求,因此會中斷執行鏈中其他的攔截器以及handler的執行

postHandle方法在有@ResponseBody和ResponseEntity的方法中用處不大,因為這種方法在postHandle方法執行前已經在寫入response了,等待postHandle方法執行時已經太遲了,而針對這種情況,我們可以使用ResponseBodyAdvice

8.異常

(1) 如果在請求映射處理過程中發生異常,DispatcherServlet會委托一個由HandlerExceptionResolver構成的異常處理鏈來處理這個異常,下麵列出一些可用的HandlerExceptionResolver實現類

HandlerExceptionResolver 說明
SimpleMappingExceptionResolver 提供異常類名稱與異常視圖名稱之間的一個映射,即針對不同類型的異常響應不同的錯誤視圖
DefaultHandlerExceptionResolver 解析由Spring MVC引發的標準異常,並將它們映射成對應的HTTP狀態碼,它是作為“預設”使用的,如果其他HandlerExceptionResolver不能處理某些異常,最後會使用DefaultHandlerExceptionResolver來統一處理
ResponseStatusExceptionResolver 解析被@ResponseStatus註解標註的異常,並根據註解中的值將異常映射到對應的HTTP狀態碼
ExceptionHandlerExceptionResolver 通過調用@ControllerAdvice類或@Controller類中合適的@ExceptionHandler方法來解析異常

(2) 我們可以在容器中配置多個HandlerExceptionResolver類型的bean並根據需要設置它們的order屬性來形成一個異常處理器鏈,其中order屬性值越高,它在異常處理器鏈中的位置就越靠後,通常情況下,HandlerExceptionResolver返回

  • 一個指向錯誤視圖的ModelAndView

  • 若異常在處理器中被處理,返回一個空的ModelAndView

  • 若異常未被解決,則返回null,以便讓後續的處理器嘗試解決,如果到最後異常仍未解決,則允許將異常冒泡到Servlet容器中

使用MVC Config(通過@EnableWebMvc註解)後,會自動的向容器中添加Spring MVC異常,由@ResponseStatus註解標註的異常等異常的處理器,我們可以對它們進行替換

(3) 如果一個異常沒有被任何HandlerExceptionResolver處理或者請求的http響應被設置為錯誤狀態(即4xx,5xx),那麼Servlet容器使用HTML來渲染一個預設的錯誤頁面,而為了自定義容器的預設錯誤頁面,我們可以在web.xml中配置錯誤頁面映射url,如下

<error-page>
    <location>/error</location>
</error-page>

當配置好錯誤頁面映射url後,如果此時有一個異常沒有被任何HandlerExceptionResolver處理或者請求的http響應被設置為錯誤狀態,那麼Servlet容器將會請求我們所配置的這個url,此時,我們就可以返回一個自定義的錯誤視圖或像下麵這樣直接返回一個字元串

@RequestMapping("/error")
@ResponseBody
public String error() {
    return "error";
}

9. view,locale,theme和logging這四節的內容略過,如果有需要可查看官方文檔

10. Multipart解析器

(1) org.springframework.web.multipart包中的MultipartResolver可用於解析multipart類型(例如:文件上傳)的請求,為了使用Multipart解析器,我們需要配置一個MultipartResolver類型的bean,並且這個bean的名稱必須是multipartResolver,配置好之後,DispatcherServlet會檢測到它並將其應用於後續的請求,當我們接收到一個類型為multipart/form-data的post請求時,Multipart解析器會解析請求內容並將當前這個HttpServletRequest包裝成MultipartHttpServletRequest以便訪問解析的內容,Spring MVC已為我們提供了兩個MultipartResolver的實現類,如下

  • CommonsMultipartResolver:基於Apache Commons FileUpload的MultipartResolver實現類,為了使用它,需要添加commons-fileupload依賴

  • StandardServletMultipartResolver:基於Servlet 3.0 multipart請求解析的MultipartResolver實現類,為了使用它,我們需要在<web.xml/>或Servlet registration中進行一些配置:

<!-- 在web.xml的<servlet/>標簽中添加<multipart-config/>標簽,配置上傳文件的大小等信息 -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <multipart-config>
        <location>/</location>
        <max-file-size>2097152</max-file-size>
        <max-request-size>419304</max-request-size>
    </multipart-config>
</servlet>

也可在Servlet registration中進行配置

public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }

    //使用ServletRegistration配置上傳文件大小等信息
    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setMultipartConfig(new MultipartConfigElement("/", 2097152, 419304, 0));
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ### 外觀式定義 為子系統中的一組介面提供一個一致的界面,Facade 模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。 #### 界面 在這裡提到的界面,主要指的是從一個組件外部來看這個組件,能夠看到什麼,這就是這個組件的界面,也就是所說的外觀。 #### 介面 在這裡提到的介面,主 ...
  • # 前言 本文主要講述**工廠模式**,文中使用通俗易懂的案例,使你更好的學習本章知識點並理解原理,做到有道無術。 # 一.什麼是工廠模式 工廠模式是23種設計模式中**創建型模式**的一種,它是一個最簡單的對象創建管理方式,根據調用方傳遞的類型來創建對象並返回。封裝了對象創建的過程,降低了程式模塊 ...
  • ### 解釋器模式(Interpreter Pattern) #### 一、定義 解釋器模式(Interpreter Pattern)提供了評估語言的語法或表達式的方式,它屬於行為型模式。這種模式實現了一個表達式介面,該介面解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。 給定一 ...
  • 在Java中,序列化(Serialization)是指將對象的狀態轉換為位元組流的過程,以便將其保存到文件、在網路中傳輸或持久化到資料庫中。而反序列化(Deserialization)則是將位元組流轉換回對象的過程,恢復對象的狀態。 序列化和反序列化主要用於以下場景: 1. 對象持久化:通過序列化,可以 ...
  • > 內容摘自我的學習網站:topjavaer.cn Redis連環40問,絕對夠全! ## Redis是什麼? Redis(`Remote Dictionary Server`)是一個使用 C 語言編寫的,高性能非關係型的鍵值對資料庫。與傳統資料庫不同的是,Redis 的數據是存在記憶體中的,所以讀寫 ...
  • > 本文首發於公眾號:Hunter後端 > 原文鏈接:[Python連接es筆記四之創建和刪除操作](https://mp.weixin.qq.com/s/ZCe0JT9TDEiZI7M5dxC9qA) 這一篇筆記介紹一下索引和數據的創建和刪除。 其實對於索引來說,如果可以接觸到 kibana 的話 ...
  • > 源碼都背下來了,你給我看這 **我是 javapub,一名 `Markdown` 程式員從👨‍💻,八股文種子選手。** **面試官: 你好,我看到你的簡歷上寫著你熟悉 Java 中的 "synchronized" 關鍵字。你能給我講講它的作用嗎?** **候選人:** 當然,"synchro ...
  • # 1. Netty總體結構 ## 1.1 Netty簡介 ​ Netty是一款用於創建高性能網路應用程式的高級框架。它的基於 Java NIO 的非同步的和事件驅動的實現,保證了高負載下應用程式性能的最大化和可伸縮性。 ​ 其次,Netty 也包含了一組**設計模式**,將應用程式邏輯從網路層解耦, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...