- 浏览: 916243 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (498)
- J2EE (52)
- 数据库 (17)
- java基础 (43)
- web技术 (19)
- 程序设计 (6)
- 操作系统 (18)
- IT资讯 (7)
- 我的IT生活 (12)
- 学习笔记 (9)
- Jquery (25)
- JavaScript (18)
- spring (40)
- Hibernate (12)
- Struts (10)
- YUI (2)
- Extjs (22)
- .net (0)
- Eclipse (10)
- 社会主义 (2)
- 服务器 (9)
- CSS (8)
- 网络安全 (16)
- 版本控制 (9)
- PHP (2)
- Oracle (42)
- SQL server (1)
- Mysql (11)
- 项目管理 (3)
- 开发工具使用 (10)
- SQL语句 (7)
- Perl (0)
- Shell (6)
- 漏洞 (4)
- ibatis (5)
- hacker (2)
- SQL注入 (6)
- Hacker工具 (2)
- 入侵和渗透 (7)
- 插件/组件 (2)
- 最爱开源 (5)
- 常用软件 (2)
- DOS (1)
- HTML (2)
- Android (9)
- CMS (1)
- portal (8)
- Linux (7)
- OSGI (1)
- Mina (5)
- maven (2)
- hadoop (7)
- twitter storm (2)
- sap hana (0)
- OAuth (0)
- RESTful (1)
- Nginx (4)
- flex (1)
- Dubbo (1)
- redis (1)
- springMVC (1)
- node.js (1)
- solr (2)
- Flume (1)
- MongoDB (2)
- ElasticSearch (1)
最新评论
-
M_drm:
请问要怎么设置浏览器才不报没权限呢?
用JS在页面调用本地可执行文件的方法(ACTIVEX) -
Alexniver:
官方文档。When importing data into I ...
mysql导入数据过慢 解决方法 -
camelwoo:
我记得 Criteria 可以做连接查询与子查询,也可以做分页 ...
Hibernate总结篇二 -
zhenglongfei:
楼主如果SubKeyName 这个节点不存在,怎么办??怎么用 ...
Java操作注册表 -
yxx676229549:
用log4j 2 了
logback
最近拿Spring MVC 3.x做项目,用了最新的系列相关Annotation来做Controller,有几点心得体会值得分享。
转载请注明 :IT进行时(zhengxianquan AT hotmail.com) from
http://itstarting.iteye.com/
一、编写一个AbstractController.java,所有的Controller必须扩展
除了获得Template Design Pattern的好处之外,还能一点,那就是放置全局的@InitBinder:
二、每个域都应该有一个Controller,且做好URI规划
大家都知道Spring MVC 3.x是完全支持Restful的,我们把URI做好规划,对于诸如ACL的实现会有很大的帮助。建议的URI规划如下:{Domain}[/{SubDomain}]/{BusinessAction}/{ID}。比如:
hotels/bookings/cancel/{id} ——表示此URI匹配hotels域的bookings子域,将要进行的是取消某项booking的操作。代码如下:
另外还有几个重要原因:
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如下:
这样,我们其实根本就不需要进行额外的JSON转换了,Spring MVC 3会根据请求的格式自行转换:
注 :我上面的JsonDataWrapper只是我自己做的一个简单的wrapper,目的是为jQuery Flexigrid plugin做数据准备的。还是贴出来吧:
四、Controller的单元测试变得很可为且简单
以前的项目从来不做controller层的测试,用了Spring MVC 3这一点就不再难为情,做吧:
需要说明一下 :由于当前最想版本的Spring(Test) 3.0.5还不支持@ContextConfiguration的注解式context file注入,所以还需要写个setUp处理下,否则类似于Tiles的加载过程会有错误,因为没有ServletContext。3.1的版本应该有更好的解决方案,参见:https://jira.springsource.org/browse/SPR-5243 。
Service等其他layer就没有这类问题,测试的写法将变得更加优雅,贴个出来:
五、ACL可以写一个HandlerInterceptorAdapter,在“事前”拦截。
由于Spring是Restful friendly的framework,做ACL就不要用过滤器了,用interceptor吧:
注 :上面还有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
转载请注明 :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
发表评论
-
使用EhCache和Spring AOP实现计算结果缓存
2012-08-07 10:47 1061原文:http://kim-miao.iteye.com/bl ... -
wsdl axis2 spring
2012-08-02 17:06 934http://renxiangzyq.iteye.com/ ... -
spring 监听器 IntrospectorCleanupListener简介
2012-08-02 17:00 1070"在服务器运行过程中,Spring不停的运行的计划任 ... -
Quartz的cron时间表达式
2012-04-11 17:33 1321一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素 ... -
Spring 框架的设计理念与设计模式分析
2012-03-06 13:49 998Spring 框架的设计理念与设计模式分析 http://ww ... -
Spring事务配置的五种方式
2012-03-04 10:40 1402前段时间对Spring的事务配置做了比较深入的研究,在此之间对 ... -
Spring技术内幕:深入解析Spring架构与设计原理(转)
2011-07-01 16:58 1174http://jiwenke.iteye.com/blo ... -
AOP 的利器:ASM 3.0 介绍
2011-06-29 13:48 1423AOP 的利器:ASM 3.0 介绍 http://www ... -
在非web环境中使用spring
2011-06-29 13:34 4230Spring再强大,也要面对降临的问题--因为Spr ... -
Spring LDAP 1.3.1 发布
2010-12-05 21:17 1216http://www.iteye.com/news/18834 ... -
Spring开始关注移动应用开发,发布Spring Mobile,Spring Android
2010-11-29 11:01 3372近日,Roy Clarkson发布了S ... -
SSH全注解-annotation详细配置
2010-11-21 18:50 2477如果有点SSH框架的经验,这个很好理解.配置不难. 配置an ... -
spring安全框架应用
2010-10-11 22:09 3257第一步 将spring-security-core-2.0. ... -
spring3.0.4 新增加的注解(mvc:resources)
2010-08-23 22:19 8951从spring3.0.3发布以后一直等待spring3.0.4 ... -
spring2.0与spring2.5的差别
2010-08-22 00:14 1659资料:http://ajava.org/online/spri ... -
利用Spring框架封装的JavaMail现实同步或异步邮件发送
2010-08-21 23:25 5562利用Spring框架封装的JavaMail现实同步或异步邮件发 ... -
领略Spring 3.x 时代的Spring MVC
2010-08-21 23:20 1440鼎鼎大名的Spring框架3.0版在12月5日由其作者之一—— ... -
使用 Spring 2.5 基于注解驱动的 Spring MVC
2010-08-21 23:16 1039概述 继 Spring 2.0 对 Spring MVC ... -
Spring2.0压缩包目录说明
2010-08-21 22:44 5841、 Spring2.0压缩包目录说明 aspectj目录 ... -
Spring的起源和背景 以及你为什么要使用Spring
2010-08-17 09:04 1546Spring的起源和背景 Rod J ...
相关推荐
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部分) 传说中的原版巨作,不差页