使用Spring开发RESTful API
使用spring mvc可以实现RESTful API。这次不得不用spring,我发现我的博客里一篇spring的笔记都没有!
现在还是从头来吧。
官方文档:
http://static.springsource.org/spring/docs/
http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html
/ 和/*的区别:
/是默认的servlet配置(就是没有被其映射截获的都会被这个处理,包含静态资源),而/*则完全包括了所有的路劲。
http://tomcat.apache.org/tomcat-7.0-doc/default-servlet.html
开始就犯个错:
copy网上的
<context:component-scan base-package="xxx.*> </context:component-scan>
结果一直无法映射,xxx包里的类根本没加载,再看文档,没那里说支持*,(有的blog里面甚至还有***).改为
<context:component-scan base-package="xxx”> </context:component-scan>就可以了。我看还是直接看文档最靠谱.
关于mapping的问题
A类配置了根/abc/
B类则不能配置根为/abc/efg,配置了虽不报错也无效
那么只好在A类里配置/efg到方法中
关于springmvc配置和spring配置
注意springmvc的配置应该和spring的配置分开,spring的配置是指关于spring 核心功能的配置,springmvc则应该视为web mvc架构的spring实现,例如springmvc中的注解只会应用mvc相关的功能例如controller,会忽略你在其配置中配置的其他像transaction注解,甚至覆盖service注解等。
所以应该在web.xml的listener中加载spring配置,而在web.xml中servlet中配置springmvc配置。而且springmvc控制器类应该和业务功能严格分离,这就要求你的springmvc控制器不能有transaction,service等注解,你必须将业务逻辑分离出来由控制器调用。
这个问题坑了我一把,我在springmvc中配置tranaction事务注解,结果事务注解总是没起作用,而spring却什么错误提示也没有,着实挖了个大坑。
参见:
http://stackoverflow.com/questions/10019426/spring-transactional-not-working
关于ServletContext
3.0之前可以使用ApplicationContextAware接口来获得WebApplicationContext,通过它来获得Servletcontext。
也可以这样:
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
那么这个ServletContextFactoryBean
就可以获得Servletcontext。
3.0之后servletContext默认就是存在Spring中的Bean,直接引用即可。
配置示例:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-application.xml</param-value> </context-param> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
关于事务
注解方式事务中,默认的是比较合适的(同一个事务,读写操作,需要事务级别),
但是是在异常抛出情况下回滚,而我们又要良好地返回错误,一种方法是将数据操作另作为一个方法以便事务处理,这样做很不方便,
因为你如果需要这个方法返回多个数据时就很麻烦了。还好有@ExceptionHandler这个机制,可以处理异常输出。
这个注解用于Controller方法上则会处理本controller的异常。
使用注解事务就需要aop,两种方式cglib和aspectJ,默认是cglib,如果实现了接口则是aspectJ.aspectJ需要注解所在方法实现接口,所以不太方便(当然如果你是设计控,那你就面向切面吧)。
注意注解事务所在方法需要时public的,否则不起作用,这个很容易忘掉。
两种都需要添加对应的依赖。
关于Property
没发现直接在配置里配置Property的例子,只能引用外部properties文件
默认还只能用一个properties配置
http://www.cnblogs.com/cookray/archive/2012/08/08/2627713.html
可以设置PropertyPlaceholderConfigurer的properties属性来引用Properties类。
关于异常:
Could not initialize class net.sf.cglib.proxy.Enhancer
出现这个一般是应该使用cglib-nodep而不是cglib这个包,maven见http://mvnrepository.com/artifact/cglib/cglib-nodep
使用别名查询时报sql语句不合法,找不到某列,实际上是应该自定义RowMapper,从里面找出对应列。
关于定时任务:
目前spring只支持Quartz1.x,不支持2.x以上。如果报
java.lang.IncompatibleClassChangeError异常就是这个原因。
cron表达式:http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
其中?问题对于day of week和day of month要注意。
两个不能同时用*,如果表示无所谓天,则一个用*一个用?.这是由于day有两个配置”且”条件。
配置示例:
<!-- cron job --> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="cronJob"/> <property name="cronExpression" value="${cron.expression}" /> </bean> <bean id="cronJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="gongxifacai.CronJob" /> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> </list> </property> </bean>
参见:
spring 3.0 应用springmvc 构造RESTful URL 详细讲解
REST IN SPRING 3: RESTTEMPLATE
http://www.ibm.com/developerworks/cn/web/wa-spring3webserv/index.html
http://www.cnblogs.com/edwardlauxh/category/277224.html 较为详细