Spring学习心得(一)
本人用Java做了不少的WEB工程,但都是用Java基本的servlet+DAO实现的,对几种web框架的认识算是小白级别。一直很想学习Spring框架的使用,但是网上的资料都是介绍Spring框架的优点,教程也繁杂臃肿,纯属备考模式,本人写这一系列博客就是为了和大家分享动手实战Spring框架时的一些经验和教训。
第一步,用eclipse建立一个普通的WEB工程,并在tomcat上测试运行。(本步骤时Java web基础,不再赘述,直接跳过)。
第二步,把Spring依赖的一些jar包导入,本文附件中有Spring所需要的大部分jar包,直接将所需要的jar复制到“WebRoot/WEB-INF/lib/”中即可,spring所依赖基本的jar有asm、beans、context、core、expression、web和commons-logging;如果做持久层还需要jdbc、transaction、dbcp、pool等jar。这些jar附件中都有,可以根据需要选择合适的版本使用。
第三步,配置Spring,就是在XML文件中对Spring做一些基本的配置,让web系统能识别Spring。
1.在web.xml文件中加入Spring配置文件信息
<display-name>MySpring</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
其中<context-param>是工程全局配置,<param-name>要求是唯一的,对于Spring配置中<param-name>要求是contextConfigLocation,<param-value>则对应了spring配置XML文件的路径。<listener>中配置的class是继承了ServletContextListener类的监听器类,spring的ja包中的org.springframework.web.context.ContextLoaderListener即可。在tomcat启动web工程时会读取这些参数来初始化servlet上下文。
2.在 在WEB-INF/ 下建一个 spring-conf.xml (名字和路径都随便了, 跟第一步的配置对应就行)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="TestBo" class="servlet.TestBo"> <property name="name" value="123"></property> </bean> <bean id="TestAction" class="servlet.TestAction"> <property name="name" value="abc"></property> <property name="testbo" ref="TestBo"></property> </bean> </beans>
现在我们已经完成了spring的基本配置,接下来写代码测试。
第四步,TestServlet.java
package servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** * Servlet implementation class TestServlet */ @WebServlet("/TestServlet") public class TestServlet extends HttpServlet { private static final long serialVersionUID = 1L; TestAction ta; /** * @see HttpServlet#HttpServlet() */ public TestServlet() { super(); // TODO Auto-generated constructor stub } /** * service * @throws IOException */ public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{ PrintWriter pw=response.getWriter(); pw.write(ta.getTestbo().getName()); pw.flush(); pw.close(); } public void init(ServletConfig servletConfig) throws ServletException{ servletConfig.getServletContext(); ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletConfig.getServletContext()); this.ta = (TestAction) ctx.getBean("TestAction"); this.ta.sayHello(); System.out.println("TestServlet init"); // TestAction ta = new TestAction(); // ta.sayHello(); } }
TestBo.java
package servlet; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class TestBo { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
TestAction.java
package servlet; public class TestAction { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } private TestBo testbo; public void sayHello() { // TODO Auto-generated method stub System.out.println(name); } public TestBo getTestbo() { return testbo; } public void setTestbo(TestBo testbo) { this.testbo = testbo; } }
后记:
1.本人一开始在启动tomcat时一直遇到以下错误:
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TestAction' defined in ServletContext resource [/WEB-INF/spring-conf.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'testbo' of bean class [servlet.TestAction]: Bean property 'testbo' is not writable or has an invalid setter method. Did you mean 'testbo1'? at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1279) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380) at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4729) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'testbo' of bean class [servlet.TestAction]: Bean property 'testbo' is not writable or has an invalid setter method. Did you mean 'testbo1'? at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:801) at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:651) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:59) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1276) ... 25 more
tomcat已经说得很清楚了,在TestAction类中的TestBo变量找不到注入方法,原因是我自己写的set方法命名有误,为了防止错误我们最好使用eclipse自动生成set、get方法。
2. spring的注入流程为:
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletConfig.getServletContext());
得到servlet的上下文环境,主要是得到spring配置文件路径。
this.ta = (TestAction) ctx.getBean("TestAction");
根据TestAction的bean实例化TestAction对象,其中TestAction的bean中
<property name="testbo" ref="TestBo"></property>
name必须和变量名一直,ref指向另一个Bean的id.