乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      SpringMVC HandlerMethodArgumentResolver自定義參數(shù)轉(zhuǎn)換器

       印度阿三17 2019-04-11

      來源: https://www.cnblogs.com/daxin/p/3296493.html

      自定義Spring MVC3的參數(shù)映射和返回值映射 fastjson首先說一下場景:在一些富客戶端Web應(yīng)用程序中我們會有比較多的Ajax調(diào)用,并且希望與服務(wù)器交互的數(shù)據(jù)需要是復(fù)雜的JSON對象。 fastjon是一個非常高效的JSON序列化和反序列化庫,我希望我們輸入的JSON串能通過fastjson直接反序列化為一個復(fù)雜的JavaBean對象,同時我的返回值能夠能通過fastjson序列化為JSON串。所謂復(fù)雜的JavaBean就是,不僅僅只有一層屬性,而是屬性也是JavaBean的情況, 例如:

      public class FooBean {
          private String name;
      
          private Long id;
      
          private Date birthday;
      
          private List<Address> addresses;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          public Date getBirthday() {
              return birthday;
          }
      
          public void setBirthday(Date birthday) {
              this.birthday = birthday;
          }
      
          public List<Address> getAddresses() {
              return addresses;
          }
      
          public void setAddresses(List<Address> addresses) {
              this.addresses = addresses;
          }
      
          @Override
          public String toString() {
              return "FooBean{"  
                      "name='"   name   '''  
                      ", id="   id  
                      ", birthday="   birthday  
                      ", addresses="   addresses  
                      '}';
          }
      }
      public class Address {
          private String street;
          private int number;
      
          public String getStreet() {
              return street;
          }
      
          public void setStreet(String street) {
              this.street = street;
          }
      
          public int getNumber() {
              return number;
          }
      
          public void setNumber(int number) {
              this.number = number;
          }
      
          @Override
          public String toString() {
              return "Address{"  
                      "street='"   street   '''  
                      ", number="   number  
                      '}';
          }
      }

      ?

      當(dāng)然,結(jié)構(gòu)還可以再復(fù)雜,Adress對象里還可以又復(fù)雜JavaBean的屬性。

      在SpringMVC3中我們可以把輸入簡單的映射為某個Action方法的參數(shù), 例如:

      ?

      @RequestMapping(value="/someAction", method=RequestMethod.POST)
      public String processSubmit(FooBean fooBean, Model model) {
      // 利用fooBean
          return “views/some_page”;
      }

      ?

      用Spring MVC3, 我們可以把Form里的字段輕松的映射到JavaBean的屬性。 Spring MVC3 提供了豐富的參數(shù)映射機(jī)制,?詳細(xì)信息可以參見這里

      同時對于Spring MVC3默認(rèn)的提供的映射機(jī)制不能涵蓋的對象,我們可以通過擴(kuò)展HandlerMethodArgumentResolver和HttpMessageConverter的機(jī)制來實(shí)現(xiàn)。

      HandlerMethodArgumentResolver對應(yīng)輸入, HttpMessageConverter對應(yīng)輸出

      假設(shè)對于上面的FooBean, 我們有這樣一個JSON對象和它對應(yīng):

      ?

      var data = {
          name : "matianyi",
          id : 12345,
          birthday : "1983-07-01 01:12:12",
          addresses : [
              {
                  street : "street1",
                  number : 1
              },
              {
                  street : "street2",
                  number : 2
              }
          ]
      };

      ?

      Spring MVC3 本身也提供直接把JSON對象映射到JavaBean的功能,例如MappingJackson2HttpMessageConverter和MappingJackson2JsonView。

      在這里我們希望通過fastjson來實(shí)現(xiàn)序列化和反序列化。所以我們要自定義一個HandlerMethodArgumentResolver用來指定HttpServletRequest的Body映射到一個JavaBean。并且返回的JavaBean通過fastjson序列化。

      方法的定義是這樣的:

      @RequestMapping(value = "/fastjson", method = RequestMethod.POST)
      public @ResponseBody FooBean fastjson2(@FastJson FooBean foo) {
          System.out.println(foo);
          return foo;
      }

      ?

      首先這里有個@FastJson的標(biāo)注,這是我們?yōu)榱俗屪约旱腍andlerMethodArgumentResolver能夠識別這個參數(shù)是需要自己來處理而定義的一個Annotation

      ?

      @Target(ElementType.PARAMETER)
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface FastJson {
      }

      ?

      然后就是定義一個FastJsonArgumentResolver,來對HttpServletRequest的body進(jìn)行解析:

      ?

      public class FastJsonArgumentResolver implements HandlerMethodArgumentResolver {
          @Override
          public boolean supportsParameter(MethodParameter parameter) {
              return parameter.getParameterAnnotation(FastJson.class) != null;
          }
      
          @Override
          public Object resolveArgument(MethodParameter parameter,
                                        ModelAndViewContainer mavContainer,
                                        NativeWebRequest webRequest,
                                        WebDataBinderFactory binderFactory) throws Exception {
      
              HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
              // content-type不是json的不處理
              if (!request.getContentType().contains("application/json")) {
                  return null;
              }
      
              // 把reqeust的body讀取到StringBuilder
              BufferedReader reader = request.getReader();
              StringBuilder sb = new StringBuilder();
      
              char[] buf = new char[1024];
              int rd;
              while((rd = reader.read(buf)) != -1){
                  sb.append(buf, 0, rd);
              }
      
              // 利用fastjson轉(zhuǎn)換為對應(yīng)的類型
              if(JSONObjectWrapper.class.isAssignableFrom(parameter.getParameterType())){
                  return new JSONObjectWrapper(JSON.parseObject(sb.toString()));
              } else {
                  return JSON.parseObject(sb.toString(), parameter.getParameterType());
              }
          }
      }

      ?

      在這里,我們只針對content-type是application/json的對象做處理,最后通過JSON.parseObject方法簡單的把JSON串反序列化為指定的類型。

      這里有一個JSONObjectWrapper對象需要解釋一下。 原本我是想如果Action方法的參數(shù)的類型是JSONObject這樣的原始類型的話就直接利用JSON.parseObject(sb.toString())映射過去。 但是由于JSONObject實(shí)現(xiàn)了Map結(jié)果,所以Spring MVC3的默認(rèn)處理器MapMethodProcessor會先起作用,這樣就不能正常的映射成JSONObject對象了。 沒有辦法做了一個簡單的JSONObject包裝類,以使MapMethodProcessor不能對其進(jìn)行處理。

      public class JSONObjectWrapper {
          private JSONObject jsonObject;
      
          public JSONObjectWrapper(JSONObject jsonObject) {
              this.jsonObject = jsonObject;
          }
      
          public JSONObject getJSONObject() {
              return jsonObject;
          }
      }

      ?

      這里順便提一下,Spring MVC自己的HandlerMethodArgumentResolver有哪些,并且會以什么樣的順序執(zhí)行呢?
      其實(shí)定義在RequestMappingHandlerAdapter里:

      /**
       * Return the list of argument resolvers to use including built-in resolvers
       * and custom resolvers provided via {@link #setCustomArgumentResolvers}.
       */
      private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
          List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
      
          // Annotation-based argument resolution
          resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
          resolvers.add(new RequestParamMapMethodArgumentResolver());
          resolvers.add(new PathVariableMethodArgumentResolver());
          resolvers.add(new PathVariableMapMethodArgumentResolver());
          resolvers.add(new MatrixVariableMethodArgumentResolver());
          resolvers.add(new MatrixVariableMapMethodArgumentResolver());
          resolvers.add(new ServletModelAttributeMethodProcessor(false));
          resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
          resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
          resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
          resolvers.add(new RequestHeaderMapMethodArgumentResolver());
          resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
          resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
      
          // Type-based argument resolution
          resolvers.add(new ServletRequestMethodArgumentResolver());
          resolvers.add(new ServletResponseMethodArgumentResolver());
          resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
          resolvers.add(new RedirectAttributesMethodArgumentResolver());
          resolvers.add(new ModelMethodProcessor());
          resolvers.add(new MapMethodProcessor());
          resolvers.add(new ErrorsMethodArgumentResolver());
          resolvers.add(new SessionStatusMethodArgumentResolver());
          resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
      
          // Custom arguments
          if (getCustomArgumentResolvers() != null) {
              resolvers.addAll(getCustomArgumentResolvers());
          }
      
          // Catch-all
          resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
          resolvers.add(new ServletModelAttributeMethodProcessor(true));
      
          return resolvers;
      }

      ?

      在這里我們可以看到:

      • Spring MVC本身提供了非常豐富的HandlerMethodArgumentResolver實(shí)現(xiàn)。
      • HandlerMethodArgumentResolver是按順序執(zhí)行,當(dāng)然為了性能Spring本身是有Cache的,一旦確定了某一個參數(shù)可以應(yīng)用的HandlerMethodArgumentResolver,下次就不會再遍歷這個List了。
      • 自定的HandlerMethodArgumentResolver會晚于Spring自己的被執(zhí)行,這也是上面提到的JSONObject會被MapMethodProcessor先處理的原因。
      • Spring自己的JSON映射機(jī)制是通過RequestResponseBodyMethodProcessor AllEncompassingFormHttpMessageConverter來實(shí)現(xiàn)的
      • 很不幸這是一個private方法, 你沒有辦法簡單的改變Spring MVC的默認(rèn)行為,除非你重寫RequestMappingHandlerAdapter

      好了,有了FastJsonArgumentResolver, 接下來我們要讓它生效:

      <mvc:annotation-driven>
          <mvc:argument-resolvers>
              <beans:bean class="org.springframework.samples.mvc.fastjson.FastJsonArgumentResolver"/>
          </mvc:argument-resolvers>
          <mvc:message-converters>
              <beans:bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
          </mvc:message-converters>
      </mvc:annotation-driven>

      ?

      就是個Spring的配置,這里就不多講了。除了FastJsonArgumentResolver,我們還配置了FastJsonHttpMessageConverter來對返回值進(jìn)行序列化。

      本來我是想自己寫一個FastJsonHttpMessageConverter, 后來發(fā)現(xiàn)fastjson庫里已經(jīng)存在了, 我就不自己造輪子了。我們自己來看看實(shí)現(xiàn)吧,截取了一部分:

      ?

      復(fù)制代碼
      @Override
      protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException,
                                                                               HttpMessageNotWritableException {
          OutputStream out = outputMessage.getBody();
          String text = JSON.toJSONString(obj, features);
          byte[] bytes = text.getBytes(charset);
          out.write(bytes);
      }
      復(fù)制代碼

      ?

      實(shí)現(xiàn)很簡單, 就不詳細(xì)說了。

      最后來看看如何通過Ajax調(diào)用上面的Action方法:

      var data = {
          name : "matianyi",
          id : 12345,
          birthday : "1983-07-01 01:12:12",
          addresses : [
              {
                  street : "street1",
                  number : 1
              },
              {
                  street : "street2",
                  number : 2
              }
          ]
      };
      var link = $(this);
      $.ajax({
          url:"/spring-sample/fastjson1",
          dataType:"json",
          type:"POST",
          contentType: "application/json",
          data : JSON.stringify(data),
          success : function(obj){
              console.log(obj);
          }
      });

      兩點(diǎn)需要注意:

      • contentType: “application/json”
      • data : JSON.stringify(data)

      這樣JavaScript的對象會被轉(zhuǎn)換為JSON串,并且最為HttpRequest的BODY傳給服務(wù)器。

      來源:http://www./content-4-161401.html

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多