@Override
 protected String getMediaTypeKey(NativeWebRequest webRequest) {
   HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
   if (request == null) {
     logger.warn("An HttpServletRequest is required to determine the media type key");
     return null;
   }
   String path = PATH_HELPER.getLookupPathForRequest(request);
   String filename = WebUtils.extractFullFilenameFromUrlPath(path);
   String extension = StringUtils.getFilenameExtension(filename);
   return (StringUtils.hasText(extension)) ? extension.toLowerCase(Locale.ENGLISH) : null;
 }
 /**
  * Determines the list of {@link MediaType} for the given {@link HttpServletRequest}.
  *
  * <p>The default implementation invokes {@link #getMediaTypeFromFilename(String)} if {@linkplain
  * #setFavorPathExtension favorPathExtension} property is <code>true</code>. If the property is
  * <code>false</code>, or when a media type cannot be determined from the request path, this
  * method will inspect the {@code Accept} header of the request.
  *
  * <p>This method can be overridden to provide a different algorithm.
  *
  * @param request the current servlet request
  * @return the list of media types requested, if any
  */
 protected List<MediaType> getMediaTypes(HttpServletRequest request) {
   if (this.favorPathExtension) {
     String requestUri = urlPathHelper.getLookupPathForRequest(request);
     String filename = WebUtils.extractFullFilenameFromUrlPath(requestUri);
     MediaType mediaType = getMediaTypeFromFilename(filename);
     if (mediaType != null) {
       if (logger.isDebugEnabled()) {
         logger.debug(
             "Requested media type is '" + mediaType + "' (based on filename '" + filename + "')");
       }
       return Collections.singletonList(mediaType);
     }
   }
   if (this.favorParameter) {
     if (request.getParameter(this.parameterName) != null) {
       String parameterValue = request.getParameter(this.parameterName);
       MediaType mediaType = getMediaTypeFromParameter(parameterValue);
       if (mediaType != null) {
         if (logger.isDebugEnabled()) {
           logger.debug(
               "Requested media type is '"
                   + mediaType
                   + "' (based on parameter '"
                   + this.parameterName
                   + "'='"
                   + parameterValue
                   + "')");
         }
         return Collections.singletonList(mediaType);
       }
     }
   }
   if (!this.ignoreAcceptHeader) {
     String acceptHeader = request.getHeader(ACCEPT_HEADER);
     if (StringUtils.hasText(acceptHeader)) {
       try {
         List<MediaType> acceptableMediaTypes = MediaType.parseMediaTypes(acceptHeader);
         List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request);
         Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
         for (MediaType acceptable : acceptableMediaTypes) {
           for (MediaType producible : producibleMediaTypes) {
             if (acceptable.isCompatibleWith(producible)) {
               compatibleMediaTypes.add(getMostSpecificMediaType(acceptable, producible));
             }
           }
         }
         List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);
         MediaType.sortByQualityValue(mediaTypes);
         if (logger.isDebugEnabled()) {
           logger.debug(
               "Requested media types are "
                   + mediaTypes
                   + " based on Accept header types "
                   + "and producible media types "
                   + producibleMediaTypes
                   + ")");
         }
         return mediaTypes;
       } catch (IllegalArgumentException ex) {
         if (logger.isDebugEnabled()) {
           logger.debug(
               "Could not parse accept header [" + acceptHeader + "]: " + ex.getMessage());
         }
         return null;
       }
     }
   }
   if (this.defaultContentType != null) {
     if (logger.isDebugEnabled()) {
       logger.debug(
           "Requested media types is "
               + this.defaultContentType
               + " (based on defaultContentType property)");
     }
     return Collections.singletonList(this.defaultContentType);
   } else {
     return Collections.emptyList();
   }
 }