springMVC例子
Spring 3.1 MVC 例子,教程
“子日:温故而知新”,如果简单回顾一下整个Java平台上的Web开发历程,将极大有助于我们理
解当前各个Web开发框架存在的背景和先进性,最主要的是有助于我们平滑过渡至Spring MVC的世界
中去。所以,不妨让我们从最初的Servlet独行天下的时代说起。
Servlet独行天下的时代
话说Servlet是当年Java平台上第一个用于Web开发的技术。相对于CGI(Common Gateway
Interface)时代来说,Servlet的提出是一个很大的进步,它运行于w曲容器(Web Container)之内,提
供了Session和对象生命周期管理等功能。最主要的,Servlet依然是Java类,从中直接访问Java平台的
各种服务,并使用相应的APl支持是很自然的事情,比如调用业务对象,使用JDBC进行数据访问等。
Servlet本身并非万能的,它的强项在于无缝地衔接业务对象与Web层对象之间的调用,以及二进
制显示内容的输出等。但在当时开发人员只有Servlet这一种技术可以选择的时候,或许是不得不,也
或许是盲从,又或许根本就是图一时的省事儿,单一的Servlet被赋予了过多的使命,从而导致了开发
过程中出现的一系列的弊病。最常见的,就是称为“神奇Servlet(Magic Servlet)”的普遍存在。在
“神奇Servlet”中,开发人员会将各种逻辑混杂于一处,包括流程控制逻辑、视图显示逻辑、业务逻辑、
数据访问逻辑等,这就造成了后期系统的难以维护等一系列问题。
(1)配置基础装备。每个符合Java EE规范的web应用程序都需要符合相应的目录结构,如图所示。
工作之初,我们需要构建web应用的基础结构。不过,现在的IDE通常都有良好的Web开发支
持,MyEclipse9.1下载与安装请参见:http://guoyiqi.iteye.com/blog/1182653
剩下的只是按照Wizard的说明构建一个web应用的工程就行了。
a)配置web.xml。我们需要将org.springframework.Web.servlet.DispatcherServlet和
org.springframework.Web.context.ContextLoaderListener通过<servlet>和<listener>元素添
加至web.xml部署描述符文件中。另外,出于其他目的考虑,我们还可以
添加相应的Filter以及ServletContextListener以处理字符编码和Log4j初始化等配置内容,这些
完全根据当前应用程序的需求情况来决定。现在,我们的web.xml看起来如代码清单所示。
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <!-- Filter 定义 -->
- <!-- Character Encoding filter -->
- <filter>
- <filter-name>encodingFilter</filter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>UTF-8</param-value>
- </init-param>
- <init-param>
- <param-name>forceEncoding</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <!-- Filter 映射 -->
- <filter-mapping>
- <filter-name>encodingFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!--Spring的ApplicationContext 载入 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- Spring 刷新Introspector防止内存泄露 -->
- <listener>
- <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
- </listener>
- <!--配置Sring MVC的核心控制器DispatcherServlet -->
- <servlet>
- <servlet-name>dispatcherServlet</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- </servlet>
- <!--为DispatcherServlet建立映射 -->
- <servlet-mapping>
- <servlet-name>dispatcherServlet</servlet-name>
- <url-pattern>*.do</url-pattern>
- </servlet-mapping>
- <!-- session超时定义,单位为分钟 -->
- <session-config>
- <session-timeout>20</session-timeout>
- </session-config>
- <!-- 出错页面定义 -->
- <error-page>
- <exception-type>java.lang.Throwable</exception-type>
- <location>/common/500.jsp</location>
- </error-page>
- <error-page>
- <error-code>500</error-code>
- <location>/common/500.jsp</location>
- </error-page>
- <error-page>
- <error-code>404</error-code>
- <location>/common/404.jsp</location>
- </error-page>
- <error-page>
- <error-code>403</error-code>
- <location>/common/403.jsp</location>
- </error-page>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Filter 定义 --> <!-- Character Encoding filter --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <!-- Filter 映射 --> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--Spring的ApplicationContext 载入 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring 刷新Introspector防止内存泄露 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!--配置Sring MVC的核心控制器DispatcherServlet --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <!--为DispatcherServlet建立映射 --> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- session超时定义,单位为分钟 --> <session-config> <session-timeout>20</session-timeout> </session-config> <!-- 出错页面定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/common/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/common/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/common/404.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/common/403.jsp</location> </error-page> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
b)WebApplicationContext文件的添加。我们需要在web-inf目录下添加org.springframework.Web.servlet.Dispatcherservlet和org.springframework.Web.context.ContextLoaderListener对应的WebApplicationContext配置文件(/WEB-INF/applicationContext.xml和
/WEB-INF/dispatcherServlet-servlet.xml)。这完全可以从Spring下载文件包中的sample目录下任何一个Web
应用程序中复制过来。只不过,需要根据命名规则修改相应的文件名称。当然,复制过来的文件内容
最好是清空,只保留可以在当前应用中能够通用的配置内容。
以上基础设施构建完成之后,我们开始“盖楼”。
(2)开发独立的业务逻辑。对于一个设计良好的web应用程序来说,虽然Web层依赖于业务层对象,
但业务层却不应该对Web层有任何的依赖。web层只应该看作是公开业务逻辑的一种视角或者交互方
式。这样做或者说这样看待系统的好处在于,业务层可以独立设计并实现,而不需要关心最终通过什
么手段将服务公开给用户。鉴于这样的理念,我们完全可以从业务层开始着手设计和实现。
entity - 领域模型层
使用Sql First的开发模式,先设计数据库,参考DBA的性能意见而不要太片面追求OO化的表结构。
- package entity;
- public class Author {
- private String auId;
- private String auLname;
- private String phone;
- public String getAuId() {
- return auId;
- }
- public void setAuId(String auId) {
- this.auId = auId;
- }
- public String getAuLname() {
- return auLname;
- }
- public void setAuLname(String auLname) {
- this.auLname = auLname;
- }
- public String getPhone() {
- return phone;
- }
- public void setPhone(String phone) {
- this.phone = phone;
- }
- }
package entity; public class Author { private String auId; private String auLname; private String phone; public String getAuId() { return auId; } public void setAuId(String auId) { this.auId = auId; } public String getAuLname() { return auLname; } public void setAuLname(String auLname) { this.auLname = auLname; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
access - 资源访问层
资源访问层包括对数据库、JMS、外部的WebService等的访问。
每个领域对象对应一个DAO类。
- package dao;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.List;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.RowMapper;
- import org.springframework.jdbc.core.RowMapperResultSetExtractor;
- import entity.Author;
- public class AuthorDao {
- class UserRowMapper implements RowMapper{
- public Object mapRow(ResultSet rs,int index) throws SQLException {
- Author author = new Author();
- author.setAuId(rs.getString(1));
- author.setAuLname(rs.getString(2));
- author.setPhone(rs.getString(3));
- return author;
- }
- }
- private JdbcTemplate jdbcTemplate;
- public JdbcTemplate getJdbcTemplate() {
- return jdbcTemplate;
- }
- public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- }
- public List select(String where) {
- List list;
- String sql = "select * from authors";
- list = jdbcTemplate.query(sql,new RowMapperResultSetExtractor(new UserRowMapper()));
- return list;
- }
- }
package dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapperResultSetExtractor; import entity.Author; public class AuthorDao { class UserRowMapper implements RowMapper{ public Object mapRow(ResultSet rs,int index) throws SQLException { Author author = new Author(); author.setAuId(rs.getString(1)); author.setAuLname(rs.getString(2)); author.setPhone(rs.getString(3)); return author; } } private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List select(String where) { List list; String sql = "select * from authors"; list = jdbcTemplate.query(sql,new RowMapperResultSetExtractor(new UserRowMapper())); return list; } }
service - 业务逻辑层
Service层有两类对象,
一类是领域对象管理类(Entity Manager), 按领域对象划分,每个Manager类负责管理多个紧密关联的Entity的增删改查及其业务逻辑。
一类是业务服务类(Service),按业务脚本划分,可能会访问到多种领域对象与Manager类。
- package service;
- import java.util.List;
- import dao.AuthorDao;
- import entity.Author;
- public class AuthorService {
- private AuthorDao authorDao;
- public AuthorDao getAuthorDao() {
- return authorDao;
- }
- public void setAuthorDao(AuthorDao authorDao) {
- this.authorDao = authorDao;
- }
- public List<Author> getAuthorsList(){
- return authorDao.select("");
- }
- }
package service; import java.util.List; import dao.AuthorDao; import entity.Author; public class AuthorService { private AuthorDao authorDao; public AuthorDao getAuthorDao() { return authorDao; } public void setAuthorDao(AuthorDao authorDao) { this.authorDao = authorDao; } public List<Author> getAuthorsList(){ return authorDao.select(""); } }
web - Web MVC层
MVC框架使用SpringMVC框架 ,每个Action实现一组页面操作。
- package web;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.mvc.Controller;
- import service.AuthorService;
- import entity.Author;
- public class AuthorAction implements Controller {
- private AuthorService authorService;
- private String viewName; // 用于获取配置文件中的viewPage属性
- public ModelAndView handleRequest(HttpServletRequest req,
- HttpServletResponse res) throws Exception {
- Map<String,List<Author>> model=new HashMap<String,List<Author>>();
- List<Author> authors=authorService.getAuthorsList();
- model.put("model", authors);
- return new ModelAndView(this.getViewName(), model); // 调用getViewPage获取要返回的页面
- }
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
- public AuthorService getAuthorService() {
- return authorService;
- }
- public void setAuthorService(AuthorService authorService) {
- this.authorService = authorService;
- }
- }
package web; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import service.AuthorService; import entity.Author; public class AuthorAction implements Controller { private AuthorService authorService; private String viewName; // 用于获取配置文件中的viewPage属性 public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) throws Exception { Map<String,List<Author>> model=new HashMap<String,List<Author>>(); List<Author> authors=authorService.getAuthorsList(); model.put("model", authors); return new ModelAndView(this.getViewName(), model); // 调用getViewPage获取要返回的页面 } public String getViewName() { return viewName; } public void setViewName(String viewName) { this.viewName = viewName; } public AuthorService getAuthorService() { return authorService; } public void setAuthorService(AuthorService authorService) { this.authorService = authorService; } }
View模板用JSP2.0 , 尽量使用纯html+JSP2.0 EL展示页面。
- <%@ page language="java" import="java.util.*,entity.*" pageEncoding="UTF-8"%>
- <%@ include file="/common/taglibs.jsp" %>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'authorsList.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- This is my JSP page2. <br>
- <c:forEach items="${model}" var="author">
- ${author.auId},${author.auLname }${author.phone }<br/>
- </c:forEach>
- </body>
- </html>
<%@ page language="java" import="java.util.*,entity.*" pageEncoding="UTF-8"%> <%@ include file="/common/taglibs.jsp" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'authorsList.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> This is my JSP page2. <br> <c:forEach items="${model}" var="author"> ${author.auId},${author.auLname }${author.phone }<br/> </c:forEach> </body> </html>
Javascript与Ajax使用JQuery或Dojo Base。
尽量采用CSS框架规范CSS的布局。
(3)配置
applicationContext.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" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
- <!-- 定义受环境影响易变的变量 -->
- <bean
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
- <property name="ignoreResourceNotFound" value="true" />
- <property name="locations">
- <list>
- <!-- 标准配置 -->
- <value>/WEB-INF/application.properties</value>
- </list>
- </property>
- </bean>
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${jdbc.driver}" />
- <property name="url" value="${jdbc.url}" />
- <property name="username" value="${jdbc.username}" />
- <property name="password" value="${jdbc.password}"></property>
- <!-- Connection Pooling Info -->
- <property name="maxIdle" value="${dbcp.maxIdle}" />
- <property name="maxActive" value="${dbcp.maxActive}" />
- <property name="defaultAutoCommit" value="false" />
- <property name="timeBetweenEvictionRunsMillis" value="3600000" />
- <property name="minEvictableIdleTimeMillis" value="3600000" />
- </bean>
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource">
- <ref bean="dataSource" />
- </property>
- </bean>
- <bean id="authorDao" class="dao.AuthorDao">
- <property name="jdbcTemplate">
- <ref bean="jdbcTemplate" />
- </property>
- </bean>
- <bean id="authorService" class="service.AuthorService">
- <property name="authorDao">
- <ref bean="authorDao" />
- </property>
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <!-- 定义受环境影响易变的变量 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <property name="ignoreResourceNotFound" value="true" /> <property name="locations"> <list> <!-- 标准配置 --> <value>/WEB-INF/application.properties</value> </list> </property> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- Connection Info --> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}"></property> <!-- Connection Pooling Info --> <property name="maxIdle" value="${dbcp.maxIdle}" /> <property name="maxActive" value="${dbcp.maxActive}" /> <property name="defaultAutoCommit" value="false" /> <property name="timeBetweenEvictionRunsMillis" value="3600000" /> <property name="minEvictableIdleTimeMillis" value="3600000" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <bean id="authorDao" class="dao.AuthorDao"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> <bean id="authorService" class="service.AuthorService"> <property name="authorDao"> <ref bean="authorDao" /> </property> </bean> </beans>
dispatcherServlet-servlet.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="localeResolver"
- class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
- </bean>
- <!--配置控制器的映射-->
- <bean id="urlMapping"
- class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- <property name="mappings">
- <props>
- <prop key="authorAction.do">authorAction</prop>
- </props>
- </property>
- </bean>
- <!--配置视图-->
- <bean id="viewResolver"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/content/" />
- <property name="suffix" value=".jsp" />
- </bean>
- <!--指定控制器的实现类,并且配置其参数的值-->
- <bean id="authorAction" class="web.AuthorAction">
- <property name="viewName">
- <value>authorsList</value>
- </property>
- <property name="authorService">
- <ref bean="authorService" />
- </property>
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"> </bean> <!--配置控制器的映射--> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="authorAction.do">authorAction</prop> </props> </property> </bean> <!--配置视图--> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/content/" /> <property name="suffix" value=".jsp" /> </bean> <!--指定控制器的实现类,并且配置其参数的值--> <bean id="authorAction" class="web.AuthorAction"> <property name="viewName"> <value>authorsList</value> </property> <property name="authorService"> <ref bean="authorService" /> </property> </bean> </beans>
(4)发布运行