完整版本和源码在http://haoxing272.download.csdn.net/处有下载
环境
eclipse3.2、myeclipse5.0,Jboss 4.0.3 , sql server2000 sp3
原理简介
在java企业应用领域,ejb的功能强大同ejb的配置复杂,难于学习一样出名。但在以前我们又有什么办法呢?只有硬着头皮来学ejb。真有点“明知山有虎,偏向虎山行”的精神。现在的形势有了乐观的变化,java开源的持续走红,使得开发java企业级应用不再局限于ejb领域。下面简要介绍一下怎样采用开源的Spring,Hibernate以及Struts构建一个轻量级的架构。
1、整体架构介绍
在软件工程领域,为了降低模块耦合度,提高模块的可重用性,分层一直是广为采纳的一个方法。其实分层还可以使开发人员专注于某一层进行开发,使得软件开发的分工变细,提高生产效率。
一个企业级的java应用,通常分为以下几层:UI层,业务逻辑层,数据持久层,域对象层。下面对这几层分别作简要介绍:
域对象层:具体的实体类,如老师,学生等等这些具体的类(注意:需要与数据库中的某一表对应),由持久层类完成。
数据持久层:主要负责与底层的数据库打交道。这里采用Spring封装的Hibernate操作来简化实际的编码。主要的操作为CRUD(create ,read,update,delete),由DAO完成。
业务逻辑层:主要负责具体的业务处理。通过Spring的IOC以及AOP实现各个功能的耦合相连,业务逻辑由service来完成,service通过调用DAO操作数据库,实现业务逻辑。service由Struts的Action类来调用。
UI层:负责与用户交互,包括:接受用户的请求,把处理结果返回给用户。目前主要采用struts来做UI层,虽然比起Tapestry以及JSF这些事件驱动的表现层技术而言,Struts的设计显得有些老土,但它目前仍是表现层事实上的标准,所以我们还是选用它。
内容
通过hibernate建立与表users相对应的类Users。
在Struts框架创建的index.jsp的表单中用户名和密码,action通过类的方法判别输入信息是否与数据库中一条记录的信息一致。如果一致,转到next.jsp页面,显示所有的用户信息。如果与每条记录都不一致,则要求重新输入。
步骤
1、预备工作:用sql server 2000创建一个test数据库,再创建一个users表,包含两个字段username和password。脚本如下
CREATE DATABASE test;
USE test;
CREATE TABLE users (
id int(11) NOT NULL idntity(1,1),
username varchar(20) NOT NULL default '',
password varchar(20) default '',
PRIMARY KEY (id)
)
打开myeclipse的database explore透视图
图5-1 打开数据库浏览器透视图
右键单击左侧的空白区域 ,点击 new 按钮
图5-2 打开数据库连接(一)
图5-3 打开数据库连接(二)
测试数据库配置是否成功。
2、新建一个myeclipse的web工程,命名为aaa
图5-4 创建web工程
3、引入Spring包
右键工程名
图5-5 准备增加Spring包
图5-6 选定要增加的Spring包
注意:这里为了省得以后再添加spring的相关包,所以一次性的选中了所有的包。选中Copy选项,它会把这些包拷贝到/WebRoot/WEB-INF/lib目录下,方便以后的实际部署。然后点击“Next”。
图5-7 选择Spring配置文件(applicationContext.xml)路径
4、添加hibernate包
图5-8添加hibernate包
系统会检测到该工程已经添加了Spring包,选择使用Spring的配置文件( ApplicationContext.xml )
图5-9 选择hibernate配置文件(一)
图5-10 选择hibernate配置文件和SessionFactory ID
图5-11 设定Bean Id并选择DB Profile
图5-12 不要创建SessionFactory class
最后点击Finish按钮,在最后即可。
5、修改库文件
和以往不同,Spring2.0并不是把所有的包加到lib目录下就能运行工程的,而且把所有的包加到lib目录下会产生冲突。由于MyEclipse5.5对Spring2.0支持还不太成熟,它在加入Spring组件时会把不需要的包加进去。因此需要手动对lib目录下的包进行增、删、改。
(1)删除文件
进入工程的Webroot/WEB-INF/lib目录,以“详细信息”方式排序所有文件,找到以下的六个文件并删除:asm- 2.2.2 .jar、asm.jar、asm-commons-2.2.2.jar、asm-util-2.2.2.jar、asm-attr.jar、cglib-2.1.3.jar。
图 5-13-1 删除不需要的文件
(2) 增加文件
到MyEclipse的安装目录下,进入eclipse/plugins文件夹,使用搜索功能找出commons-pool.jar文件,可能会有多个结果,只需要其中一个即可,把它放到lib目录下。
6、添加Struts2.0包
从www.apache.org 上下载struts2.0的包,一般情况下是struts-版本号-all.zip,打开里面的lib文件夹,把下图所示的包添加到工程的lib目录下。
图5-14 添加struts2.0包
完成后刷新工程。
7、搭建工程框架,写log4j.properties文件
在工程的src目录下新建几个包,方法为右键在src文件夹上点击,然后如图所示:
图5-15 新建一个包
图5-16 建好的包结构
其中:
Com.action包存放各个action文件。
Com.service包存放service接口
Com.service.impl包实现service接口。
Com.filter包存放过滤器文件,写这些文件为了解决中文问题。
Com.hibernate包存放hibernate映射文件和持久类。
Com.util包存入公共文件,如BaseService.java、BaseObject.java、BaseAction.java,如果不同的service调用同样的方法,可以把这些方法写在BaseService.java中,下面将详细说明。
先创建BaseObject类BaseObject.java:
右键点击com.util包,选择new->Class,如图所示:
图5-17 新建一个类
图5-18
package com.util;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
public class BaseObject implements Serializable {
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
public boolean equals(Object o) {
return EqualsBuilder.reflectionEquals(this, o);
}
public int hashCode(Object o) {
return HashCodeBuilder.reflectionHashCode(this);
}
protected String showDatetime(Date pidate) {
return getFormateDate(pidate, "yyyy-MM-dd HH:mm");
}
protected String showDate(Date pidate) {
return getFormateDate(pidate, "yyyy-MM-dd");
}
protected String showTime(Date pidate) {
return getFormateDate(pidate, "HH:mm");
}
private String getFormateDate(Date pidate, String formate) {
if (pidate == null) {
return null;
}
else {
return (new SimpleDateFormat(formate)).format(pidate);
}
}
}
再创建BaseService.java
图5-18 指定类名
在弹出来的对话框中指定类名为BaseService,点击选择其父类的“Browse”按钮。
然后在弹出来的对话框中选择超类名为HibernateDaoSupport,如图所示:
图5-19 选择父类
双击被选的父类(不用点“OK”按钮),然后点“Finish”完成BaseService.java的创建。Eclipse会自动跳到该文件下。暂时往BaseService.java中添加如下代码:
package com.util;
import java.io.Serializable;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class BaseService extends HibernateDaoSupport {
public Serializable insert(BaseObject obj) throws DataAccessException {
return getHibernateTemplate().save(obj);
}
public void update(BaseObject obj) throws DataAccessException {
getHibernateTemplate().update(obj);
}
public void delete(BaseObject obj) throws DataAccessException {
getHibernateTemplate().delete(obj);
}
public Object load(Class cls, Serializable id) throws DataAccessException {
return getHibernateTemplate().load(cls, id);
}
public List getAll(String hql,Object objs[]) throws DataAccessException{
if(objs == null)
return getHibernateTemplate().find(hql);
else
return getHibernateTemplate().find(hql,objs);
}
public Object getFirstObject(String hql,Object objs[]) throws DataAccessException{
Object ret = null;
List tmp = getAll(hql,objs);
if(tmp != null && tmp.size()>0)
ret = tmp.get(0);
return ret;
}
}
说明:在BaseService.java中定义了几个方法,包括插入、修改、删除、查询,需要的话直接调用即可。
用类似的方法新建BaseAction.java文件,选择其父类为ActionSupport,注意是com.opensymphony.xwork2.ActionSupport,另外两个是Struts1的。
接着,写log4j.properties文件,该文件的主要作用是对后台每一步操作在控制台中显示对应的日志信息,方便对程序的调试。
右键在src目录上点击,选择new->File,弹出如下图所示对话框,指定文件名为log4j.properties。然后点“Finish”。
图5-20 建立log4j.properties文件
往里面添加如下代码:
log4j.rootLogger=INFO, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
# Print only messages of level WARN or above in the package com.foo.
# log4j.logger.com.foo=WARN
#log4j.logger.au.gov.sa.health.oacis=DEBUG
#log4j.logger.org.apache.struts2=DEBUG
#log4j.logger.org.apache=INFO
#log4j.logger.org.hibernate=INFO
#log4j.logger.ca.uhn=INFO
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=INFO
#log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=DEBUG
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
这样当以后启动服务时会显示更为详细的日志信息。
8、为解决中文问题写过滤器文件
在com.filter包上点击右键,新建一个Class,命名为NewFilterDispatcher,选择其父类为FilterDispatcher,往里面添加如下代码:
public class NewFilterDispatcher extends FilterDispatcher {
private static String encoding = "GB2312";
public void init(FilterConfig filterConfig) throws ServletException {
super.init(filterConfig);
String encodingParam = filterConfig.getInitParameter("encoding");
if (encodingParam != null && encodingParam.trim().length() != 0) {
encoding = encodingParam;
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(encoding);
super.doFilter(request, response, chain);
}
}
再写一个过滤器类,命名为SetCharacterEncodingFilter,注意选择其接口为javax.Servlet.Filter,重写相应的方法,代码如下:
public class SetCharacterEncodingFilter implements Filter {
protected String encoding;
public SetCharacterEncodingFilter(){
super();
this.encoding = "GB2312";
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)throws IOException, ServletException {
try
{
request.setCharacterEncoding(this.encoding);
}
catch(UnsupportedEncodingException e)
{
throw new ServletException("Can't set incoming encoding to"+this.encoding);
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterconfig) throws ServletException {
this.encoding = filterconfig.getInitParameter("encoding");
}
}
9、写web.xml文件
在web.xml中把工程需要运行的配置文件按一定顺序描述清楚,它位于Webroot/WEB-INF目录下,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts</filter-name>
<filter-class>
com.filter.NewFilterDispatcher
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>com.filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- servlet>
<servlet-name>SpringContextServlet</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
注意其中有一段是注释,原因是Struts2需要Spring的listener来初始化Context,而不是SpringContextServlet。但是以后的版本可能需要Servlet,因此就不把它去掉了。
10、产生持久类
切换到database explore视图,右键点击 users 表的“Hibrnate Reverse Engineering”
图5-21 准备产生 O/R映射
弹出如下窗口,注意指定生成的映射文件的位置,为com.hibernate包中。还有注意“Base Persistence Class”选择BaseObject类。
图5-22 设定 O/R映射要产生的结果
点击 “next”,在弹出来的对话框中注意选择主键生成类型为“identity”,不同的数据库主键生成方式是不一样的,由于这里用的是SQL Server,所以选择使用“identity”。
图5-23 设定ID产生的方式
直接点“Finish”即可。然后从包视图中可以看到在com.hibernate包中多了三个文件,其中的Users.hbm.xml是映射文件,另外两个是映射类。同时注意在Spring的配置文件applicationContext.xml中的名为sessionFactory的bean中已经添加了关于映射文件的相关内容。
11、增加事务管理配置
在applicationContext.xml中,在id为“sessionFactory”的Bean后增加:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="baseProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
<!-- prop key="get*">PROPAGATION_REQUIRED,readOnly</prop-->
</props>
</property>
</bean>
12、建立业务逻辑层代码
右键点击com.service包,选择new->Interface,命名为UserService,在里面定义两个方法,添加如下代码:
package com.service;
import java.util.List;
import org.springframework.dao.DataAccessException;
public interface UserService {
public abstract boolean validate(String username,String password) throws DataAccessException;
public abstract List showAllUsers() throws DataAccessException;
}
然后在com.service.impl包里新建一个类,名为UserServiceImpl实现UserService接口,并继承BaseService类。
在该类中实现接口中定义的方法,代码如下:
public class UserServiceImpl extends BaseService implements UserService {
public boolean validate(String username, String password)
throws DataAccessException {
// TODO Auto-generated method stub
String hql = "from com.hibernate.Users where username=? and password=?";
if(getFirstObject(hql,new String[]{username,password}) != null)
return true;
else
return false;
}
public List showAllUsers() throws DataAccessException {
// TODO Auto-generated method stub
return getHibernateTemplate().find("from com.hibernate.Users");
}
同时在Spring的配置文件applicationContext.xml中添加如下配置项
<bean id="userService" parent="baseProxy">
<property name="target"><ref local="userServiceImpl" /></property>
</bean>
<bean id="userServiceImpl" class="com.service.impl.UserServiceImpl" autowire="byName" />
13、配置Struts2 Action
(1)写struts.properties文件
struts.properties文件内容:
### START SNIPPET: complete_file
### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
###
### Specifies the Configuration used to configure Struts
### one could extend org.apache.struts2.config.Configuration
### to build one's customize way of getting the configurations parameters into Struts
# struts.configuration=org.apache.struts2.config.DefaultConfiguration
### This can be used to set your default locale and encoding scheme
struts.locale=zh_CN
struts.i18n.encoding=GB2312
### if specified, the default object factory can be overridden here
### Note: short-hand notation is supported in some cases, such as "spring"
### Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
struts.objectFactory = spring
### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name
### indicates to the struts-spring integration if Class instances should be cached
### this should, until a future Spring release makes it possible, be left as true
### unless you know exactly what you are doing!
### valid values are: true, false (true is the default)
struts.objectFactory.spring.useClassCache = true
### if specified, the default object type determiner can be overridden here
### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger"
### Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here
### Note: if you have the xwork-tiger.jar within your classpath, GenericsObjectTypeDeterminer is used by default
### To disable tiger support use the "notiger" property value here.
#struts.objectTypeDeterminer = tiger
#struts.objectTypeDeterminer = notiger
### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser= jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
struts.multipart.maxSize=2097152
### Load custom property files (does not override struts.properties!)
# struts.custom.properties=application,org/apache/struts2/extension/custom
### How request URLs are mapped to and from actions
struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper
### Used by the DefaultActionMapper
### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
struts.action.extension=action
### Used by FilterDispatcher
### If true then Struts serves static content from inside its jar.
### If false then the static content must be available at <context_path>/struts
struts.serve.static=true
### Used by FilterDispatcher
### This is good for development where one wants changes to the static content be
### fetch on each request.
### NOTE: This will only have effect if struts.serve.static=true
### If true -> Struts will write out header for static contents such that they will
### be cached by web browsers (using Date, Cache-Content, Pragma, Expires)
### headers).
### If false -> Struts will write out header for static contents such that they are
### NOT to be cached by web browser (using Cache-Content, Pragma, Expires
### headers)
struts.serve.static.browserCache=true
### Set this to false if you wish to disable implicit dynamic method invocation
### via the URL request. This includes URLs like foo!bar.action, as well as params
### like method:bar (but not action:foo).
### An alternative to implicit dynamic method invocation is to use wildcard
### mappings, such as <action name="*/*" method="{2}" class="actions.{1}">
struts.enable.DynamicMethodInvocation = true
### use alternative syntax that requires %{} in most places
### to evaluate expressions for String attributes for tags
struts.tag.altSyntax=true
### when set to true, Struts will act much more friendly for developers. This
### includes:
### - struts.i18n.reload = true
### - struts.configuration.xml.reload = true
### - raising various debug or ignorable problems to errors
### For example: normally a request to foo.action?someUnknownField=true should
### be ignored (given that any value can come from the web and it
### should not be trusted). However, during development, it may be
### useful to know when these errors are happening and be told of
### them right away.
struts.devMode = false
### when set to true, resource bundles will be reloaded on _every_ request.
### this is good during development, but should never be used in production
struts.i18n.reload=false
### Standard UI theme
### Change this to reflect which path should be used for JSP control tag templates by default
struts.ui.theme=xhtml
struts.ui.templateDir=template
#sets the default template type. Either ftl, vm, or jsp
struts.ui.templateSuffix=ftl
### Configuration reloading
### This will cause the configuration to reload struts.xml when it is changed
struts.configuration.xml.reload=true
### Location of velocity.properties file. defaults to velocity.properties
# struts.velocity.configfile = velocity.properties
### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext
# struts.velocity.contexts =
### used to build URLs, such as the UrlTag
struts.url.http.port = 80
struts.url.https.port = 443
### possible values are: none, get or all
struts.url.includeParams = get
### Load custom default resource bundles
# struts.custom.i18n.resources=testmessages,testmessages2
### workaround for some app servers that don't handle HttpServletRequest.getParameterMap()
### often used for WebLogic, Orion, and OC4J
struts.dispatcher.parametersWorkaround = false
### configure the Freemarker Manager class to be used
### Allows user to plug-in customised Freemarker Manager if necessary
### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager
#struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager
### See the StrutsBeanWrapper javadocs for more information
struts.freemarker.wrapper.altMap=true
### configure the XSLTResult class to use stylesheet caching.
### Set to true for developers and false for production.
struts.xslt.nocache=false
### A list of configuration files automatically loaded by Struts
struts.configuration.files=struts-default.xml,struts-plugin.xml,struts.xml
### END SNIPPET: complete_file
(2)与spring2.0整合
在applicationContext.xml的名为dataSource的Bean前增加以下内容
<bean id="spring-object-factory" class="org.apache.struts2.spring.StrutsSpringObjectFactory" init-method="initObjectFactory" />
(3)写action文件
在com.action包中增加一个类,名为UserManage,使其继承BaseAction类。其代码如下:
package com.action;
import com.service.UserService;
import com.util.BaseAction;
public class UserManage extends BaseAction {
private UserService userService;
private String message;
private String username;
private String password;
private List userList;
public String checkUser() throws Exception{
// TODO Auto-generated method stub
if(username == null) username="";
if(password == null) password="";
if(userService.validate(username, password)){
setMessage("成功登录!");
return SUCCESS;
}
else{
setMessage("登录失败!");
return INPUT;
}
}
public String showAll() throws Exception{
setUserList(userService.showAllUsers());
return SUCCESS;
} 然后生成成员变量的get、set方法,如下图所示:
图5-24 生成get、set方法
在下面弹出来的对话框中选中所有的成员变量,点“OK”即可。
然后在applicationContext.xml中增加如下内容:
<bean id="UserManage" class="com.action.UserManage" scope="prototype" autowire="byName" />
在Webroot目录下增加next.jsp页面,作为正确登录后跳转的页面。
在src目录下增加struts.xml文件,代码如下:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="Login" class="UserManage" method="checkUser">
<result name="success" type="chain">ShowAllUser</result>
<result name="input">/index.jsp</result>
</action>
<action name="ShowAllUser" class="UserManage" method="showAll">
<result name="success">/next.jsp</result>
</action>
</package>
</struts>
修改index.jsp,在里面增加一个表单,具体代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W 3C //DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.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>
<h2 align="center">用户登录</h2>
<br>
<form name="loginForm" id="loginForm" action="Login.action" method="post">
<div align="center">
用户名<input type="text" name="username" /><br>
密码<input type="password" name="password" /><br>
<input type="submit" value="提交" /> <input type="reset" value="重置" /><br>
<p align="center"><font color="red"><s:property value="message" /></font></p>
<p> </p>
</div>
</form>
</body>
</html>
注:其中带有<s:>标签的就是Struts2.0标签,如果要引用该标签,必需在该页面头部加上:
<%@ taglib prefix="s" uri="/struts-tags" %>
Next.jsp内容如下:
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W 3C //DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'next.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>
<p>
欢迎,<s:property value="username" />
</p>
<div align="center">
<h3>用户信息列表</h3><br>
<table border="1">
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
</tr>
<s:iterator value="userList">
<tr>
<td><s:property value="id" /></td>
<td><s:property value="username" /></td>
<td><s:property value="password" /></td>
</tr>
</s:iterator>
</table>
</div>
</body>
</html>
注:此时完整的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="spring-object-factory" class="org.apache.struts2.spring.StrutsSpringObjectFactory" init-method="initObjectFactory" />
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>net.sourceforge.jtds.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:jtds:sqlserver://localhost:1433/test</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value>sa</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/hibernate/Users.hbm.xml</value></list>
</property>
</bean>
<!-- Transaction Manage Bean -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="baseProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
<!-- prop key="get*">PROPAGATION_REQUIRED,readOnly</prop-->
</props>
</property>
</bean>
<!-- Business Logic Bean -->
<bean id="userService" parent="baseProxy">
<property name="target"><ref local="userServiceImpl" /></property>
</bean>
<bean id="userServiceImpl" class="com.service.impl.UserServiceImpl" autowire="byName" />
<!-- Struts2 Action Bean -->
<bean id="UserManage" class="com.action.UserAction" scope="prototype" autowire="byName" >
</bean>
</beans>
发布、运行
使用users表中的用户信息登录,如果登录成功,跳转到next.jsp页面,并显示所有用户信息。