我正在使用Spring开发一个使用AngularJS和WildFly的Web应用程序。
我的问题是我疯了,因为注释@requestBody似乎工作不对。
这是我的服务:
@ResponseBody
@RequestMapping(value = "/keyuser", method = RequestMethod.POST,
consumes = "application/json")
public KeyProfileUserSummary updateEmployee(@RequestBody KeyProfileUserSummary keyUser) {
return null;
}
这是我的对象KeyProfileUserSummary:
的成员private Integer id;
private String login;
private String password;
private String firstname;
private String lastname;
private UserRole userRole;
我不知道发生了什么,但我已经用其他类型的对象测试了这个服务,它运行得很好,但是当定义KeyProfileUserSummary它不能正常工作时,我得到ERROR 400 BAD REQUEST。我已经测试过将@RequestBody设置为“Object”,所以至少我可以看到即将发生的事情,从我的前端,我得到以下内容:
{id=3, login=aa, password=a, firstname=Martin, lastname=Müller, userRole=ROLE_USER}
UserRole是一个枚举。重要的是要清楚KeyProfileUserSummary只是KeyProfileUser的摘要版本,但是由于我得到了响应的所有链接元素,我决定发送这个更轻的类。使用KeyProfileUser进行测试工作得很好,我在Angular端获得JSON对象并可以将其发回。
在Angular方面,我没有对该对象做任何事情。只需在列表中接收它,当按下编辑按钮时,只需返回列表中的元素即可。这就是我发送它的方式:
res = $http.post("url.../keyuser", user);
问题是我的一切都与KeyProfileUser完美配合,但由于数据库可以变得非常庞大并且引用相当多,我决定切换到这个更轻的类,但现在我只得到这个ERROR 400 BAD REQUEST ......我正要挂起自己:P
感谢您的帮助!
答案 0 :(得分:2)
好的,最后我找到了解决方案。
在我的KeyProfileUserSummary中,我只有一个构造函数正在使用KeyProfileUser并将属性设置为摘要版本:
public KeyProfileUserSummary(KeyProfileUser keyProfileUser) {
this.id = keyProfileUser.getId();
this.login = keyProfileUser.getLogin();
this.password = keyProfileUser.getPassword();
this.firstname = keyProfileUser.getPerson().getFirstname();
this.lastname = keyProfileUser.getPerson().getLastname();
this.userRole = keyProfileUser.getUserRole();
}
显然,在调度程序servlet的第993行设置断点(感谢@Clemens Eberwein的提示)我意识到从JSON对象解析时,Jackson解析器需要一个空的构造函数!所以添加它解决了它并且完美地工作。
注意:对于KeyProfileUser,它完全正常,因为我们有hibernate的注释@Entity,因此自动创建了空构造函数。
答案 1 :(得分:1)
尝试一下..可能对你有用..
$http({
method: 'POST',
url: 'http://localhost:8080/keyuser',
data: user,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}}).then(function(result) {
console.log(result);
}, function(error) {
console.log(error);
});
答案 2 :(得分:0)
如果我猜测,杰克逊无法反序列化/序列化您的对象。这是我制作的一个工具:
import java.io.IOException;
import java.nio.charset.Charset;
import org.springframework.http.MediaType;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class SerializeDeserializeUtil {
public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
public static byte[] convertObjectToJsonBytes(Object object)
throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
return mapper.writeValueAsBytes(object);
}
public static <T> T deserializeObject(String jsonRepresentation,
Class<T> clazz) throws JsonParseException, JsonMappingException,
IOException {
ObjectMapper mapper = new ObjectMapper();
Object obj = mapper.readValue(jsonRepresentation.getBytes(), clazz);
return clazz.cast(obj);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static byte[] convertObjectToJsonBytesWithCustomSerializer(
Object object, JsonSerializer serializer, Class clazz)
throws IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule sm = new SimpleModule();
sm.addSerializer(clazz, serializer);
mapper.registerModule(sm);
mapper.setSerializationInclusion(Include.NON_NULL);
return mapper.writeValueAsBytes(object);
}
}
尝试创建测试只是为了序列化和反序列化目标。创建一个KeyProfileUserSummary对象并尝试反序列化/序列化,看看杰克逊是否抱怨。
更简单的方法是启用DEBUG日志记录并检查日志文件,默认情况下您不会看到此类错误
希望它有所帮助。
答案 3 :(得分:0)
如果为“org.springframework.web”添加DEBUG日志记录org.springframework.web.servlet.DispatcherServlet应该为您提供导致“400 Bad Request”错误的详细信息。
可以找到有关Wildfly日志记录配置的详细信息here
基于你的KeyProfileUserSummary类,我猜问题是UserRole对象,在上面的例子中只是userRole=ROLE_USER
。由于它是一个对象,它应该用花括号括起来,并且必须设置属性名称。例如
userRole = { name = "ROLE_USER"}
如果是enum,this答案可能会有帮助