我正在寻找在Spring MVC中绑定和转换数据的最简单和最简单的方法.如果可能,不进行任何xml配置.
到目前为止,我一直在使用PropertyEditors:
public class CategoryEditor extends PropertyEditorSupport {
// Converts a String to a Category (when submitting form)
@Override
public void setAsText(String text) {
Category c = new Category(text);
this.setValue(c);
}
// Converts a Category to a String (when displaying form)
@Override
public String getAsText() {
Category c = (Category) this.getValue();
return c.getName();
}
}
Run Code Online (Sandbox Code Playgroud)
和
...
public class MyController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class, new CategoryEditor());
}
...
}
Run Code Online (Sandbox Code Playgroud)
它很简单:两个转换都在同一个类中定义,绑定很简单.如果我想在我的所有控制器上进行通用绑定,我仍然可以在我的xml配置中添加3行 …
我们都知道,Spring MVC通常与Hibernate Validator和JSR-303很好地集成.但正如有人所说,Hibernate Validator只适用于Bean Validation,这意味着应该将更复杂的验证推送到数据层.此类验证的示例:业务密钥唯一性,内部记录依赖性(通常指向数据库设计问题,但我们都生活在一个不完美的世界).即使像字符串字段长度这样的简单验证也可能由某个DB值驱动,这使得Hibernate Validator无法使用.
所以我的问题是,Spring或Hibernate或JSR是否提供了执行此类复杂验证的功能?是否有一些已建立的模式或技术部分可以在基于Spring和Hibernate的标准Controller-Service-Repository设置中执行此类验证?
更新:让我更具体一点.例如,有一个表单向控制器的save方法发送AJAX保存请求.如果出现一些验证错误 - 简单或"复杂" - 我们应该回到浏览器,其中一些json指示有问题的字段和相关错误.对于简单错误,我可以从中提取字段(如果有)和错误消息BindingResult.您会针对"复杂"错误提出什么样的基础设施(可能是特定的,而不是临时的例外?)?使用异常处理程序对我来说似乎不是一个好主意,因为在save方法之间分离单个验证过程@ExceptionHandler并使事情变得复杂.目前我使用一些特殊的例外(如,ValidationException):
public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
Result r = new Result();
if (errors.hasErrors()) {
r.setStatus(Result.VALIDATION_ERROR);
// ...
} else {
try {
dao.save(entity);
r.setStatus(Result.SUCCESS);
} except (ValidationException e) {
r.setStatus(Result.VALIDATION_ERROR);
r.setText(e.getMessage());
}
}
return r;
}
Run Code Online (Sandbox Code Playgroud)
你能提供更优化的方法吗?
我想知道如何在Spring MVC应用程序中使用Spring Validator(非注释)验证表单中的嵌套对象列表.
class MyForm() {
String myName;
List<TypeA> listObjects;
}
class TypeA() {
String number;
String value;
}
Run Code Online (Sandbox Code Playgroud)
如何创建MyFormValidator以验证listObjects并为TypeA的数量和值添加错误消息.
我听说控制器属于表示层.这怎么可能?
我以为 :
是否有良好的链接来证明控制器属于表示层?
"Spring MVC用于表示层":我们如何才能在表示层中使用MVC?
我已经通过Spring文档和源代码,仍然没有找到我的问题的答案.
我在我的域模型中有这些类,并希望在spring-mvc中将它们用作后备表单对象.
public abstract class Credentials {
private Long id;
....
}
public class UserPasswordCredentials extends Credentials {
private String username;
private String password;
....
}
public class UserAccount {
private Long id;
private String name;
private Credentials credentials;
....
}
Run Code Online (Sandbox Code Playgroud)
我的控制器:
@Controller
public class UserAccountController
{
@RequestMapping(value = "/saveAccount", method = RequestMethod.POST)
public @ResponseBody Long saveAccount(@Valid UserAccount account)
{
//persist in DB
return account.id;
}
@RequestMapping(value = "/listAccounts", method = RequestMethod.GET)
public String listAccounts()
{
//get all accounts from …Run Code Online (Sandbox Code Playgroud) 我有一个名为Browser的POJO,我用Hibernate Validator注释进行了注释.
import org.hibernate.validator.constraints.NotEmpty;
public class Browser {
@NotEmpty
private String userAgent;
@NotEmpty
private String browserName;
...
}
Run Code Online (Sandbox Code Playgroud)
我编写了以下单元测试,试图验证我的Controller方法是否捕获了验证错误.
@Test
public void testInvalidData() throws Exception {
Browser browser = new Browser("opera", null);
MockHttpServletRequest request = new MockHttpServletRequest();
BindingResult errors = new DataBinder(browser).getBindingResult();
// controller is initialized in @Before method
controller.add(browser, errors, request);
assertEquals(1, errors.getErrorCount());
}
Run Code Online (Sandbox Code Playgroud)
这是我的Controller的add()方法:
@RequestMapping(value = "/browser/create", method = RequestMethod.POST)
public String add(@Valid Browser browser, BindingResult result, HttpServletRequest request) throws Exception {
if (result.hasErrors()) {
request.setAttribute("errorMessage", result.getAllErrors());
return …Run Code Online (Sandbox Code Playgroud) 我有一个Model,它包含一个States(List)列表和一个包含Country对象的用户对象.我认为用户可以选择他的国家.
这是我的jsp页面的片段:
<form:select path="user.country">
<form:option value="-1">Select your country</form:option>
<form:options items="${account.countries}" itemLabel="name" itemValue="id" />
</form:select>
Run Code Online (Sandbox Code Playgroud)
这是我的帐户模型:
public class Account {
private User user;
private List<Country> countries;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Country> getCountries() {
return countries;
}
public void setCountries(List<Country> countries) {
this.countries = countries;
}
}
Run Code Online (Sandbox Code Playgroud)
当jsp加载(GET)表单时:select显示当前用户所在国家/地区的选定项目.问题是,当我发布表单时,我得到这个例外:
Field error in object 'account' on field 'user.country': rejected value [90];
codes [typeMismatch.account.user.country,typeMismatch.user.country,typeMismatch.country,typeMismatch.org.MyCompany.entities.Country,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [account.user.country,user.country];
arguments []; default message …Run Code Online (Sandbox Code Playgroud) 我试图在松耦合系统方面围绕这些对象之间的差异.业务对象是否与实体对象相同?我可以在MVC中使用业务或实体对象作为我的命令对象吗?命令对象与表单对象相同吗?只是在寻找Spring术语和用法中对象类型的说明.
我在stackoverflow上发现了一些问题,但没有任何问题可以解释我的喜好.
Spring Web MVC文档似乎说你可以使用你的业务(实体?)对象作为你的命令/表单对象,但这不会违背关注点的分离吗?
来自Spring Docs:
可重复使用的业务代码,无需重复.将现有业务对象用作命令或表单对象,而不是镜像它们以扩展特定的框架基类.
我不确定这是否是一个复杂的问题,但作为一个初学者,这对我来说似乎有点复杂.我有一个对象,我需要在UI上显示一些值,让用户选择其中的一些,我需要在用户点击提交按钮时将数据发送回另一个控制器.这是我的数据对象的结构
public class PrsData{
private Map<String, List<PrsCDData>> prsCDData;
}
public class PrsCDData{
private Map<String, Collection<ConfiguredDesignData>> configuredDesignData;
}
public ConfiguredDesignData{
// simple fields
}
Run Code Online (Sandbox Code Playgroud)
我在显示视图之前在模型中设置了对象
model.addAttribute("prsData", productData.getPrData());
Run Code Online (Sandbox Code Playgroud)
在表格中,我有以下设置
<form:form method="post" commandName="prsData" action="${addProductToCartAction}" >
<form:hidden path="prsCDData['${prsCDDataMap.key}']
[${status.index}].configuredDesignData['${configuredDesignDataMap.key}']
[${configuredDesignDataStatus.index}].code"/>
<form:hidden path="prsCDData['${prsCDDataMap.key}']
[${status.index}].configuredDesignData['${configuredDesignDataMap.key}']
[${configuredDesignDataStatus.index}].description"/>
</form:form>
Run Code Online (Sandbox Code Playgroud)
这就是我所拥有的 AddProductToCartController
public String addToCart(@RequestParam("productCodePost") final String code,
@ModelAttribute("prsData") final PrsData prsData, final Model model,
@RequestParam(value = "qty", required = false, defaultValue = "1") final long qty)
Run Code Online (Sandbox Code Playgroud)
在提交表格时,我会收到以下异常
org.springframework.beans.NullValueInNestedPathException: Invalid property 'prsCDData[Forced][0]'
of bean class [com.product.data.PrsData]:
Cannot access indexed …Run Code Online (Sandbox Code Playgroud) 我试图解决为什么抛出以下异常.
我认为这是因为在"查看"模式下访问了一个portlet,但由于某种原因我不知道spring servlet容器无法提供请求,这是正确的吗?
以下例外集中的"参数映射"在哪里?
org.springframework.web.portlet.NoHandlerFoundException:没有为portlet请求找到匹配的处理程序方法:mode'view',phase'ACT__PASE',参数map [empty]
这是控制器:
@Controller
@RequestMapping("VIEW")
public class DetailsController {
@RequestMapping("VIEW")
public String showDetails(final ModelMap modelMap, final RenderRequest renderRequest) {
return "allDetails/details";
}
}
Run Code Online (Sandbox Code Playgroud) java ×10
spring-mvc ×10
spring ×6
data-binding ×2
validation ×2
binding ×1
forms ×1
jsp ×1
jstl ×1
junit ×1
list ×1
nested ×1
portlet ×1
types ×1