整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          SpringBootWeb容器配置:JAX-RS和Jersey框架、內(nèi)嵌容器的配置

          pring Boot Web容器

          Web應(yīng)用開發(fā)是企業(yè)開發(fā)的重要領(lǐng)域,Spring Boot 1.X的Web容器管理方式基于Servlet容器技術(shù)棧。Servlet容器主要基于同步阻塞I/O架構(gòu),HTTP請求和線程是一對一的關(guān)系,主要是TPR模型,即一個請求對應(yīng)一個線程。主要的業(yè)務(wù)邏輯也是基于命令式的編程模式。以Spring MVC框架為主,Web容器方面以Tomcat為主,也可以通過自動配置功能改為Jetty/UnderTow容器。

          Spring Boot 2.X主要基于異步非阻塞I/O架構(gòu),HTTP請求基于收斂的線程模型,網(wǎng)絡(luò)層使用基于Reactor的I/O多路復(fù)用模式,業(yè)務(wù)邏輯基于函數(shù)式編程模式,以Spring WebFlux為主要框架。在Web容器方面可以基于Servlet 3.0的異步模式,默認(rèn)情況下使用Netty作為容器。本節(jié)我們主要以Spring Boot 1.X講解嵌入式Web容器的啟動和加載原理,在進階篇的響應(yīng)式編程中將介紹Spring 5及Spring Boot 2.X的響應(yīng)式框架WebFlux對Web應(yīng)用服務(wù)的支持。

          Spring Boot Web容器配置

          Spring Boot對Web項目的支持主要是Spring Boot對Spring MVC框架的繼承。Spring MVC框架是一個基于Servlet容器標(biāo)準(zhǔn)的Web容器框架實現(xiàn),Spring Boot向Spring MVC提供開箱即用的Starter:springboot-starter-web。

          Spring Boot應(yīng)用中利用自動配置功能,只需要在pom.xml文件中加入下面的Web依賴,就可以直接啟動一個Web服務(wù):

          Spring Web MVC 框 架 使 用 特 定 的 @Controller 或 者@RestController 注 解 的 Bean 作 為 處 理 HTTP 請 求 的 端 點 , 通 過@RequestMapping注解將控制器中的方法與HTTP請求進行映射,示例如下:

          Spring Boot為Spring MVC提供了自動配置功能,包含如下主要配置特性。

          ● 自動配置ViewResolver引入ContentNegotiatingViewResolver組件功能。示例:在應(yīng)用中添加ViewResolver組件用來匹配HTML靜態(tài)頁面,如果沒有匹配成功,則返回false,由其他ViewResolver繼續(xù)嘗試匹配。ContentNegotiatingViewResolver會組合所有的視圖解析器,代碼如下。

          ● 自動注冊Converter、GenericConverter、Formatter Bean。

          示例:將頁面提交數(shù)據(jù)轉(zhuǎn)化為后臺數(shù)據(jù),實現(xiàn)格式化,代碼如下。

          ● 對HttpMessageConverters的支持。

          示例:Spring Boot可以為HttpMessageConverters類添加自定義轉(zhuǎn)換類,通過這種方式可以將所有的HttpMessageConverters的Bean添加到Converter列表,覆蓋默認(rèn)的轉(zhuǎn)換器列表,代碼如下。

          ● 自動注冊MessageCodeResolver。

          ● 自動使用ConfigurableWebBindingInitializer Bean。

          ● 使用WebMvcConfigurerAdapter類型的Bean來定制化配置。

          默認(rèn)情況下,Spring Boot會以/src/main/resources/static作為查找靜態(tài)資源的文件路徑,如果想自定義靜態(tài)資源映射目錄,需要重寫addResourceHandlers來添加指定路徑,重寫addResourceLocations來指定靜態(tài)資源路徑。

          總之,我們可以根據(jù)自己的意愿,對默認(rèn)的Spring MVC的組件配置加以修改,方法也很簡單,通過在IoC容器中注冊新的同類型Bean來替換即可。如果你希望完全接管Spring MVC的所有相關(guān)配置,可以添加自己的@Configuration,并使用@EnableWebMvc注解實現(xiàn)定制化配置。

          JAX-RS和Jersey框架

          如果你喜歡JAX-RS和REST風(fēng)格的編程模型,可以使用下面的Starter替代Spring MVC框架,Spring支持Jersey 1.X和Jersey 2.X等技術(shù)框架。這里我們只介紹Spring Boot對Jersey 2.X的支持,在pom.xml文件中加入下面的依賴:

          Spring Boot對Jersey的配置有三種主要方式。在開始不同的配置方式前,我們注冊一個端點對象資源,示例代碼如下:

          ● 第一種方式,創(chuàng)建一個自定義的ResourceConfig:

          ● 第二種方式,返回一個ResourceConfig類型的@Bean:

          ● 第三種方式,配置一組ResourceConfigCustomizer對象。

          Spring Boot提供了ResourceConfigCustomizer接口,讓我們更靈活地對ResourceConfig對象進行配置。要使用該接口,我們需要先注釋掉前面兩節(jié)中提到的相關(guān)代碼,然后創(chuàng)建一個類:

          默 認(rèn) 情 況 下 , Jersey 將 以 Servlet 的 形 式 注 冊 一 個

          ServletRegistrationBean 類 型 的 @Bean 。 它 的 名 字 為

          jerseyServletRegistration,該Servlet默認(rèn)會延遲初始化。

          你可以通過spring.jersey.servlet.load-on-startup自定義配置

          Jersey組件。通過創(chuàng)建相同名字的Bean,可以禁用或覆蓋框架默認(rèn)的

          Bean。設(shè)置spring.jersey.type=filter可以使用Filter的形式代替

          Servlet , 相 應(yīng) 的 @Bean 類 型 變 為 jerseyFilter-Registration , 該

          Filter有一個@Order屬性,你可以通過spring.jersey.filter.order

          設(shè) 置 該 屬 性 。 Servlet 和 Filter 在 注 冊 時 都 可 以 使 用

          spring.jersey.init.*定義一個屬性集合并將其傳遞給init參數(shù)進行

          初始化。

          內(nèi)嵌容器的配置

          Spring Boot 的 另 一 大 特 性 就 是 支 持 內(nèi) 嵌 的 Web 容 器 , 包 括Tomcat、Jetty和UnderTow服務(wù)器,大多數(shù)開發(fā)者只需要使用合適的Starter來獲取一個完全配置好的實例即可,內(nèi)嵌服務(wù)器默認(rèn)監(jiān)聽8080端口的HTTP請求。spring-boot-starter-web默認(rèn)使用Tomcat作為Web容器,你可以在pom.xml中去除spring-boot-starter-tomcat依賴,然后 引 入 spring-boot-starter-jetty 或 者 spring-boot-starterundertow模塊作為替代Web容器方案。Starter還提供了以“server.”為前綴的配置項對嵌入式容器配置進行修改。配置項的加載和定制化鉤子加載過程如下。

          1.自動化配置嵌入式容器

          2.初始化TomcatEmbeddedServletContainerFactory的Bean對象

          3.定制化Bean擴展邏輯

          EmbeddedServletContainerCustomizerBeanPostProcessor在加載Bean后開始初始化配置項PostProcessor的處理邏輯:

          4.配置文件加載

          從配置文件中,你可以加載配置文件對象的配置值。如果配置文件中沒有相關(guān)配置項,將使用默認(rèn)代碼設(shè)定配置。

          5.Web容器定制化

          如果你需要對Web容器進行更深入的定制,可以使用對應(yīng)的Factory自動化配置Tomcat容器,它是初始化的關(guān)鍵流程和步驟,代碼示例如下:

          下圖是Spring Boot啟動過程中Tomcat容器完成自動配置的類圖結(jié)構(gòu)。我們在最新的Spring Boot下查看Tomcat的相關(guān)配置,發(fā)現(xiàn)有兩個自動裝配類,分別包含了三個定制器,還有一個工廠類。

          本文給大家講解的內(nèi)容是SpringBootWeb容器配置:JAX-RS和Jersey框架、內(nèi)嵌容器的配置

          1. 下篇文章給大家講解的是Spring Boot嵌入式Web容器原理
          2. 覺得文章不錯的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
          3. 感謝大家的支持!

          開發(fā)Web應(yīng)用程序時,經(jīng)常需要進行一些全局性的配置,例如添加攔截器、設(shè)置消息轉(zhuǎn)換器、配置跨域資源共享(CORS)等。在Spring WebFlux中,我們可以通過實現(xiàn)WebFluxConfigurer接口來進行這些全局配置。本文將詳細(xì)介紹如何使用WebFluxConfigurer進行全局配置,以及常見的配置項和實現(xiàn)方式。

          全局配置接口

          WebFluxConfigurer是Spring WebFlux框架中用于配置WebFlux全局特性的接口,它提供了多個方法用于配置不同的功能。

          public interface WebFluxConfigurer {
          
              default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {}
          
              default void addFormatters(FormatterRegistry registry) {}
          
              default void configureViewResolvers(ViewResolverRegistry registry) {}
          
              default void addArgumentResolvers(ArgumentResolverConfigurer configurer) {}
          
              default void addReturnValueHandlers(ReturnValueHandlerConfigurer configurer) {}
          
              default void configureHandlerExceptionResolvers(HandlerExceptionResolverConfigurer configurer) {}
          
              default void addInterceptors(InterceptorRegistry registry) {}
          
              default void addCorsMappings(CorsRegistry registry) {}
          
              default void configurePathMatching(PathMatchConfigurer configurer) {}
          
              default void configureWebSocketTransport(WebSocketTransportConfigurer configurer) {}
          
              default void configureWebSocketHandlerMapping(WebSocketHandlerMappingConfigurer configurer) {}
          
              default void configureHttpMessageReader(ServerHttpMessageReaderConfigurer configurer) {}
          
              default void configureHttpMessageWriter(ServerHttpMessageWriterConfigurer configurer) {}
          
              default void configureClientHttpRequestFactory(ClientHttpConnectorConfigurer configurer) {}
          
              default void addResourceHandlers(ResourceHandlerRegistry registry) {}
          
              default void configureServerSentEvent(ServerSentEventHttpMessageWriterConfigurer configurer) {}
          }

          在上述接口中,每個方法對應(yīng)一個特定的全局配置功能。接下來,我們將詳細(xì)介紹每個方法的作用和實現(xiàn)方式。

          配置消息編解碼器

          在WebFlux中,消息編解碼器(Message Codec)負(fù)責(zé)將請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為對象,并進行序列化和反序列化。可以通過configureHttpMessageCodecs方法來配置消息編解碼器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
                  configurer.customCodecs().encoder(new MyEncoder());
                  configurer.customCodecs().decoder(new MyDecoder());
              }
          }

          在上述示例中,我們通過configureHttpMessageCodecs方法添加了自定義的編碼器和解碼器,實現(xiàn)了對特定數(shù)據(jù)格式的處理。

          配置格式化器

          格式化器(Formatter)用于將字符串類型的數(shù)據(jù)轉(zhuǎn)換為特定類型的對象,例如將字符串轉(zhuǎn)換為日期對象。可以通過addFormatters方法來配置格式化器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addFormatters(FormatterRegistry registry) {
                  registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
              }
          }

          在上述示例中,我們通過addFormatters方法添加了日期格式化器,將日期字符串轉(zhuǎn)換為yyyy-MM-dd格式的日期對象。

          配置視圖解析器

          視圖解析器(View Resolver)用于將邏輯視圖名稱解析為實際的視圖對象,例如將Thymeleaf模板文件解析為HTML視圖。可以通過configureViewResolvers方法來配置視圖解析器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureViewResolvers(ViewResolverRegistry registry) {
                  registry.viewResolver(new ThymeleafViewResolver());
              }
          }

          在上述示例中,我們通過configureViewResolvers方法添加了Thymeleaf視圖解析器,用于解析Thymeleaf模板文件。

          配置參數(shù)解析器和返回值處理器

          在WebFlux中,參數(shù)解析器(Argument Resolver)用于將請求中的參數(shù)解析為控制器方法的參數(shù),而返回值處理器(Return Value Handler)用于將控制器方法的返回值處理為響應(yīng)數(shù)據(jù)。可以通過addArgumentResolversaddReturnValueHandlers方法來配置參數(shù)解析器和返回值處理器。

          配置參數(shù)解析器

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addArgumentResolvers(ArgumentResolverConfigurer configurer) {
                  configurer.addCustomResolver(new MyArgumentResolver());
              }
          }

          在上述示例中,我們通過addArgumentResolvers方法添加了自定義的參數(shù)解析器MyArgumentResolver

          配置返回值處理器

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addReturnValueHandlers(ReturnValueHandlerConfigurer configurer) {
                  configurer.addCustomHandler(new MyReturnValueHandler());
              }
          }

          在上述示例中,我們通過addReturnValueHandlers方法添加了自定義的返回值處理器MyReturnValueHandler

          配置異常處理器

          在Web應(yīng)用程序開發(fā)中,異常處理器(Exception Resolver)用于處理控制器方法中拋出的異常,并返回適當(dāng)?shù)捻憫?yīng)。可以通過configureHandlerExceptionResolvers方法來配置異常處理器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureHandlerExceptionResolvers(HandlerExceptionResolverConfigurer configurer) {
                  configurer.addExceptionHandler(new MyExceptionHandler());
              }
          }

          在上述示例中,我們通過configureHandlerExceptionResolvers方法添加了自定義的異常處理器MyExceptionHandler

          配置攔截器

          攔截器(Interceptor)用于在處理請求之前或之后執(zhí)行一些額外的邏輯,例如記錄請求日志、權(quán)限驗證等。可以通過addInterceptors方法來配置攔截器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addInterceptors(InterceptorRegistry registry) {
                  registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**");
              }
          }

          在上述示例中,我們通過addInterceptors方法添加了自定義的攔截器MyInterceptor,并指定了攔截路徑為/api/**

          配置跨域資源共享(CORS)

          跨域資源共享(Cross-Origin Resource Sharing,CORS)是一種用于解決跨域訪問問題的機制,可以通過addCorsMappings方法來配置CORS。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addCorsMappings(CorsRegistry registry) {
                  registry.addMapping("/api/**")
                          .allowedOrigins("*")
                          .allowedMethods("GET", "POST", "PUT", "DELETE")
                          .allowCredentials(true)
                          .maxAge(3600);
              }
          }

          在上述示例中,我們通過addCorsMappings方法配置了跨域訪問的規(guī)則,允許所有來源的請求訪問/api/**路徑,并指定了允許的方法、是否允許攜帶憑證以及最大緩存時間。

          配置路徑匹配規(guī)則

          路徑匹配規(guī)則(Path Matching)用于指定URL路徑與請求處理器的映射關(guān)系。可以通過configurePathMatching方法來配置路徑匹配規(guī)則。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configurePathMatching(PathMatchConfigurer configurer) {
                  configurer.setUseSuffixPatternMatch(false)
                            .setUseTrailingSlashMatch(false);
              }
          }

          在上述示例中,我們通過configurePathMatching方法配置了路徑匹配規(guī)則,禁用了后綴模式匹配和尾部斜杠匹配。

          總 結(jié)

          通過本文的詳細(xì)介紹,讀者應(yīng)該對如何使用WebFluxConfigurer進行全局配置有了更深入的了解。合理地進行全局配置可以提高開發(fā)效率,并確保應(yīng)用程序的穩(wěn)定性和可維護性。希望本文能夠幫助讀者更好地理解和應(yīng)用Spring WebFlux中的全局配置功能,為開發(fā)高效、靈活的Web應(yīng)用程序提供參考和指導(dǎo)。


          公眾號:九極客

          來源:blog.csdn.net/Gaowumao?type=blog


          難度分析

          雖然但是聽到這個消息的時候,內(nèi)心還是挺震驚的,畢竟是一個完整的管理系統(tǒng),功能界面還不能太過簡陋。而且從數(shù)據(jù)庫設(shè)計到整個系統(tǒng)的交付全由自己一人完成,挑戰(zhàn)效果直接拉滿!但是冷靜下來思考一下,其實也并不是很難,整體的項目流程即為:設(shè)計——>文檔——>編碼——>交付。整體的流程劃清之后,就開始一步步從無到有的實現(xiàn),沒想到到最后一步的時候,我竟然才用一天半的時間!!后面又用了半天的時間對整體的項目做了一個優(yōu)化處理!

          項目回顧

          最終效果演示:

          技術(shù)選型:

          • SpringBoot
          • Thymeleaf
          • Mybatis-Plus
          • MySQL
          • PageHelper
          • Lombok
          • Redis(后期頁面優(yōu)化使用)

          項目業(yè)務(wù)流程簡介

          登錄模塊、用戶模塊管理以及對用戶的角色分配,新聞公告模塊的管理、商品模塊(包括對商品、商品分類、訂單)的管理、角色模塊的管理;對于前端某資源是否有權(quán)限操作該資源,使用的是thymeleaf模板語法進行判斷鑒別以及文件上傳等基本功能。

          項目搭建(使用模板引擎)

          1. 首先創(chuàng)建Maven項目

          引入相應(yīng)的依賴,構(gòu)建所需文件目錄

          2. 編寫yaml配置文件

          server:
          port: 8080

          spring:
          datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/supplier?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
          username: root
          password: root
          # thymeleaf 配置
          thymeleaf:
          # 關(guān)閉緩存
          cache: false
          prefix: classpath:/templates/

          mybatis-plus:
          mapper-locations: classpath*:/mapper/**/*.xml

          3. 項目初期基本搭建

          在搭建一個項目的初期,為了讓系統(tǒng)顯得更規(guī)范化,我一般會提前做好基礎(chǔ)的配置和聲明,一個項目從開始設(shè)想時所涉及到技術(shù)以及這些技術(shù)對應(yīng)的一些基礎(chǔ)配置,都要提前規(guī)劃清楚(個人習(xí)慣)。比如:異常處理、攔截器、過濾器、常量類等等。

          ①異常處理

          @ControllerAdvice
          public class ExceptionHandler {

          private final org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());

          @org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
          public ModelAndView exception(HttpServletRequest request, Exception e ) throws Exception {
          logger.error("Request URL:{},Exception:{}",request.getRequestURL(),e);

          if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class )!= ){
          throw e;
          }

          ModelAndView mv = new ModelAndView();
          mv.addObject("url",request.getRequestURL());
          mv.addObject("exception",e);
          mv.setViewName("error/error");

          return mv;
          }
          }

          ② 攔截器

          攔截器主要是對一些資源做的處理,類似于某些資源需要用戶登錄后才能訪問的,某些是不需要的,比如:登錄功能就不需要有所攔截,而對用戶的各種管理就需要添加攔截操作,這樣才能使系統(tǒng)的安全性有所提高。

          登錄攔截

          public class LoginInterceptor extends HandlerInterceptorAdapter {

          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          if (request.getSession().getAttribute("user") == ){
          response.sendRedirect("/api");
          return false;
          }
          return true;
          }
          }

          資源放行

          @Configuration
          public class WebConfig extends WebMvcConfigurerAdapter {

          @Override
          public void addInterceptors(InterceptorRegistry registry) {
          registry.addInterceptor(new LoginInterceptor())
          .addPathPatterns("/api/**")
          .excludePathPatterns("/api","/api/doLogin");
          }
          }

          4. 編寫Controller前端控制器代碼

          首先創(chuàng)建一個FileController類

          ① 跳轉(zhuǎn)文件上傳的頁面

          //跳轉(zhuǎn)文件上傳的頁面
          @RequestMapping("/file-upload")
          public String userList(){
          return "file-upload";
          }

          ② 實現(xiàn)文件上傳的功能

          @RequestMapping("/doAddForUser")
          public String doAdd(User user, @RequestParam("file") MultipartFile files, HttpServletRequest request) throws IOException {
          //String path = ;
          if (files != && !files.isEmpty()){
          String name = UUID.randomUUID().toString().replace("-","");
          //獲取文件的擴展名
          String ext = FilenameUtils.getExtension(files.getOriginalFilename());
          //設(shè)置文件上傳的路徑
          String url =request.getSession().getServletContext().getRealPath("/upload/");

          File file = new File(url);
          if (!file.exists()){
          file.mkdir();
          }
          //測試路徑
          System.out.println(request.getServletPath()+ "/upload");
          System.out.println(request.getContextPath() + "/upload/");
          //以絕對路徑保存重命名后的文件
          files.transferTo(new File(url+"/"+name+"."+ext));
          user.setAvatar(request.getContextPath() + "/upload/"+name+"."+ext);
          }

          user.setId(UUID.randomUUID().toString());
          String salt = PasswordUtils.getSalt();
          String password = user.getPassword();
          String encode = PasswordUtils.encode(password, salt);
          user.setSalt(salt) ;
          user.setPassword(encode);
          user.setCreateTime(new Date());
          userService.save(user);
          return "redirect:/api/users";
          }

          注:如何想要實現(xiàn)多文件上傳需要更改的地方如下:

          ③ 實現(xiàn)多文件上傳功能

          在這個項目中并未實現(xiàn)多文件上傳功能

          private void commons(Object obj, @RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request) throws IOException {
          //String path = ;
          for (int i = 0; i < files.length; i++) {

          if (files[i] != && !files[i].isEmpty()){
          String name = UUID.randomUUID().toString().replace("-","");
          //獲取文件的擴展名
          String ext = FilenameUtils.getExtension(files[i].getOriginalFilename());
          //設(shè)置文件上傳的路徑
          String url =request.getSession().getServletContext().getRealPath("/upload/");

          File file = new File(url);
          if (!file.exists()){
          file.mkdir();
          }
          //測試路徑
          System.out.println(request.getServletPath()+ "/upload");
          System.out.println(request.getContextPath() + "/upload/");
          //以絕對路徑保存重命名后的文件
          files[i].transferTo(new File(url+"/"+name+"."+ext));

          if (i == 0){
          obj.setUrl1(request.getContextPath() + "/upload/"+name+"."+ext);
          }
          if (i == 1){
          obj.setUrl2(request.getContextPath() + "/upload/"+name+"."+ext);
          }
          if (i == 2){
          obj.setUrl3(request.getContextPath() + "/upload/"+name+"."+ext);
          }
          if (i == 3){
          obj.setUrl4(request.getContextPath() + "/upload/"+name+"."+ext);
          }
          if (i == 4){
          obj.setUrl5(request.getContextPath() + "/upload/"+name+"."+ext);
          }
          }
          }
          }

          5. 項目優(yōu)化

          對于前后端不分離的項目,多數(shù)使用的是頁面緩存優(yōu)化,當(dāng)系統(tǒng)某一瞬間遭受巨大流量時,當(dāng)?shù)谝粋€用戶進行頁面訪問時可以將該頁面數(shù)據(jù)進行緩存,這樣,后來的用戶訪問到的頁面都是從緩存中獲取的,這樣就減少了 對數(shù)據(jù)庫的操作,減輕了數(shù)據(jù)庫的壓力,從而達(dá)到優(yōu)化的處理。

          ① 導(dǎo)入依賴

          <!--Redis-->
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
          </dependency>
          <!--commons-pools2 對象池依賴-->
          <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-pool2</artifactId>
          </dependency>

          ② yaml配置

          ## Redis配置
          redis:
          # 服務(wù)器地址
          host: localhost
          # 端口
          port: 6379
          # 數(shù)據(jù)庫
          database: 0
          # 超時時間
          connect-timeout: 10000ms
          lettuce:
          pool:
          # 最大連接數(shù)
          max-active: 8
          # 最大連接阻塞等待時間 默認(rèn) -1
          max-wait: 10000ms
          # 最大空閑時間 默認(rèn)8
          max-idle: 200
          # 最小空閑連接 默認(rèn)8
          min-idle: 5

          ④ Redis序列化處理

          @Configuration
          public class RedisConfig {

          @Bean
          public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
          RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
          //key序列化
          redisTemplate.setKeySerializer(new StringRedisSerializer());
          //value序列化
          redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
          //hash類型key的序列化
          redisTemplate.setHashKeySerializer(new StringRedisSerializer());
          //hash類型value的序列化
          redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
          redisTemplate.setConnectionFactory(redisConnectionFactory);
          return redisTemplate;
          }
          }

          ③ 優(yōu)化處理

           @Autowired
          private NewsService newsService;
          @Autowired
          private RedisTemplate redisTemplate;
          @Autowired
          private ThymeleafViewResolver viewResolver;

          @RequestMapping(value = "/news",produces = "text/html;charset=utf-8")
          @ResponseBody
          public String roles(Model model, @RequestParam(value = "pageNo",defaultValue = "1")Integer pageNo
          , @RequestParam(value = "pageSize",defaultValue = "10")Integer pageSize
          , HttpServletRequest request, HttpServletResponse response){
          //Redis中獲取頁面,如果不為空,則直接返回頁面
          ValueOperations valueOperations = redisTemplate.opsForValue();
          String html = (String) valueOperations.get("news-list");
          if (!StringUtils.isEmpty(html)){
          return html;
          }
          PageHelper.startPage(pageNo,pageSize);
          List<News> list = newsService.list();
          PageInfo<News> pageInfo = new PageInfo<>(list);
          model.addAttribute("news",list);
          model.addAttribute("pageInfo",pageInfo);
          //如果為空,手動渲染,存入Redis中并返回
          WebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
          html = viewResolver.getTemplateEngine().process("news-list", context);
          if (!StringUtils.isEmpty(html)){
          //給緩存設(shè)置過期時間
          valueOperations.set("news-list",html,60, TimeUnit.SECONDS);
          }
          return html;
          }

          ④ Redis查看

          6. 注意事項

          注意@Controller和@RestController的區(qū)別,本項目使用的是模板渲染頁面,而@Controller就是用來響應(yīng)頁面的;而@RestController是用來返回Json

          在項目優(yōu)化階段需要在方法上添加注解@ResponseBody,因為我們是將整個頁面進行緩存 ,所以要將頁面轉(zhuǎn)換成JSON進行存儲。

          注入Thymeleaf解析器,將具體的 頁面進行解析成Json字符串進行存儲

          將存入Redis中的數(shù)據(jù)加上過期時間,因為頁面中的數(shù)據(jù)要和數(shù)據(jù)庫保持一致,如果用戶看到是幾十秒之前或一分鐘之前的數(shù)據(jù)還是勉強可以接受的。

          目前代碼已經(jīng)同步到Gitee:

          https://gitee.com/gao-wumao/supplier

          如果有需要的自行前去倉庫拉取


          主站蜘蛛池模板: 亚洲国产成人久久一区WWW | 亚洲第一区精品观看| 亚洲欧美国产国产综合一区| 色老板在线视频一区二区 | 3d动漫精品成人一区二区三| 日本一区二区三区在线网| 蜜桃无码AV一区二区| 一区二区三区美女视频| 国产乱码精品一区二区三区麻豆| 亚洲线精品一区二区三区影音先锋| 福利国产微拍广场一区视频在线 | 国产SUV精品一区二区四| 精品国产一区二区三区免费| 国产在线无码视频一区| 国产韩国精品一区二区三区久久| 国产一区二区视频在线观看| 午夜在线视频一区二区三区| 亚洲美女一区二区三区| 国产精品无码AV一区二区三区| 日韩一区二区在线观看| 色窝窝免费一区二区三区 | 成人毛片无码一区二区| 久久综合亚洲色一区二区三区| 亚洲无线码在线一区观看| 一区二区三区日本视频| 在线精品日韩一区二区三区| 亚洲综合在线一区二区三区| 色欲AV蜜臀一区二区三区| 亚洲一区二区三区偷拍女厕 | 国产日本亚洲一区二区三区| 久久91精品国产一区二区| 国产在线视频一区二区三区98| 人妻无码一区二区视频| 国产一区二区三区不卡在线看 | 亚洲午夜精品一区二区公牛电影院| 亚洲综合色自拍一区| 成人精品视频一区二区三区| 亚洲国模精品一区| 一区二区国产在线观看| 高清一区二区三区视频| 免费人人潮人人爽一区二区|