3、 减小Controler对页面地址的依赖 在上面的Controler中,return new ModelAndView("WEB-INF/jsp/hello.jsp", "now", now);指出了jsp页面的绝对路径,这可以改变。 首先在springapp-servlet.xml中增加一个bean定义: <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property> <property name="prefix"><value>/WEB-INF/jsp/</value></property> <property name="suffix"><value>.jsp</value></property> </bean> 然后把Controler的返回写为: return new ModelAndView("hello", "now", now); 这样InternalResourceViewResolver在返回页面之前,会自动加上prefix和suffix。 (。。。我不清楚这有什么用,如果我的路径除了/WEB-INF/jsp之外还有多个,那该怎么加呢?。。。看来只好都放到jsp下面了) 4、 bean定义中把其属性定义成其他的bean 在springapp-servlet.xml中,我们做出如下定义 <beans> <bean id="springappController" class="web.SpringappController"> <property name="productManager"> <ref bean="prodMan"/> </property> </bean> <bean id="prodMan" class="bus.ProductManager"> <property name="products"> <list> <ref bean="product1"/> <ref bean="product2"/> <ref bean="product3"/> </list> </property> </bean> <bean id="product1" class="bus.Product"> <property name="description"><value>Lamp</value></property> <property name="price"><value>5.75</value></property> </bean> <bean id="product2" class="bus.Product"> <property name="description"><value>Table</value></property> <property name="price"><value>75.25</value></property> </bean> <bean id="product3" class="bus.Product"> <property name="description"><value>Chair</value></property> <property name="price"><value>22.79</value></property> </bean> </beans> 有2点需要理解的: 1、 可以直接利用<property name="price"><value>75.25</value></property>为bean的属性赋值,也可以用<property name="productManager"> <ref bean="prodMan"/> </property>将属性赋为另一个定义的bean。 2、 这些被定义为属性的bean是在Web Module被加载时同时被加载的并且赋给属性的。一旦加载完成,就可以直接使用,因此没有必要在Class定义中为这些属性赋值(但必须有这些属性的setter定义)。比如按照上面的XML定义,我们把SpringappController写成这样: public class SpringappController implements Controller { private ProductManager prodMan; public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map myModel = new HashMap(); myModel.put("products", getProductManager().getProducts()); return new ModelAndView("hello", "model", myModel); } public void setProductManager(ProductManager pm) { prodMan = pm; } public ProductManager getProductManager() { return prodMan; } } 可以看到,没有为属性private ProductManager prodMan赋值,但定义了它的setter――setProductManager,这个setter在<bean id="springappController">被加载的时候自动调用了,以给prodMan赋上值。 5、 单元测试 在WEB应用开发中,我们习惯的测试方法是实际测试,即把WEB Module部署好了之后,用测试用例测试。这样效率很低,因为编译、打包、部署、测试的过程很费时间。 Spring的思想是及早测试以发现问题。 例子中,为测试SpringappController编写了测试程序: package tests; import java.util.Map; import java.util.List; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.web.servlet.ModelAndView; import web.SpringappController; import bus.ProductManager; import bus.Product; public class TestSpringappController extends TestCase { private ApplicationContext ac; public void setUp() throws IOException { ac = new FileSystemXmlApplicationContext("src/tests/WEB-INF/springapp-servlet.xml"); } public void testHandleRequest() throws ServletException, IOException { SpringappController sc = (SpringappController) ac.getBean("springappController"); ModelAndView mav = sc.handleRequest((HttpServletRequest) null, (HttpServletResponse) null); Map m = mav.getModel(); List pl = (List) ((Map) m.get("model")).get("products"); Product p1 = (Product) pl.get(0); assertEquals("Lamp", p1.getDescription()); Product p2 = (Product) pl.get(1); assertEquals("Table", p2.getDescription()); Product p3 = (Product) pl.get(2); assertEquals("Chair", p3.getDescription()); } } 测试类继承自junit.framework.TestCase。测试的时候,主要是测试controler产生的model对不对。当然在上面的例子中,测试没有多大的意义,因为model的产生太简单了。但是如果model产生的逻辑非常复杂,那这种测试是非常有意义的。 注意上面例子中的 public void setUp() throws IOException { ac = new FileSystemXmlApplicationContext ( "src/tests/WEB-INF/springapp-servlet.xml" ); } 它为controler创建了一个类似于app server的环境(bean的加载就是在这里完成的) |
|