1

第一次在这里发帖……但我在许多教程、SO 帖子和文档中找不到解决方案。

使用以下命令创建 Spring MVC REST webapp:

   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>3.1.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.1.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.8</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.8</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.6</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.7</version>
</dependency>

我的控制器是

@Controller
public class HomeController {
    @RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public String login(@RequestBody Login login) {
        if (login != null) {
            logger.debug(login.toString());
        } else {
            logger.error("Null Login JSON received!");
        }
        return new Login();
    }

    private class Login {
        String username;
        String password;
         ..}

我正在尝试通过以下方式以编程方式配置它:

@Configuration
@EnableTransactionManagement
@EnableWebMvc
@ImportResource("classpath:applicationContext.xml")
@PropertySource("classpath:application.properties")
public class ApplicationContext {

@Bean
public MappingJacksonJsonView mappingJacksonJsonView() {
    MappingJacksonJsonView mappingJacksonJsonView = new MappingJacksonJsonView();
    return mappingJacksonJsonView;
}

@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
    Map<String, String> mediaTypes = new HashMap<String, String>();
    mediaTypes.put("json", "application/json");

    org.springframework.web.servlet.view.ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
    contentNegotiatingViewResolver.setMediaTypes(mediaTypes);
    return contentNegotiatingViewResolver;
}

@Bean
public org.codehaus.jackson.map.ObjectMapper objectMapper() {
    org.codehaus.jackson.map.ObjectMapper objectMapper = new org.codehaus.jackson.map.ObjectMapper();
    return objectMapper;
}

}

但是当我通过 AJAX 或 Firefox RESTClient 发送请求时:

{"username": "aname", "password" : "ahack"}

我收到消息:

"NetworkError: 415 Unsupported Media Type - http://localhost:8080/edm/login"

我真的很感激任何指示,这个让我很难过。

4

3 回答 3

2

您不需要注册 AnnotationHandlerMethodAdapter,因为您使用的是 Spring 3.1,所以单独使用 @EnableMVC 就足够了(它实际上注册了一个 RequestMappingHandlerAdapter) - 与 objectMapper、contentNegotiatingViewResolver、mappingJacksonJsonView 相同。

你也可以这样注释你的方法:

@RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json", produces="application/json")

这是一个使用相同注释的单页测试 - 该测试使用Spring-test-mvc

package org.bk.webtest;

import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.server.setup.MockMvcBuilders.*;

import org.junit.Test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

public class WebContextConfigurationTest {

    @Test
    public void testWebFlow() throws Exception {
        annotationConfigSetup(WebContextConfigurationTest.TestConfiguration.class)
            .build()
            .perform(post("/login").contentType(MediaType.APPLICATION_JSON).body("{\"username\":\"user\",\"password\":\"password\"}".getBytes()))
                .andExpect(status().isOk())
                .andExpect(content().string("{\"username\":\"user\",\"password\":\"password\"}"));
    }

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages="org.bk.webtest")
    public static class TestConfiguration{

    }
}

@Controller
class JsonController{
    @RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
    @ResponseBody
    public Login login(@RequestBody Login login) {
        System.out.println(login);
        return login;
    }
}

class Login{
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

}
于 2012-07-11T20:37:50.793 回答
1

如果您的配置没问题,那么当 Spring 尝试序列化您的参数时可能会出现问题。如果您在序列化中遇到问题(例如,由于 oneToMany 关系中的双向属性导致无限递归),您会收到 415 错误。在使用 Web 服务之前,请尝试模拟 Spring 所做的事情,例如:

try {
    ObjectMapper mapper=new ObjectMapper();
    //serialize
    String json=mapper.writeValueAsString(login);
    //deserialize
    Login login2 = mapper.readValue(json, Login.class);
} catch (Exception e) {
    e.printStackTrace();
}

//consume the ws
restTemplate.postForObject(URI,login,String.class);

如果出现问题,您会得到一个异常,显示原因。

于 2013-09-06T08:49:59.837 回答
0

对于此类错误“NetworkError: 415 Unsupported Media Type”,

您只需要调查以下事项: 在您的 Web 服务中:

  • 您的网络服务产生什么媒体类型?
  • 您的 Web 服务使用什么媒体类型?

在客户端:

  • 响应的接受媒体类型是什么?
  • 您请求的内容类型是什么?

映射如下:

  • Web 服务产生 <---> 客户端接受媒体类型
  • Web 服务使用 <---> 客户端内容类型的请求

对于您的问题,我认为根本原因应该是您忘记在 AJAX 或 Firefox RESTClient 请求中设置内容类型或接受类型。

于 2013-11-20T01:53:56.420 回答