- 浏览: 149110 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
fei33423:
流程引擎的流转比状态机要复杂太多了把. 我觉得你即可以看成平行 ...
工作流引擎是否应该建立在有限状态机(Finite State Machine, FSM)引擎之上? -
c601097836:
为什么你们都说FSM,而不是UML State machine ...
工作流引擎是否应该建立在有限状态机(Finite State Machine, FSM)引擎之上? -
ronghao:
di1984HIT 写道类似啊,我现在也有这个困惑、我的工作流 ...
工作流引擎是否应该建立在有限状态机(Finite State Machine, FSM)引擎之上? -
di1984HIT:
不错啊。学习了。
[转]hadoop使用中的几个小细节(一) -
di1984HIT:
好的、
工作流20种基本模式的理解
最近拿Spring MVC 3.x做项目,用了最新的系列相关Annotation来做Controller,有几点心得体会值得分享。
转载请注明 :IT进行时(zhengxianquan AT hotmail.com) from http://itstarting.iteye.com/
一、编写一个AbstractController.java,所有的Controller必须扩展
除了获得Template Design Pattern的好处之外,还能一点,那就是放置全局的@InitBinder:
public class AbstractController { ... @InitBinder protected void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class,new CustomDateEditor(dateFormat, false)); } ... }
二、每个域都应该有一个Controller,且做好URI规划
大家都知道Spring MVC 3.x是完全支持Restful的,我们把URI做好规划,对于诸如ACL的实现会有很大的帮助。建议的URI规划如下:{Domain}[/{SubDomain}]/{BusinessAction}/{ID}。比如:
hotels/bookings/cancel/{id} ——表示此URI匹配hotels域的bookings子域,将要进行的是取消某项booking的操作。代码如下:
@Controller @RequestMapping(value = "/hotels") public class HotelsController extends AbstractController { ... @RequestMapping(value = "/bookings/cancel/{id}", method = RequestMethod.POST) public String deleteBooking(@PathVariable long id) { bookingService.cancelBooking(id); //use prefix 'redirect' to avoid duplicate submission return "redirect:../../search"; } ... }
另外还有几个重要原因:
1、由于Spring的DefaultAnnotationHandlerMapping.java在做Mapping的时候,先做是否有类匹配,再找方法,把基本的mapping放在类上面,可以加速匹配效率;
2、后续可以通过更细腻的支持Ant path style的AntPathMatcher来规划URI Template资源,做ACL控制(请参考后面的心得体会)。
三、JSON/XML等ajax的支持很cool,可以尝试
JSON/XML/RSS等均可支持,当然有些denpendency,比如JSON的默认支持,需要jackson jar出现在lib中,POM的artifact如下:
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.5.3</version> </dependency>
这样,我们其实根本就不需要进行额外的JSON转换了,Spring MVC 3会根据请求的格式自行转换:
@ResponseBody @RequestMapping(value = "/ajax", method = RequestMethod.POST) public JsonDataWrapper<Hotel> ajax(WebRequest request, Hotel hotel, Model model) throws Exception { JsonDataWrapper<Hotel> jsonDataWrapper = this.getPaginatedGridData(request, hotel, hotelService); return jsonDataWrapper; }
注 :我上面的JsonDataWrapper只是我自己做的一个简单的wrapper,目的是为jQuery Flexigrid plugin做数据准备的。还是贴出来吧:
/** * A wrapper class for jQuery Flexigrid plugin component. * * The format must be like this: * <code> * {"total":2,"page":1,"rows":[ * {"personTitle":"Mr","partyName":"Test8325","personDateOfBirth":"1970-07-12"}, * {"personTitle":"Ms","partyName":"Ms Susan Jones","personDateOfBirth":"1955-11-27"} * ]} * </code> * * @author bright_zheng * * @param <T>: the generic type of the specific domain */ public class JsonDataWrapper<T> implements Serializable { private static final long serialVersionUID = -538629307783721872L; public JsonDataWrapper(int total, int page, List<T> rows){ this.total = total; this.page = page; this.rows = rows; } private int total; private int page; private List<T> rows; public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public List<T> getRows() { return rows; } public void setRows(List<T> rows) { this.rows = rows; } }
四、Controller的单元测试变得很可为且简单
以前的项目从来不做controller层的测试,用了Spring MVC 3这一点就不再难为情,做吧:
public class HotelsControllerTest { private static HandlerMapping handlerMapping; private static HandlerAdapter handlerAdapter; private static MockServletContext msc; @BeforeClass public static void setUp() { String[] configs = { "file:src/main/resources/context-*.xml", "file:src/main/webapp/WEB-INF/webapp-servlet.xml" }; XmlWebApplicationContext context = new XmlWebApplicationContext(); context.setConfigLocations(configs); msc = new MockServletContext(); context.setServletContext(msc); context.refresh(); msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); ApplicationContextManager manager = new ApplicationContextManager(); manager.setApplicationContext(context); handlerMapping = (HandlerMapping) ApplicationContextManager.getContext().getBean(DefaultAnnotationHandlerMapping.class); handlerAdapter = (HandlerAdapter) ApplicationContextManager.getContext().getBean(ApplicationContextManager.getContext().getBeanNamesForType(AnnotationMethodHandlerAdapter.class)[0]); } @Test public void list() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); request.setRequestURI("/hotels"); request.addParameter("booking.id", "1002"); request.addParameter("hotel.name", ""); request.setMethod("POST"); //HandlerMapping HandlerExecutionChain chain = handlerMapping.getHandler(request); Assert.assertEquals(true, chain.getHandler() instanceof HotelsController); //HandlerAdapter final ModelAndView mav = handlerAdapter.handle(request, response, chain.getHandler()); //Assert logic Assert.assertEquals("hotels/search", mav.getViewName()); } }
需要说明一下 :由于当前最想版本的Spring(Test) 3.0.5还不支持@ContextConfiguration的注解式context file注入,所以还需要写个setUp处理下,否则类似于Tiles的加载过程会有错误,因为没有ServletContext。3.1的版本应该有更好的解决方案,参见:https://jira.springsource.org/browse/SPR-5243 。
Service等其他layer就没有这类问题,测试的写法将变得更加优雅,贴个出来:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"file:src/main/resources/context-*.xml" }) public class DefaultServiceImplTest { /** @Autowired works if we put @ContextConfiguration at junit type */ @Autowired @Qualifier("hotelService") private HotelService<Hotel> hotelService; @Test public void insert() { Hotel hotel = new Hotel(); hotel.setAddress("addr"); hotel.setCity("Singapore"); hotel.setCountry("Singapore"); hotel.setName("Great Hotel"); hotel.setPrice(new BigDecimal(200)); hotel.setState("Harbarfront"); hotel.setZip("010024"); hotelService.insert(hotel); } }
五、ACL可以写一个HandlerInterceptorAdapter,在“事前”拦截。
由于Spring是Restful friendly的framework,做ACL就不要用过滤器了,用interceptor吧:
public class AclInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = Logger.getLogger(AclInterceptor.class); /** default servlet prefix */ private static final String DEFAULT_SERVLET_PREFIX = "/servlet"; /** will be injected from context configuration file */ private AclService service; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String currentUri = request.getRequestURI(); boolean isAccessible = true; //only intercept for annotated business controllers Controller c = AnnotationUtils.findAnnotation(handler.getClass(), Controller.class); if(c!=null){ String[] grantedResource = getGrantedResource(request); if(grantedResource==null || grantedResource.length==0){ throw new AccessDeniedException("No resource granted"); } isAccessible = service.isAccessible(grantedResource, currentUri); if(logger.isDebugEnabled()){ logger.debug("ACL interceptor excueted. Accessible for Uri[" + currentUri +"] = " + isAccessible); } //if isAccessible==true, throw custom AccessDeniedException if(!isAccessible) throw new AccessDeniedException(); } return isAccessible; } /** * transfer the original Uri to resource Uri * e.g.: * original Uri: /servlet/hotels/ajax * target Uri : /hotels/ajax * @param originalUri * @return */ protected String getUri(String originalUri){ return originalUri.substring(DEFAULT_SERVLET_PREFIX.length()); } /** * Get the granted resource from session * @param request * @return */ protected String[] getGrantedResource(HttpServletRequest request){ //get the resources from current session //String[] uriResourcePattern = (String[]) request.getSession().getAttribute("uriResourcePattern"); //TODO: mock data here String[] uriResourcePattern = new String[]{"/**"}; return uriResourcePattern; } public void setService(AclService service) { this.service = service; } }
注 :上面还有TODO部分,很简单,登录后把当然用户可访问的Ant path style的URI Resources放到session中,作为一个String[],这里拿来出匹配即可,建议匹配就用org.springframework.util.AntPathMatcher。
六、对于Ajax Form Validation,正在寻求更佳的解禁方案。
Spring 3已经支持@Valid的注解式validation,又一个JSR,但通过我研究代码发现,默认的org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.java实现还是非常封闭,并不能很好的实现binding后执行业务代码前处理,所以目前的实现办法还不算优雅。
已经实现,大致的思路是:
1)发出ajax form post请求(用jQuery);
2)正常mapping到controller的方法中处理;
3)做form validation;
4)不管怎样,forward到一个解析错误消息的JSP,叫ajaxFormValidatorResult.jsp;
5)再写一个jquery plugin,叫errorBinder.js,解析错误并自定binding为Tooltip,如果没错误就正常submit
贴个简单的demo效果,欢迎拍砖。
==Before
==After
补充说明:后面陆续补充的心得,就不在这里出现了,而是以跟帖的形式存在,便于讨论吧
评论
参数里增加了@ModelAttribute("customerCommand") CustomerCommand customerCommand 就正常显示了,我很纳闷我hello这个方法根本用不到CustomerCommand customerCommand难道必须要在这声明?
其实你的hello方法的执行终点是渲染hello.jsp,此时hello.jsp会试图在request获取modelAttribute,但如果你按原来的写法,显然没有名字为customerCommand的modelAttribute,所以会有绑定异常,而你加上就可以了。
另外,你也可以直接new一个然后put到request里去,也是OK的,此时方法上可以不要这个参数(@ModelAttribute("customerCommand") CustomerCommand customerCommand)了:
model.addAttribute("customerCommand",new CustomerCommand ());
BTW:也许显式的写@ModelAttribute也是一种好习惯,但我一般懒得写,放在方法上即可,此时Spring能处理好,即使你没put到request去:
@RequestMapping(value="/hello",method = RequestMethod.GET) public String hello(CustomerCommand customerCommand,Model model) { model.addAttribute("hello","helloworld!"); return "hello"; }
我改成一样的了,还是不行,报customerCommand没有绑定。
服了:
action="/addcustomer.do"
but
@RequestMapping(value="/addcustomer",method = RequestMethod.GET)
9成9是低级错误所致
现在有了一点进展,事情是这样的,我一上来访问的helloController,并返回输入customer信息的页面hello.jsp。
@RequestMapping(value="/hello",method = RequestMethod.GET) public String hello(Model model) { model.addAttribute("hello","helloworld!"); return "hello"; }
hello.jsp
<form:form method="get" modelAttribute="customerCommand" action="/xrequirement/addcustomer"> ${hello}<br> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
customerController
@RequestMapping(value="/addcustomer",method = RequestMethod.GET) public String addCustomer(@ModelAttribute("customerCommand") CustomerCommand customerCommand) throws Exception { ....... }
此时会报customerCommand找不到绑定的异常,但是如果我把helloController改成这样
@RequestMapping(value="/hello",method = RequestMethod.GET) public String hello(@ModelAttribute("customerCommand") CustomerCommand customerCommand,Model model) { model.addAttribute("hello","helloworld!"); return "hello"; }
参数里增加了@ModelAttribute("customerCommand") CustomerCommand customerCommand 就正常显示了,我很纳闷我hello这个方法根本用不到CustomerCommand customerCommand难道必须要在这声明?
我改成一样的了,还是不行,报customerCommand没有绑定。
服了:
action="/addcustomer.do"
but
@RequestMapping(value="/addcustomer",method = RequestMethod.GET)
9成9是低级错误所致
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
你把相关代码贴出来,这个问题不应该是个棘手问题,肯定是哪里犯了低级错误。
代码包括:
1. CustomerComand.java
2. 在controller的addcustomer方法
3. 加上这个jsp的form,就OK了
好的
CustomerComand.java
public class CustomerCommand { private String firstname ; private String lastname ; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } }
在controller的addcustomer方法
@Controller public class CustomerController { private CustomerRepository customerRepository; @RequestMapping(value="/addcustomer",method = RequestMethod.GET) public String addCustomer(CustomerCommand customerCommand) throws Exception { //do something } public void setCustomerRepository(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } }
加上这个jsp的form
<form:form method="post" modelAttribute="customerCommand" action="/addcustomer.do"> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
非常感谢楼主细心解答!
老兄,你form里是post
但你mapping的地方是get(@RequestMapping(value="/addcustomer",method = RequestMethod.GET))
其他我觉得不会有问题,你调整过来看看,直接去掉method的限制好了。
我改成一样的了,还是不行,报customerCommand没有绑定。
呵呵 谢谢你的解答 大概有些理解了 照你的说法 modelAttribute 只是一种写法习惯 用来在VIEW中分辨哪个实体 即使不写也没有关系 是这个意思吗?
no
modelAttribute是form tag的属性,其实说白了就是用来构造类似于EL的path.
比如,modelAttribute="hotel",而<form:input path="name" .../>,这binding的时候就是
hotel.name
而如果需要多个bean在一个form里,就要modelAttribute="someWrapperBean",而
<form:input就要写:
<form:input path="beanA.name".../>
<form:input path="beanB.title".../>
此时:
someWrapperBean.beanA.name,someWrapperBean.beanB.title,。。。
如此而已
PS :modelAttribute 是怎么反射到POJO的
咱俩的问题估计是一样的,我也不知道怎么可能通过modelAttribute里的CustomerCommand名找到com.command.CustomerCommand并实例化,所以不知道modelAttribute怎么bind到POJO。
这里涉及Spring大量的conventions,我没细看这部分,我印象中大概的思路会是:
1.找到mapping的方法,然后逐个匹配方法的param
2.如果找到非“内置”的param(有一个列表,十几个这样),就试图去实例化并填充数据
此时,如果看到一个com.command.CustomerCommand,那就先实例化一个,然后从request取东西出来populate,取啥呢,取名字为“customerCommand”的modelAttribute,这就是convention。
binding部分大概也就是BeanUtils那样的思路,有深度研究的兄弟可以来给大家分享一下
呵呵 谢谢你的解答 大概有些理解了 照你的说法 modelAttribute 只是一种写法习惯 用来在VIEW中分辨哪个实体 即使不写也没有关系 是这个意思吗?
PS :modelAttribute 是怎么反射到POJO的
咱俩的问题估计是一样的,我也不知道怎么可能通过modelAttribute里的CustomerCommand名找到com.command.CustomerCommand并实例化,所以不知道modelAttribute怎么bind到POJO。
这里涉及Spring大量的conventions,我没细看这部分,我印象中大概的思路会是:
1.找到mapping的方法,然后逐个匹配方法的param
2.如果找到非“内置”的param(有一个列表,十几个这样),就试图去实例化并填充数据
此时,如果看到一个com.command.CustomerCommand,那就先实例化一个,然后从request取东西出来populate,取啥呢,取名字为“customerCommand”的modelAttribute,这就是convention。
binding部分大概也就是BeanUtils那样的思路,有深度研究的兄弟可以来给大家分享一下
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
你把相关代码贴出来,这个问题不应该是个棘手问题,肯定是哪里犯了低级错误。
代码包括:
1. CustomerComand.java
2. 在controller的addcustomer方法
3. 加上这个jsp的form,就OK了
好的
CustomerComand.java
public class CustomerCommand { private String firstname ; private String lastname ; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } }
在controller的addcustomer方法
@Controller public class CustomerController { private CustomerRepository customerRepository; @RequestMapping(value="/addcustomer",method = RequestMethod.GET) public String addCustomer(CustomerCommand customerCommand) throws Exception { //do something } public void setCustomerRepository(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } }
加上这个jsp的form
<form:form method="post" modelAttribute="customerCommand" action="/addcustomer.do"> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
非常感谢楼主细心解答!
老兄,你form里是post
但你mapping的地方是get(@RequestMapping(value="/addcustomer",method = RequestMethod.GET))
其他我觉得不会有问题,你调整过来看看,直接去掉method的限制好了。
PS :modelAttribute 是怎么反射到POJO的
咱俩的问题估计是一样的,我也不知道怎么可能通过modelAttribute里的CustomerCommand名找到com.command.CustomerCommand并实例化,所以不知道modelAttribute怎么bind到POJO。
PS :modelAttribute 是怎么反射到POJO的
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
你把相关代码贴出来,这个问题不应该是个棘手问题,肯定是哪里犯了低级错误。
代码包括:
1. CustomerComand.java
2. 在controller的addcustomer方法
3. 加上这个jsp的form,就OK了
好的
CustomerComand.java
public class CustomerCommand { private String firstname ; private String lastname ; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } }
在controller的addcustomer方法
@Controller public class CustomerController { private CustomerRepository customerRepository; @RequestMapping(value="/addcustomer",method = RequestMethod.GET) public String addCustomer(CustomerCommand customerCommand) throws Exception { //do something } public void setCustomerRepository(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } }
加上这个jsp的form
<form:form method="post" modelAttribute="customerCommand" action="/addcustomer.do"> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
非常感谢楼主细心解答!
看来SpringMVC3.x变得灵活多了,我以前用过一段时间2.x,所以习惯了返回ModelAndView的那个思路,有点转不过来弯。
我逐一说说吧,欢迎探讨
那这样的话,原来与simpleFormController配合使用的validator怎么弄呢?
还有,前面littcai问的问题好像没有被证明解答,我也有同样疑问:
Validation在Spring MVC 3.X上变得非常flexible,一般而言有两种方法:
1、遵循@Valid的注解式validation,此为JSR-303 Bean Validation API,其实与Spring没有啥关系,就是把annotation放到bean中,根据annotation的规则定义进行“自动化”校验——老实说不是特别喜欢,感觉可控性差一些;
2、自己写个validator,注意此时不再需要实现特定的接口咯,比如这样就可以:
public class HotelQueryValidator{ public void validate(Hotel hotel, Errors errors) { if(StringUtils.isEmpty(hotel.getName())){ //demo for multiple message //global error, and this message doesn't exist in file errors.reject("form.global.error", "Errors found by form validation"); //field error by rejectValue(...) errors.rejectValue("hotel.name", "hotel.query.keyword.required"); errors.rejectValue("hotel.name", "hotel.query.keyword.size",new Object[]{"1","10"},null); } } }
然后在controller的方法中调用即可,其原理无非是校验-》网errors加错误,错误一般有两大类:global error用reject,field error用rejectValue。
当然了,自己用一些必要的pattern去写一套简单的validator工具也是推荐的,从我看来。
ExceptionHandler似乎只能处理普通请求(处理方式是跳转到特定错误页面),但是对ajax请求就不行了,无法返回包含错误信息的json。
在Spring MVC 3.x世界里,ajax跟一般的request几乎没有任何区别,你可以:
1、按照正常的validation去做,然后看到有error后,构建你需要的json,比如{"isError":"true"},当然了,最好写一个简单的bean,put进去然后直接return,Spring MVC会帮我们转换为json格式的了
2、显示throw naming exception,然后用ExceptionHandler捕获并采用特定的view来显示
以前的simpleFormController可以实现同一个url处理一个表单的显示和提交,估计改成annotation模式以后不行了,需要分成两个方法和url处理了。
那如何区分是显示还是提交呢,难道还要专门有个什么flag?
因为一般的页面初始化,也要做少量的就绪逻辑吧,难道直接访问jsp不经controller,然后submit才到controller?
我倒是没注意通过类似于直接越过我们的controller而直接到view的,比如这样配置:
<mvc:view-controller path="/intro" />
我倒是想找时间试一下。
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
你把相关代码贴出来,这个问题不应该是个棘手问题,肯定是哪里犯了低级错误。
代码包括:
1. CustomerComand.java
2. 在controller的addcustomer方法
3. 加上这个jsp的form,就OK了
<form:form method="post" modelAttribute="customerCommand" action="/xrequirement/addcustomer.do"> ${hello}<br> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
我明白你的意思了。
以前的simpleFormController可以实现同一个url处理一个表单的显示和提交,估计改成annotation模式以后不行了,需要分成两个方法和url处理了。
<form:form method="post" modelAttribute="customerCommand" action="/xrequirement/addcustomer.do"> ${hello}<br> FIRSTNAME: <form:input path="firstname"/><br> LASTNAME: <form:input path="lastname"/><br> <input type="submit" value="regist"/> </form:form>
这是我页面里东西,我觉得和/xrequirement/addcustomer.do提交到的controller没关系,因为这个页面刚一打开初始化就报错java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerComand' available as request attribute,那时候还没有提交呢。是不是要求command要和controller在同一个包下?
感谢楼主回复,按照上面的配置方法
<form:form method="post" modelAttribute="CustomerCommand" action="/xrequirement/addcustomer.do">
我出了一个错误,说没有绑定'CustomerCommand'
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'CustomerCommand' available as request attribute
我突然想到一个问题,如果我的CustomerCommand.class在com.command.CustomerCommand,modelAttribute怎么知道去这个路径找到并实例化CustomerCommand?是不是哪还少配置了什么?
需要你把controller对应的方法也贴出来,咋一看还真不知道,如果你的controller的方法为:
@RequestMapping(value="/xrequirement/addcustomer.do") public void addcustomer(WebRequest request, CustomerCommand command, Model model){ ... }
应该可以的吧。
还有,会不会是
modelAttribute="CustomerCommand"
改为
modelAttribute="customerCommand"
发表评论
-
Netty + Protobuf 的客户端模式运用和问题探讨
2012-05-14 16:04 6158使用NETTY之前,当然需要先看一下所带的samples。 ... -
实战:使用JMeter的Java Sampler轻松定制自己的benchmark
2012-05-06 22:08 4491以前碰到更多的是WEB APP ... -
如何从零开始编写一个企业级的生物匹配引擎
2012-04-29 23:35 1322考虑编写一篇文章,以分享个人的一些所谓引擎策划、架构、实现和验 ... -
JBoss在单机下多实例的配置备忘
2011-06-17 16:41 2553版本:jboss-5.1.0.GA + JDK 1.6 ... -
能不能让log4j跑的“更快”,对业务总体执行时间影响更小?
2011-06-10 00:00 2799最近事情不多,翻了一下log4j的源代码,发现这个一直跟 ... -
大家都用什么Maven插件?及本人的几个常用插件分享
2011-01-25 12:47 5150两个月前我只是一直知道有Maven,但从来没用过也没这个计划, ... -
JSTL/EL如何方便高效的访问Constants和CodeTable(存储于DB的应用系统变量)
2010-12-20 12:35 7926之前只是简单的使用JSTL/EL进行输出,一般的思路很简单:r ... -
让Ajax框架Buffalo支持JSON协议而非仅仅自定义的XML协议[JS前端及单元测试完成]
2010-01-14 16:01 2861Buffalo默认实现了一套很棒的自定义XML协议(具体请参考 ... -
Ajax框架Buffalo深度研究
2010-01-11 14:37 2234Buffalo深度研究 ——2010.01.11, IT进行 ...
相关推荐
5. **Spring MVC 3.x annotated controller的几点心得体会** - 作者可能分享了在实际开发中使用注解控制器的经验和技巧,包括错误处理、数据验证、模型绑定等方面。 6. **SpringMVC数据绑定** - 数据绑定是Spring...
7.1. Alternate Spring MVC configuration 7.1.1. Customizing DispatcherServlet configuration 7.1.2. Adding additional servlets and filters 7.1.3. Declaring DispatcherServlet in web.xml 7.2. Processing ...
Exporting a lazily initialized bean (which implements SelfNaming and is annotated with ManagedResource annotation) gives IllegalStateException [SPR-17592] #22124 MockHttpServletRequest changes Accept-...
书中的内容主要围绕以下几个关键知识点展开: 1. **图灵机模型**:图灵机是计算理论的基石,它是一个抽象的计算设备,能够模拟任何算法的逻辑。书中详细介绍了图灵机的工作原理,包括状态、带子、读写头和规则,...
在学习Apollo 1.0源码时,可以关注以下几个关键点: - 数据流处理:了解如何从不同传感器获取原始数据,并将其转化为可供其他模块使用的格式。 - 算法实现:深入研究感知模块中的目标检测算法,如YOLO、Faster R-...
Margaret A. Ellis, Bjarne Stroustrup-The Annotated C++ Reference Manual
Edited by a Lead Program Manager on Microsoft's .NET Framework team, .NET Framework Standard Library Annotated Reference, Volume 1, is the definitive reference for the .NET Framework base class ...
在Spring MVC中,当需要将Java对象转换为JSON格式发送给客户端时,有时会遇到返回对象包含大量冗余属性的情况,这可能导致不必要的网络流量消耗。为了解决这个问题,我们可以实现一个动态擦除属性的机制,使得在序列...
Following this, you will explore how to implement the request handling layer using Spring annotated controllers. Other highlights include learning how to build the Java DAO implementation layer by ...
Following this, you will explore how to implement the request handling layer using Spring annotated controllers. Other highlights include learning how to build the Java DAO implementation layer by ...
redis-3.0-annotated-unstable.zipredis-3.0-annotated-unstable.zipredis-3.0-annotated-unstable.zipredis-3.0-annotated-unstable.zip
13. 配置控制器(Controller)以处理Web层的请求,并将视图解析器配置到Spring MVC配置文件中,以便Spring MVC框架知道如何渲染视图。 通过上述步骤,可以将Spring、SpringMVC、JPA和Hibernate集成到一起,构建一个...
2. **注解驱动开发(Annotated Controllers)**:在Spring 2.5中,可以使用`@Controller`、`@RequestMapping`等注解来声明控制器类和处理HTTP请求的方法,大大简化了Web应用程序的开发。 3. **AOP增强**:Spring ...
The Annotated C++ Reference Manual.part2
在"Annotated Database"中,这些关键点已预先标注,可以用于训练和优化关键点检测算法,如Dlib的HOG(Histogram of Oriented Gradients)或基于深度学习的MTCNN(Multi-task Cascaded Convolutional Networks)。...
The Annotated C++ Reference Manual
而《The Thinking in Java Annotated Solution Guide》则是对原书习题的详尽解答,帮助读者巩固所学知识并解决实际编程问题。 这个压缩包包含的是书中所有代码示例,对于学习Java编程非常有帮助。以下是这些代码...
The Annotated C++ Reference Manual (共11部分) 传说中的原版巨作,不差页