该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-12-20
itstarting 写道 unsid 写道 参数里增加了@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"; } 奥,你要怎么说我就理解modelAttribute的出处了,原来是从request里取CustomerCommand对象 但是每次打开一个带form的页面时候,都要从上一个controller里写一个model.addAttribute("customerCommand",new CustomerCommand ());么?这多不优雅啊,至少controller中加入了和这个controller关系不大的代码,你一般是这么写么?还是有什么更好的写法? |
|
返回顶楼 | |
发表时间:2010-12-20
unsid 写道 itstarting 写道 unsid 写道 参数里增加了@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"; } 奥,你要怎么说我就理解modelAttribute的出处了,原来是从request里取CustomerCommand对象 但是每次打开一个带form的页面时候,都要从上一个controller里写一个model.addAttribute("customerCommand",new CustomerCommand ());么?这多不优雅啊,至少controller中加入了和这个controller关系不大的代码,你一般是这么写么?还是有什么更好的写法? new一个我是不会干的,多烦啊 我认为有两种办法可以值得一试: 1、在方法上简单加上这个参数; public String hello(CustomerCommand customerCommand,Model model) { ... } 2、写一个专门的方法来初始化并就绪一个新的bean,这个方法需要加上@ModelAttribute 我一般用第一种。 第二种不是很好——所有方法都要执行,代码虽然“优雅”点但效率不高 试想一下,你要导航到一个form了,一般而言重要初始化一些东西,那么直接拿到这个从方法参数来的东西加工就是了 |
|
返回顶楼 | |
发表时间:2010-12-25
最近在考虑一个问题,就是话说springMVC支持rest风格的URI,这样非常方便
你是怎么规划URI的呢?我觉得web应用的页面无非三种列表页面,详细信息页面和录入信息窗口页面,那么如果是以书为例,rest风格API怎么规划合理: 1、图书列表 /project/booktype/3/booklist 2、图书详细信息/project/booktype/3/booklist/4 3、录入页面怎么描述?/project/newbook? 如果录入页面分很多栏信息?/project/newbook/1? 如果这些新西兰嵌入到一个父frame里怎么表示frame?/project/newbookframe? 4、试想如果一个网站能在“最新图书列表”,“图书分类检索”里都能查到同一本书,那么一本图书对应两个URI? /project/newbook或者project/newbookframe这种风格的URI不觉得很不REST么? |
|
返回顶楼 | |
发表时间:2011-01-19
体验很不错,但是唯有测试有点牵强:
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]); } ... } 这段代码没必要,分析原因: 1.WebApplicationContext本身继承自ApplicationContext, 所以,使用@ContextConfiguration(locations={"spring-*.xml"}完全可以用ApplicationContext加载所有类 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-dao.xml", "classpath:spring-service.xml", "classpath:spring-web.xml"}, inheritLocations = true) @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public class UserControllerTest { private static HandlerMapping handlerMapping; private static HandlerAdapter handlerAdapter; @Before public void setUp() { handlerMapping = ApplicationContextHook.applicationContext.getBean(DefaultAnnotationHandlerMapping.class); handlerAdapter = ApplicationContextHook.applicationContext.getBean(AnnotationMethodHandlerAdapter.class); } ... } hook spring的application即可 |
|
返回顶楼 | |
发表时间:2011-01-26
请问搂主..
这个spring的验证说是要jsr-303规范.. 就是不在spring的范畴里面.. 我怎么打不出@valid注解.myeclipse没有提示.. 我换了1.6的jdk还是编译错误. |
|
返回顶楼 | |
发表时间:2011-01-26
fq_jeid 写道 请问搂主..
这个spring的验证说是要jsr-303规范.. 就是不在spring的范畴里面.. 我怎么打不出@valid注解.myeclipse没有提示.. 我换了1.6的jdk还是编译错误. 这个需要更多的依赖,一个是api另一个是实现,目前比较推荐的实现来自于hibernate。 比如: <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.0.2.GA</version> </dependency> |
|
返回顶楼 | |
发表时间:2011-01-27
itstarting 写道 fq_jeid 写道 请问搂主..
这个spring的验证说是要jsr-303规范.. 就是不在spring的范畴里面.. 我怎么打不出@valid注解.myeclipse没有提示.. 我换了1.6的jdk还是编译错误. 这个需要更多的依赖,一个是api另一个是实现,目前比较推荐的实现来自于hibernate。 比如: <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.0.2.GA</version> </dependency> 项目中也用上JSR-303,做验证挺方便的,给个简单例子吧 <!-- 开启MVC注解 --> <mvc:annotation-driven /> Bean代码: public class User { private int id; @NotBlank(message = "用户名不能为空") @Size(min = 4, max = 16, message = "用户名长度必须为{min} ~ {max} 位") private String username; @NotBlank(message = "密码不能为空") @Size(min = 6, max = 20, message = "密码度必须为{min} ~ {max} 位") private String password; // 省略setter,getter } Controller代码: @Controller @RequestMapping("/user/*") public class UserControler { @Resource private UserManager userManager; @RequestMapping(value = "save.do", method = RequestMethod.POST) public String save(@Valid User user, BindingResult result) { if (result.hasErrors()) { // 验证到错误时 return "user/input"; } userManager.save(user); return "user/success"; } } 当然,页面上也要对应有,不过也可以用上form标签来绑定 <input type="text" name="username" /> <input type="password" name="password" /> |
|
返回顶楼 | |
发表时间:2011-01-28
kongruxi 写道 项目中也用上JSR-303,做验证挺方便的,给个简单例子吧 <!-- 开启MVC注解 --> <mvc:annotation-driven /> Bean代码: public class User { private int id; @NotBlank(message = "用户名不能为空") @Size(min = 4, max = 16, message = "用户名长度必须为{min} ~ {max} 位") private String username; @NotBlank(message = "密码不能为空") @Size(min = 6, max = 20, message = "密码度必须为{min} ~ {max} 位") private String password; // 省略setter,getter } Controller代码: @Controller @RequestMapping("/user/*") public class UserControler { @Resource private UserManager userManager; @RequestMapping(value = "save.do", method = RequestMethod.POST) public String save(@Valid User user, BindingResult result) { if (result.hasErrors()) { // 验证到错误时 return "user/input"; } userManager.save(user); return "user/success"; } } 当然,页面上也要对应有,不过也可以用上form标签来绑定 <input type="text" name="username" /> <input type="password" name="password" /> 我是担心验证的地方太多,逻辑看起来不方便(总是感觉不太完整),毕竟除了简单的表单验证之外,还有更为复杂的业务逻辑校验,所以我们为了统一,全部废掉JSR-303的做法,反而用了最原始的做法,即编写一套简单的验证工具,基于此工具编码验证。 |
|
返回顶楼 | |
发表时间:2011-01-28
不知spring mvc今后是否会取代struts 呵呵
|
|
返回顶楼 | |
发表时间:2011-01-28
其实我觉得原来的SpringMVC在validation这一块已经做得很不错了:
一般的输入合法性验证靠集成Commons-Validator框架,规则写在配置文件里,而且可以实现服务端客户端双重验证,灵活、集中、便于维护; 对于复杂的纯服务端验证,比如校验email是否已经存在,可以用SpringMVC自己的Validator框架,验证逻辑封装在Validator然后注入SimpleFormController,验证逻辑不会和业务逻辑混在一起,也很优雅。 而且上述两种验证可以同时使用,而且可以做到验证失败后,表单回填和错误信息的显示,集成的天衣无缝。 |
|
返回顶楼 | |