0

Here is my controller

@RequestMapping(value = "/download/{product}/{topic}/{key:.*}")
//@ResponseBody
public AjaxResult download(@PathVariable("product") String product, @PathVariable("topic") String topic,
    @PathVariable("key") String key, HttpServletRequest request, HttpServletResponse response) {

Since the key path variable may contains dot, so regular expression is used, and class AjaxResult extends LinkedHashMap and all getter and setter are added, so it can return json result. the view resolver is as follow:

<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="viewResolvers">
          <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
        </list>      
    </property>
    <property name="defaultViews">
        <list>
            <bean
                class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
        </list>
    </property>
</bean>

and the converter:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean id="fastJsonHttpMessageConverter"
            class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=UTF-8</value>
                    <value>text/plain;charset=UTF-8</value>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
            <property name="features">
                <array>
                    <!--<value>WriteMapNullValue</value> -->
                    <value>QuoteFieldNames</value>
                    <value>DisableCircularReferenceDetect</value>
                </array>
            </property>
        </bean>

        <bean id="stringHttpMessageConverter"
            class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8" index="0" />
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

and <mvc:annotation-driven /> <mvc:default-servlet-handler /> are added.

The problem is when i access like: /download/product/topic/key.abc, it works fine, but when access: /download/product/topic/key.txt, error happens:

javax.servlet.ServletException: Could not resolve view with name '/download/product/topic/key' in servlet with name ''
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1227)
    at org.springframework.test.web.servlet.TestDispatcherServlet.render(TestDispatcherServlet.java:105)

Please notice the difference between the two url, in a word when access a url that contains a dot and a correct file extension, error happens.

You may see that i comment the annotation @ResponseBody of the controller, if a add @ResponseBody and access url /download/product/topic/key.txt, error happens:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:137)

Can anyone help? Thanks.

Update

  1. add trailing slash as said in Spring MVC @PathVariable getting truncated can solve my problem, that is :

@RequestMapping(value = "/download/{product}/{topic}/{key:.*}/")

and when access using /download/product/topic/key.txt/, but is there any other solution that won't change the value in @RequestMapping and url?

chou
  • 344
  • 3
  • 17

2 Answers2

0

add below conde into .xml file of your Spring Configuration:

<context:annotation-config/> 
<mvc:annotation-driven />

<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
  <list>
    <ref bean="jacksonMessageConverter"/>
  </list>
</property>
</bean>

you can try to add DispatcherServlet into your web.xml file, you can find code below:

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

    <servlet-mapping>
        <servlet-name>myServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
Anshul Sharma
  • 3,432
  • 1
  • 12
  • 17
  • It doesn't work, still the error javax.servlet.ServletException: Could not resolve view with name '/download/product/topic/key' when access url '/download/product/topic/key.txt' – chou Aug 08 '17 at 05:53
0

I solve the problem as follow: for in my spring servlet config xml, there is a bean ContentNegotiatingViewResolver, so i add a bean ContentNegotiationManagerFactoryBean and set it property favorPathExtension to false, so below is my config file:

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
</bean>
<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">    
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="viewResolvers">
          <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean
                class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
        </list>
    </property>
</bean>

And you don't need @ResponseBody in your controller

chou
  • 344
  • 3
  • 17