溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

發(fā)布時(shí)間:2021-08-14 14:45:55 來(lái)源:億速云 閱讀:1210 作者:chen 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器”吧!

目錄
  • 使用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

    • Converter接口

    • 添加依賴(lài)

    • 實(shí)體類(lèi)

      • 1.User類(lèi)

      • 2.Article類(lèi)

    • 配置類(lèi)型轉(zhuǎn)化器

      • 1.定義全局日期轉(zhuǎn)換器

      • 2.定義全局對(duì)象轉(zhuǎn)換器

      • 3.定義全局List類(lèi)型轉(zhuǎn)換器

    • 控制器

      • 測(cè)試

      • Converter使用及其原理

        • 配置文件中對(duì)Converter的引用

          • 以字符串去空為例

            • 我們查看Converter接口的源碼

              • 我們查看對(duì)應(yīng)的成員變量:

              使用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

              在Spring3中引入了一個(gè)Converter接口,它支持從一個(gè)Object轉(zhuǎn)為另一個(gè)Object。除了Converter接口之外,實(shí)現(xiàn)ConverterFactory接口和GenericConverter接口也可以實(shí)現(xiàn)我們自己的類(lèi)型轉(zhuǎn)換邏輯。

              Converter接口

              首先看看Converter接口的定義

              public interface Converter<S, T> {       
                  T convert(S source);     
              }

              可以看到這個(gè)接口是使用了泛型的,S表示原類(lèi)型,T表示目標(biāo)類(lèi)型,然后里面定義了一個(gè)convert方法,將原類(lèi)型對(duì)象作為參數(shù)傳入進(jìn)行轉(zhuǎn)換之后返回目標(biāo)類(lèi)型對(duì)象。

              下面在Spring Boot中使用Converter接口來(lái)實(shí)現(xiàn)將String類(lèi)型分別轉(zhuǎn)換為Data,自定義對(duì)象和List<自定義對(duì)象>。

              添加依賴(lài)

              添加spring-boot-starter-web依賴(lài)

              <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>

              實(shí)體類(lèi)

              1.User類(lèi)
              public class User {
                private long  id;
                //用戶(hù)名
                private String name;
                //出生日期
                private Date birth;
                //關(guān)聯(lián)用戶(hù)
                private User linkUser;
                //喜歡的文章
                private List<Article> favArticles=new ArrayList<>();
               //下面省略Getter和Setter方法
              2.Article類(lèi)
              public class Article {
                //文章id
                private long artId;
                //文章名
                private String artName;
                
               //下面省略Getter和Setter方法
              }

              配置類(lèi)型轉(zhuǎn)化器

              下面三個(gè)類(lèi)都需要添加@Component注解,否則不能生效。并實(shí)現(xiàn)Spring提供的org.springframework.core.convert.converter.Converter接口,重寫(xiě)其中的convert()方法 ,方法中寫(xiě)自己的轉(zhuǎn)換邏輯。

              1.定義全局日期轉(zhuǎn)換器
              @Component
              public class DateConvert implements Converter<String,Date> {
                //日期格式
               SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
                @Override
                public Date convert(String s) {
                  if (s!=null&&!"".equals(s)){
                    try {
                      //解析參數(shù)
                      Date date=sdf.parse(s);
                      return date;
                    } catch (ParseException e) {
                      e.printStackTrace();
                    }
                  }
                  return null;
                }
              }
              2.定義全局對(duì)象轉(zhuǎn)換器

              這里使用Jackson的ObjectMapper類(lèi)的readValue()函數(shù)實(shí)現(xiàn)將Json字符串反序列化為Java對(duì)象

              @Component
              public class ObjectConvert implements Converter<String,User> {
                @Override
                public User convert(String s) {
                  ObjectMapper objectMapper=new ObjectMapper();
                  if (s!=null&&!"".equals(s)){
                    try {
                      User user=objectMapper.readValue(s,User.class);
                      return user;
                    } catch (JsonProcessingException e) {
                      e.printStackTrace();
                    }
                  }
                  return null;
                }
              }
              3.定義全局List類(lèi)型轉(zhuǎn)換器

              這里使用Jackson的ObjectMapper類(lèi)的readValue()函數(shù)實(shí)現(xiàn)將Json字符串反序列化為 List

              @Component
              public class StringToListController implements Converter<String, List<Article>> {
               ObjectMapper objectMapper=new ObjectMapper();
                @Override
                public List<Article> convert(String s) {
                  List<Article> list=null;
                  try {
                     list=objectMapper.readValue(s, new TypeReference<List<Article>>() {
                    });
                  } catch (JsonProcessingException e) {
                    e.printStackTrace();
                  }
                  return list;
                }
              }

              控制器

              這里注意使用produces設(shè)置返回?cái)?shù)據(jù)的類(lèi)型為json,consumes設(shè)置提交內(nèi)容的類(lèi)型為:application/x-www-form-urlencoded。

              application/x-www-form-urlencoded作用:將鍵值對(duì)的參數(shù)用&連接起來(lái),如果有空格,將空格轉(zhuǎn)換為+加號(hào);有特殊符號(hào),將特殊符號(hào)轉(zhuǎn)換為ASCII HEX值。

              @RestController
              public class HelloController {
                @GetMapping("hello")
                public Date getDate(Date birth){
                  System.out.println(birth);
                  return birth;
                }
                @PostMapping(value="showUser",produces="application/json",
                        consumes = "application/x-www-form-urlencoded")
                public User showUser(User user){
                  return user;
                }
              }

              測(cè)試

              在Postman中進(jìn)行測(cè)試,注意以下設(shè)置:POST請(qǐng)求 -> Body -> x-www-form-urlencoded。在Body中輸入?yún)?shù)進(jìn)行測(cè)試。

              因?yàn)閰?shù)中有Json類(lèi)型參數(shù),如果直接使用Params下進(jìn)行發(fā)送數(shù)據(jù),會(huì)出現(xiàn)請(qǐng)求參數(shù)異常錯(cuò)誤。

              Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

              測(cè)試結(jié)果:

              Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

              Converter使用及其原理

              在Spring MVC開(kāi)發(fā)中,我們可以很方便的使用Converter來(lái)實(shí)現(xiàn)對(duì)請(qǐng)求參數(shù)的處理,比如字符串去空,日期格式化等。

              配置文件中對(duì)Converter的引用

              <!-- 屬性編輯器 -->
                  <bean id="conversionService"
                      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
                      <property name="converters">
                          <list>
                              <bean class="com.xxx.common.converter.StringTrimConverter" />
                              <bean class="com.xxx.common.converter.DateConverter" />
                              <bean class="com.xxx.common.converter.DatetimeConverter" />
                          </list>
                      </property>
                  </bean>
              <mvc:annotation-driven conversion-service="conversionService">

              如上代碼,我們配置了三種類(lèi)型的Converter。

              以字符串去空為例

              import org.springframework.core.convert.converter.Converter;
              /**
               * 去除前后空格
               * @author 
               *
               */
              public class StringTrimConverter implements Converter<String, String> {
                  public String convert(String source) {
                      //如果源字符串不為空則進(jìn)行轉(zhuǎn)換
                      if(source != null){
                          //去除源字符串前后空格
                          source = source.trim();
                          if(source.equals("")){ 
                              source = null;
                          }
                      }
                      return source;
                  }
              }

              配置好以上內(nèi)容,即可在我們的請(qǐng)求中實(shí)現(xiàn)字符串自動(dòng)去空格。

              明白使用其實(shí)很簡(jiǎn)單,我們可以看下在Spring的底層,具體是如何實(shí)現(xiàn)Converter的。我們以字符串去空的代碼為例。

              以上代碼,首先實(shí)現(xiàn)了Converter接口

              我們查看Converter接口的源碼

              /**
               * A converter converts a source object of type S to a target of type T.
               * Implementations of this interface are thread-safe and can be shared.
               *
               * <p>Implementations may additionally implement {@link ConditionalConverter}.
               *
               * @author Keith Donald
               * @since 3.0
               * @see ConditionalConverter
               * @param <S> The source type
               * @param <T> The target type
               */
              public interface Converter<S, T> {
                  /**
                   * Convert the source of type S to target type T.
                   * @param source the source object to convert, which must be an instance of S
                   * @return the converted object, which must be an instance of T
                   * @throws IllegalArgumentException if the source could not be converted to the desired target type
                   */
                  T convert(S source);
              }

              通過(guò)JavaDoc我們可以看到,實(shí)現(xiàn)該接口,可以使我們將S類(lèi)型的對(duì)象轉(zhuǎn)換為T(mén)類(lèi)型。那么對(duì)應(yīng)的我們對(duì)于Date類(lèi)型的轉(zhuǎn)換,就可寫(xiě)為如下代碼:

              public class DateConverter implements Converter
              <bean id="conversionService"
                      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

              該類(lèi)的對(duì)象,繼續(xù)查看對(duì)應(yīng)改類(lèi)的源碼,以及對(duì)應(yīng)的JavaDoc。我們可以在該類(lèi)的Doc中看到如下描述:

              * <p>Like all {@code FactoryBean} implementations, this class is suitable for
               * use when configuring a Spring application context using Spring {@code <beans>}
               * XML. When configuring the container with
               * {@link org.springframework.context.annotation.Configuration @Configuration}
               * classes, simply instantiate, configure and return the appropriate
               * {@code FormattingConversionService} object from a
               * {@link org.springframework.context.annotation.Bean @Bean} method.

              該類(lèi)適用于適用XML構(gòu)建Spring應(yīng)用。

              我們查看對(duì)應(yīng)的成員變量:

              public class FormattingConversionServiceFactoryBean
                      implements FactoryBean<FormattingConversionService>, EmbeddedValueResolverAware, InitializingBean {
                  private Set<?> converters;
                  private Set<?> formatters;
                  private Set<FormatterRegistrar> formatterRegistrars;
                  private boolean registerDefaultFormatters = true;
                  private StringValueResolver embeddedValueResolver;
                  private FormattingConversionService conversionService;

              在配置XML時(shí),我們主要配置了集合類(lèi)的converters,該類(lèi)比較重要的方法如下:

              @Override
                  public void afterPropertiesSet() {
                      this.conversionService = new DefaultFormattingConversionService(this.embeddedValueResolver, this.registerDefaultFormatters);
                      ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
                      registerFormatters();
                  }

              該方法實(shí)現(xiàn)了對(duì)conversionService中增減我們對(duì)應(yīng)的格式化器。

              在Spring啟動(dòng)時(shí),注冊(cè)轉(zhuǎn)換器 時(shí)會(huì)進(jìn)入afterPropertiesSet 方法。在該方法中,我們可以看到Spring以HashSet來(lái)存儲(chǔ)對(duì)應(yīng)的converters。在ConversionServiceFactory中,判斷不同的轉(zhuǎn)換器,并進(jìn)行注冊(cè)。

              public static void registerConverters(Set<?> converters, ConverterRegistry registry) {
                      if (converters != null) {
                          for (Object converter : converters) {
                              if (converter instanceof GenericConverter) {
                                  registry.addConverter((GenericConverter) converter);
                              }
                              else if (converter instanceof Converter<?, ?>) {
                                  registry.addConverter((Converter<?, ?>) converter);
                              }
                              else if (converter instanceof ConverterFactory<?, ?>) {
                                  registry.addConverterFactory((ConverterFactory<?, ?>) converter);
                              }
                              else {
                                  throw new IllegalArgumentException("Each converter object must implement one of the " +
                                          "Converter, ConverterFactory, or GenericConverter interfaces");
                              }
                          }
                      }
                  }

              到此,相信大家對(duì)“Spring Boot中怎么用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

              向AI問(wèn)一下細(xì)節(jié)

              免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

              AI