<web-app version="2.4" xmlns="https://java.sun.com/xml/ns/j2ee">
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list>
</web-app>
<beans>
<bean id="springappController" class="spring.SpringappController"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props><prop key="/hello.htm">springappController</prop></props>
</property>
</bean>
</beans>
package spring;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.*;
import java.io.IOException;
import org.apache.log4j.Logger;
public class SpringappController implements Controller {
static Logger logger = Logger.getLogger(SpringappController.class);
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
logger.info("SpringappController - returning hello view");
return new ModelAndView("hello.jsp");
}
}
<%@ page contentType="text/html; charset=Big5" %>
<html><body><h1>Hello - Spring Application</h1><p>Greetings.</p></body></html>
Run Configuration → Server → Launch URI: `/springapp/hello.htm` → 控制台輸出日志、訪問頁面成功。
<%@ taglib prefix="c" uri="https://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="https://java.sun.com/jstl/fmt" %>
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<c:redirect url="/hello.htm"/>
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<html><head><title><fmt:message key="title"/></title></head>
<body><h1><fmt:message key="heading"/></h1>
<p><fmt:message key="greeting"/> <c:out value="${now}"/></p>
</body></html>
public class SpringappController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) throws Exception {
String now = new java.util.Date().toString();
logger.info("returning hello view with " + now);
return new ModelAndView("hello", "now", now); // 視圖邏輯名 "hello"
}
}
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
title=SpringApp
heading=Hello :: SpringApp
greeting=Greetings, it is now
package bus;
public class Product implements Serializable {
private String description; private Double price;
// getter/setter...
}
package bus;
public class ProductManager implements Serializable {
private List products;
public List getProducts() { return products; }
public void setProducts(List products) { this.products = products; }
}
<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"/><property name="price" value="5.75"/></bean>
<bean id="product2" class="bus.Product">
<property name="description" value="Table"/><property name="price" value="75.25"/></bean>
<bean id="product3" class="bus.Product">
<property name="description" value="Chair"/><property name="price" value="22.79"/></bean>
public ModelAndView handleRequest(...) {
Map model = new HashMap<>();
model.put("now", new Date().toString());
model.put("products", getProductManager().getProducts());
return new ModelAndView("hello", "model", model);
}
<h3>Products</h3>
<c:forEach items="${model.products}" var="prod">
<c:out value="${prod.description}"/> <i>$<c:out value="${prod.price}"/></i><br><br>
</c:forEach>
CREATE TABLE products (
id INTEGER NOT NULL PRIMARY KEY,
description VARCHAR(255),
price DECIMAL(15,2)
);
CREATE INDEX products_description ON products(description);
INSERT INTO products VALUES (1, 'Lamp', 5.78);
INSERT INTO products VALUES (2, 'Table', 75.29);
INSERT INTO products VALUES (3, 'Chair', 22.81);
package db;
public interface ProductManagerDao {
List getProductList();
void increasePrice(Product prod, int pct);
}
package db;
public class ProductManagerDaoJdbc implements ProductManagerDao {
protected final Log logger = LogFactory.getLog(getClass());
private DataSource dataSource;
public List getProductList() {
logger.info("Getting products!");
return new ProductQuery(dataSource).execute();
}
public void increasePrice(Product prod, int pct) {
SqlUpdate su = new SqlUpdate(dataSource,
"UPDATE products SET price = price * (100 + ?) / 100 WHERE id = ?");
su.declareParameter(new SqlParameter("increase", Types.INTEGER));
su.declareParameter(new SqlParameter("id", Types.INTEGER));
su.compile();
su.update(new Object[]{pct, prod.getId()});
}
public void setDataSource(DataSource ds) { this.dataSource = ds; }
private class ProductQuery extends MappingSqlQuery {
ProductQuery(DataSource ds) { super(ds, "SELECT id, description, price FROM products"); compile(); }
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Product p = new Product();
p.setId(rs.getInt("id"));
p.setDescription(rs.getString("description"));
p.setPrice(new Double(rs.getDouble("price")));
return p;
}
}
}
package bus;
public class ProductManager {
private ProductManagerDao productManagerDao;
public List getProducts() { return productManagerDao.getProductList(); }
public void increasePrice(int pct) {
for (Product p : getProducts()) productManagerDao.increasePrice(p, pct);
}
// setter/getter...
}
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:/home/trisberg/workspace/springapp/db/test"/>
<property name="username" value="sa"/><property name="password" value=""/>
</bean>
<bean id="prodManDao" class="db.ProductManagerDaoJdbc">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="prodMan" class="bus.ProductManager">
<property name="productManagerDao" ref="prodManDao"/>
</bean>
<!-- Controller、urlMapping、viewResolver、messageSource 同前 -->
<bean id="priceIncreaseValidator" class="bus.PriceIncreaseValidator"/>
<bean id="priceIncreaseForm" class="web.PriceIncreaseFormController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="priceIncrease"/>
<property name="commandClass" value="bus.PriceIncrease"/>
<property name="validator" ref="priceIncreaseValidator"/>
<property name="formView" value="priceincrease"/>
<property name="successView" value="hello.htm"/>
<property name="productManager" ref="prodMan"/>
</bean>
// tests.MockProductManagerDaoImpl - 內存實現,無需數據庫
// tests.TestProductManagerDaoJdbc - 真實數據庫集成測試
// tests.TestProductManager - 業務邏輯單元測試 (Mock DAO)
JBuilder 2005 + Spring 1.2 的這套教程,完整展示了 **Spring MVC 核心設計**:DispatcherServlet 前端控制器、HandlerMapping、Controller 接口、ModelAndView、ViewResolver、簡單表單控制器、驗證器、JDBC 抽象、聲明式事務 (後續版本)。今日 Spring Boot 只是將這些「約定優於配置」、內嵌容器、Starter 依賴管理、Actuator 監控,核心編程模型**一脈相承**。