J2EE项目:整合SSH开发『新闻发布系统』
来源:互联网 发布:centos vsftpd 端口 编辑:程序博客网 时间:2024/06/06 00:02
一、架构
Struts+Spring+Hibernate
二、Hibernate持久层
1.编写PO类
====================================================================================
package org.prolove.model;
import java.io.Serializable;
/** *//**
* Base class for Model objects. Child objects should implement toString(),
* equals() and hashCode();
*
* <p>
* <a href="BaseObject.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:prolove@live.cn">PROLOVE</a>
*/
public abstract class BaseObject implements Serializable ...{
public abstract String toString();
public abstract boolean equals(Object o);
public abstract int hashCode();
}
====================================================================================
package org.prolove.model;
import java.util.Date;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
/** *//**
* @hibernate.class table="news"
* @struts.form include-all="false" extends="BaseForm"
*/
public class News extends BaseObject ...{
private Long id;// pk,required
private String title;// required
private String content;// required
private User poster;// fk,required
private Date postDate;// required
private Date lastModifyDate;// required
private Category category;// required
private Set newsReviews;
public News() ...{
}
/** *//**
* @return Returns the newsReview.
*/
public Set getNewsReviews() ...{
return newsReviews;
}
/** *//**
* @param newsReview
* The newsReview to set.
*/
public void setNewsReviews(Set newsReviews) ...{
this.newsReviews = newsReviews;
}
/** *//**
* @hibernate.many-to-one column="id" not-null="true"
*/
public Category getCategory() ...{
return category;
}
public void setCategory(Category category) ...{
this.category = category;
}
/** *//**
* @hibernate.property column="last_modify_date" not-null="true"
*/
public Date getLastModifyDate() ...{
return lastModifyDate;
}
public void setLastModifyDate(Date lastModifyDate) ...{
this.lastModifyDate = lastModifyDate;
}
/** *//**
* @hibernate.property column="post_date" not-null="true"
*/
public Date getPostDate() ...{
return postDate;
}
public void setPostDate(Date postDate) ...{
this.postDate = postDate;
}
/** *//**
* @hibernate.many-to-one column="username" not-null="true"
*/
public User getPoster() ...{
return poster;
}
public void setPoster(User poster) ...{
this.poster = poster;
}
/** *//**
* @hibernate.property column="content" length="3000" not-null="true"
*/
public String getContent() ...{
return content;
}
public void setContent(String content) ...{
this.content = content;
}
/** *//**
* @return Returns the id.
* @hibernate.id column="id" generator-class="increment"
* unsaved-value="null"
*/
public Long getId() ...{
return id;
}
public void setId(Long id) ...{
this.id = id;
}
/** *//**
* @hibernate.property column="title" length="50" not-null="true"
*/
public String getTitle() ...{
return title;
}
public void setTitle(String title) ...{
this.title = title;
}
/** *//**
* @see java.lang.Object#equals(Object)
*/
public boolean equals(Object object) ...{
if (!(object instanceof News)) ...{
return false;
}
News rhs = (News) object;
return this.poster.equals(rhs.getPoster())
&& this.postDate.equals(rhs.getPostDate());
/**//*
* return new EqualsBuilder().append(this.newsReviews, rhs.newsReviews)
* .append(this.title, rhs.title).append(this.category,
* rhs.category).append(this.content, rhs.content).append(
* this.postDate, rhs.postDate).append( this.lastModifyDate,
* rhs.lastModifyDate).append( this.id, rhs.id).append(this.poster,
* rhs.poster) .isEquals();
*/
}
/** *//**
* @see java.lang.Object#hashCode()
*/
public int hashCode() ...{
return this.poster.hashCode() + this.postDate.hashCode();
/**//*
* return new HashCodeBuilder(1595611275, -1477459617).append(
* this.newsReviews).append(this.title).append(this.category)
* .append(this.content).append(this.postDate).append(
* this.lastModifyDate).append(this.id)
* .append(this.poster).toHashCode();
*/
}
/** *//**
* @see java.lang.Object#toString()
*/
public String toString() ...{
return new ToStringBuilder(this).append("id", this.id).append("title",
this.title).append("postDate", this.postDate).append("content",
this.content).append("lastModifyDate", this.lastModifyDate)
.append("poster", this.poster)
.append("category", this.category).append("newsReviews",
this.newsReviews).toString();
}
}
2.编写PO的映射配置文件
====================================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.prolove.model.News" table="news">
<id name="id" column="id" unsaved-value="null">
<!-- The generator-class attribute of @hibernate.id is deprecated, use the @hibernate.generator tag instead -->
<generator class="increment">
</generator>
</id>
<many-to-one name="category" class="org.prolove.model.Category" column="category_id" not-null="true">
</many-to-one>
<property name="lastModifyDate" column="last_modify_date" not-null="true">
</property>
<property name="postDate" column="post_date" not-null="true">
</property>
<many-to-one name="poster" column="username" not-null="true">
</many-to-one>
<property name="content" column="content" length="3000" not-null="true">
</property>
<property name="title" column="title" length="50" not-null="true">
</property>
<!-- bi-directional one-to-many association to NewsReview -->
<set name="newsReviews" lazy="false" inverse="true" cascade="all-delete-orphan">
<meta attribute="field-description">
@hibernate.list lazy="true" inverse="false" cascade="none"
@hibernate.collection-key column="id"
@hibernate.collection-one-to-many class="org.prolove.model.NewsReview"
</meta>
<key>
<column name="news_id" />
</key>
<one-to-many class="org.prolove.model.NewsReview" />
</set>
</class>
</hibernate-mapping>
3.连接数据库
applicationContext-hibernate.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="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!-- property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/-->
<property name="url" value="jdbc:oracle:thin:@10.200.3.81:1521:oranet"/>
<property name="username" value="hm"/>
<property name="password" value="hm123"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="logAbandoned" value="true"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>org/prolove/model/User.hbm.xml</value>
<value>org/prolove/model/News.hbm.xml</value>
<value>org/prolove/model/NewsReview.hbm.xml</value>
<value>org/prolove/model/Category.hbm.xml</value>
</list>
</property>
<!-- The property below is commented out b/c it doesn't work when run via
Ant in Eclipse. It works fine for individual JUnit tests and in IDEA ??
<property name="mappingJarLocations">
<list><value>file:dist/appfuse-dao.jar</value></list>
</property>
-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>
<!-- Create/update the database tables automatically when the JVM starts up
<prop key="hibernate.hbm2ddl.auto">update</prop> -->
<!-- Turn batching off for better error messages under PostgreSQL
<prop key="hibernate.jdbc.batch_size">0</prop> -->
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Generic DAO - can be used when doing standard CRUD -->
<bean id="dao" class="org.prolove.dao.hibernate.BaseDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- UserDAO: Hibernate implementation -->
<bean id="userDAO" class="org.prolove.dao.hibernate.UserDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Add new DAOs here -->
<bean id="newsDAO" class="org.prolove.dao.hibernate.NewsDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="newsReviewDAO" class="org.prolove.dao.hibernate.NewsReviewDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="categoryDAO" class="org.prolove.dao.hibernate.CategoryDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- PersonDAO: Hibernate implementation -->
<bean id="personDAO" class="org.appfuse.dao.hibernate.PersonDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
=====================================================================
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- hibernate datasource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/newsboard"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="20"/>
<property name="maxIdle" value="10"/>
<property name="initialSize" value="1"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="logAbandoned" value="true"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>org/prolove/model/User.hbm.xml</value>
<value>org/prolove/model/News.hbm.xml</value>
<value>org/prolove/model/NewsReview.hbm.xml</value>
<value>org/prolove/model/Category.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- service manager Template-->
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- service manager-->
<bean id="facadeManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.prolove.service.impl.FacadeManagerImpl">
<property name="newsDAO" ref="newsDAO"/>
<property name="newsReviewDAO" ref="newsReviewDAO"/>
<property name="categoryDAO" ref="categoryDAO"/>
<property name="userDAO" ref="userDAO"/>
</bean>
</property>
</bean>
</beans>
三、DAO组件层
1.DAO组件的结构
为了让逻辑组件与具体的DAO组件分离,还必须有一个DAO工厂。
2.编写DAO接口
package org.prolove.dao;
import java.io.Serializable;
import java.util.List;
/** *//**
* Data Access Object (DAO) interface. This is an interface
* used to tag our DAO classes and to provide common methods to all DAOs.
*
* <p><a href="DAO.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public interface DAO ...{
/** *//**
* Generic method used to get all objects of a particular type. This
* is the same as lookup up all rows in a table.
* @param clazz the type of objects (a.k.a. while table) to get data from
* @return List of populated objects
*/
public List getObjects(Class clazz);
/** *//**
* Generic method to get an object based on class and identifier. An
* ObjectRetrievalFailureException Runtime Exception is thrown if
* nothing is found.
*
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
* @return a populated object
* @see org.springframework.orm.ObjectRetrievalFailureException
*/
public Object getObject(Class clazz, Serializable id);
/** *//**
* Generic method to save an object - handles both update and insert.
* @param o the object to save
*/
public void saveObject(Object o);
/** *//**
* Generic method to delete an object based on class and id
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
*/
public void removeObject(Class clazz, Serializable id);
}
=========================================================================
package org.prolove.dao;
import java.util.List;
import org.prolove.model.User;
/** *//**
* User Data Access Object (DAO) interface.
*
* <p>
* <a href="UserDAO.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public interface UserDAO extends DAO ...{
/** *//**
* Gets users information based on login name.
* @param username the current username
* @return user populated user object
*/
public User getUser(String username);
/** *//**
* Gets a list of users based on parameters passed in.
*
* @return List populated list of users
*/
public List getUsers(User user);
/** *//**
* Saves a user's information
* @param user the object to be saved
*/
public void saveUser(User user);
/** *//**
* Removes a user from the database by id
* @param username the user's username
*/
public void removeUser(String username);
}
……
3.编写DAO的具体实现
package org.prolove.dao.hibernate;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.prolove.dao.DAO;
/** *//**
* This class serves as the Base class for all other DAOs - namely to hold
* common methods that they might all use. Can be used for standard CRUD
* operations.</p>
*
* <p><a href="BaseDAOHibernate.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public class BaseDAOHibernate extends HibernateDaoSupport implements DAO ...{
protected final Log log = LogFactory.getLog(getClass());
/** *//**
* @see org.leecode.dao.DAO#saveObject(java.lang.Object)
*/
public void saveObject(Object o) ...{
getHibernateTemplate().saveOrUpdate(o);
}
/** *//**
* @see org.leecode.dao.DAO#getObject(java.lang.Class, java.io.Serializable)
*/
public Object getObject(Class clazz, Serializable id) ...{
Object o = getHibernateTemplate().get(clazz, id);
if (o == null) ...{
throw new ObjectRetrievalFailureException(clazz, id);
}
return o;
}
/** *//**
* @see org.leecode.dao.DAO#getObjects(java.lang.Class)
*/
public List getObjects(Class clazz) ...{
return getHibernateTemplate().loadAll(clazz);
}
/** *//**
* @see org.leecode.dao.DAO#removeObject(java.lang.Class, java.io.Serializable)
*/
public void removeObject(Class clazz, Serializable id) ...{
getHibernateTemplate().delete(getObject(clazz, id));
}
}
======================================================================================
package org.prolove.dao.hibernate;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.prolove.dao.NewsDAO;
import org.prolove.model.News;
public class NewsDAOHibernate extends BaseDAOHibernate implements NewsDAO ...{
public News getNews(Long id) ...{
News news = (News) getHibernateTemplate().get(News.class, id);
if (news == null) ...{
throw new ObjectRetrievalFailureException(News.class, id);
}
return news;
}
public void saveNews(News news) ...{
getHibernateTemplate().saveOrUpdate(news);
}
public void removeNews(Long id) ...{
// object must be loaded before it can be deleted
getHibernateTemplate().delete(getNews(id));
}
}
……
4.用Spring容器代替DAO工厂
见上文applicationContext-hibernate.xml
以及
daoContext.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- DAO模板,用于被其他的DAO组件继承 -->
<bean id="daoTemplate" abstract="true" lazy-init="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Generic DAO - can be used when doing standard CRUD -->
<bean id="dao" class="org.prolove.dao.hibernate.BaseDAOHibernate"
parent="daoTemplate"/>
<!-- UserDAO: Hibernate implementation -->
<bean id="userDAO" class="org.prolove.dao.hibernate.UserDAOHibernate"
parent="daoTemplate"/>
<!-- NewsDAO Hibernate implementation -->
<bean id="newsDAO" class="org.prolove.dao.hibernate.NewsDAOHibernate"
parent="daoTemplate"/>
<!-- NewsReviewDAO Hibernate implementation -->
<bean id="newsReviewDAO" class="org.prolove.dao.hibernate.NewsReviewDAOHibernate"
parent="daoTemplate"/>
<!-- CategoryDAO Hibernate implementation -->
<bean id="categoryDAO" class="org.prolove.dao.hibernate.CategoryDAOHibernate"
parent="daoTemplate"/>
</beans>
四、业务逻辑层
1.业务逻辑组件的结构
每个模块设计一个业务逻辑组件。
2.业务逻辑组件的接口
package org.prolove.service;
import java.util.List;
import org.prolove.dao.CategoryDAO;
import org.prolove.dao.NewsDAO;
import org.prolove.dao.NewsReviewDAO;
import org.prolove.dao.UserDAO;
import org.prolove.model.Category;
import org.prolove.model.News;
import org.prolove.model.NewsReview;
import org.prolove.model.User;
//该接口是对DAO的正面包装
public interface FacadeManager ...{
// category的业务方法
public void setCategoryDAO(CategoryDAO dao);
public Category getCategory(String id);
public void saveCategory(Category category);
public void removeCategory(String id);
public List getCategories();
// news的业务方法
public void setNewsDAO(NewsDAO dao);
public News getNews(String id);
public void saveNews(News news);
public void removeNews(String id);
// newsReview的业务方法
public void setNewsReviewDAO(NewsReviewDAO dao);
public NewsReview getNewsReview(String id);
public void saveNewsReview(NewsReview newsReview);
public void removeNewsReview(String id);
// user的业务方法
public void setUserDAO(UserDAO dao);
public User getUser(String username);
public List getUsers(User user);
public void saveUser(User user) throws Exception;
public void removeUser(String username);
public boolean validateUser(User user);
}
3.业务逻辑组件的实现类
package org.prolove.service;
import java.io.Serializable;
import java.util.List;
import org.prolove.dao.DAO;
public interface Manager ...{
/** *//**
* Expose the setDAO method for testing purposes
* @param dao
*/
public void setDAO(DAO dao);
/** *//**
* Generic method used to get a all objects of a particular type.
* @param clazz the type of objects
* @return List of populated objects
*/
public List getObjects(Class clazz);
/** *//**
* Generic method to get an object based on class and identifier.
*
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
* @return a populated object
* @see org.springframework.orm.ObjectRetrievalFailureException
*/
public Object getObject(Class clazz, Serializable id);
/** *//**
* Generic method to save an object.
* @param o the object to save
*/
public void saveObject(Object o);
/** *//**
* Generic method to delete an object based on class and id
* @param clazz model class to lookup
* @param id the identifier of the class
*/
public void removeObject(Class clazz, Serializable id);
}
package org.prolove.service.impl;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.prolove.dao.DAO;
import org.prolove.service.Manager;
/** *//**
* Base class for Business Services - use this class for utility methods and
* generic CRUD methods.
*
* <p><a href="BaseManager.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:prolove@live.cn">Matt Raible</a>
*/
public class BaseManager implements Manager ...{
protected DAO dao = null;
protected final Log log = LogFactory.getLog(getClass());
/** *//**
* @see org.leecode.service.Manager#setDAO(org.leecode.dao.DAO)
*/
public void setDAO(DAO dao) ...{
this.dao = dao;
}
/** *//**
* @see org.leecode.service.Manager#getObject(java.lang.Class, java.io.Serializable)
*/
public Object getObject(Class clazz, Serializable id) ...{
return dao.getObject(clazz, id);
}
/** *//**
* @see org.leecode.service.Manager#getObjects(java.lang.Class)
*/
public List getObjects(Class clazz) ...{
return dao.getObjects(clazz);
}
/** *//**
* @see org.leecode.service.Manager#removeObject(java.lang.Class, java.io.Serializable)
*/
public void removeObject(Class clazz, Serializable id) ...{
dao.removeObject(clazz, id);
}
/** *//**
* @see org.leecode.service.Manager#saveObject(java.lang.Object)
*/
public void saveObject(Object o) ...{
dao.saveObject(o);
}
}
package org.prolove.service.impl;
import java.util.List;
import org.springframework.dao.DataIntegrityViolationException;
import org.prolove.dao.CategoryDAO;
import org.prolove.dao.NewsDAO;
import org.prolove.dao.NewsReviewDAO;
import org.prolove.dao.UserDAO;
import org.prolove.model.Category;
import org.prolove.model.News;
import org.prolove.model.NewsReview;
import org.prolove.model.User;
import org.prolove.service.FacadeManager;
public class FacadeManagerImpl extends BaseManager implements
FacadeManager ...{
private CategoryDAO categoryDAO;
private NewsDAO newsDAO;
private NewsReviewDAO newsReviewDAO;
private UserDAO userDAO;
public void setCategoryDAO(CategoryDAO categoryDAO) ...{
this.categoryDAO = categoryDAO;
}
public Category getCategory(String id) ...{
return categoryDAO.getCategory(Long.valueOf(id));
}
public void saveCategory(Category category) ...{
categoryDAO.saveCategory(category);
}
public void removeCategory(String id) ...{
categoryDAO.removeCategory(Long.valueOf(id));
}
public List getCategories() ...{
return categoryDAO.getCategories();
}
public void setNewsDAO(NewsDAO newsDAO) ...{
this.newsDAO = newsDAO;
}
public News getNews(String id) ...{
return newsDAO.getNews(Long.valueOf(id));
}
public void saveNews(News news) ...{
newsDAO.saveNews(news);
}
public void removeNews(String id) ...{
newsDAO.removeNews(Long.valueOf(id));
}
public void setNewsReviewDAO(NewsReviewDAO newsReviewDAO) ...{
this.newsReviewDAO = newsReviewDAO;
}
public NewsReview getNewsReview(String id) ...{
return newsReviewDAO.getNewsReview(Long.valueOf(id));
}
public void saveNewsReview(NewsReview newsReview) ...{
newsReviewDAO.saveNewsReview(newsReview);
}
public void removeNewsReview(String id) ...{
newsReviewDAO.removeNewsReview(Long.valueOf(id));
}
public void setUserDAO(UserDAO userDAO) ...{
this.userDAO = userDAO;
}
public User getUser(String username) ...{
return userDAO.getUser(username);
}
public List getUsers(User user) ...{
return userDAO.getUsers(user);
}
public void saveUser(User user) throws Exception ...{
try ...{
userDAO.saveUser(user);
} catch (DataIntegrityViolationException e) ...{
throw new Exception("User '" + user.getUsername()
+ "' already exists!");
}
}
public void removeUser(String username) ...{
userDAO.removeUser(username);
}
public boolean validateUser(User aUser) ...{
User user = getUser(aUser.getUsername());
if (user != null && user.getPassword().equals(aUser.getPassword()))
return true;
else
return false;
}
}
4.业务逻辑组件的配置
在applicationContext.xml配置FacadeManager组件
五、Web层设计
1.Action的实现
package org.prolove.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.validator.DynaValidatorForm;
import org.prolove.action.base.BaseAction;
import org.prolove.webapp.util.AppConstants;
import org.prolove.model.*;
import java.util.*;
/** *//**
* @author PROLOVE prolve@live.cn
* @version 1.0
* <br>Copyright (C), 2006-2008, PROLOVE
* <br>This program is protected by copyright laws.
* <br>Program Name:
* <br>Date:
*/
public class AddReviewAction extends BaseAction
...{
//必须重写该核心方法,该方法actionForm将表单的请求参数封装成值对象
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception
...{
DynaValidatorForm addForm = (DynaValidatorForm)form;
String content = (String)addForm.get("content");
String newsId = (String)addForm.get("newsId");
try
...{
News news = mgr.getNews(newsId);
String username = (String)request.getSession(true).getAttribute(AppConstants.LOGIN_USER);
User poster = mgr.getUser(username);
NewsReview newsReview = new NewsReview();
newsReview.setNews(news);
newsReview.setPoster(poster);
newsReview.setContent(content);
newsReview.setPostDate(new Date());
newsReview.setLastModifyDate(new Date());
mgr.saveNewsReview(newsReview);
}
catch (Exception e)
...{
request.setAttribute("newsId" , newsId);
return mapping.findForward("failure");
}
request.setAttribute("newsId" , newsId);
return mapping.findForward("success");
}
}
package org.prolove.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.validator.DynaValidatorForm;
import org.prolove.action.base.BaseAction;
import org.prolove.model.News;
import java.util.Set;
/** *//**
* @author PROLOVE prolve@live.cn
* @version 1.0
* <br>Copyright (C), 2006-2008, PROLOVE
* <br>This program is protected by copyright laws.
* <br>Program Name:
* <br>Date:
*/
public class LoadReviewsByNews extends BaseAction
...{
//必须重写该核心方法,该方法actionForm将表单的请求参数封装成值对象
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception
...{
String newsId = null;
if(request.getAttribute("newsId") == null)
...{
newsId = request.getParameter("newsId");
}
else
...{
newsId = (String)request.getAttribute("newsId");
}
News news = mgr.getNews(newsId);
request.setAttribute("news" , news);
request.setAttribute("reviews",news.getNewsReviews());
return mapping.findForward("success");
}
}
……
2.Spring管理容器Action
采用DelegatingRequestProcessor的整合策略。
struts-config.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<!-- 配置登陆所使用的Form-->
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="user" type="java.lang.String" />
<form-property name="pass" type="java.lang.String" />
</form-bean>
<!-- 添加新闻所用的Form-->
<form-bean name="addNewsForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="title" type="java.lang.String" />
<form-property name="content" type="java.lang.String" />
<form-property name="categoryId" type="java.lang.String" />
</form-bean>
<!-- 添加新闻评论所用的Form-->
<form-bean name="addNewsReviewForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="content" type="java.lang.String" />
<form-property name="newsId" type="java.lang.String" />
</form-bean>
</form-beans>
<global-forwards>
</global-forwards>
<!-- ========================================= Action Mapping Definitions -->
<action-mappings>
<!-- 处理登陆 -->
<action path="/processLogin"
name="loginForm"
scope="request"
validate="true"
input="input">
<forward name="input" path="/index.jsp" />
<forward name="success" path="/listCate.do" />
</action>
<!-- 登出系统 -->
<action path="/logout" scope="request">
<forward name="success" path="/index.jsp"/>
</action>
<!-- 进入主页面 -->
<action path="/listCate" scope="request">
<forward name="success" path="/main.jsp"/>
</action>
<!-- 根据种类加载所有新闻 -->
<action path="/loadNewsByCategory" scope="request">
<forward name="failure" path="/listCate.do"/>
<forward name="success" path="/category_view.jsp"/>
</action>
<!-- 添加新闻 -->
<action path="/addNews"
name="addNewsForm"
scope="request"
validate="true"
input="input">
<forward name="failure" path="/loadNewsByCategory.do"/>
<forward name="success" path="/loadNewsByCategory.do"/>
</action>
<!-- 根据新闻id加载所有评论 -->
<action path="/loadNewsReviewByNews" scope="request">
<forward name="success" path="/news_view.jsp"/>
</action>
<!-- 添加新闻评论 -->
<action path="/addNewsReview"
name="addNewsReviewForm"
scope="request"
validate="true"
input="input">
<forward name="failure" path="/loadNewsReviewByNews.do"/>
<forward name="success" path="/loadNewsReviewByNews.do"/>
</action>
</action-mappings>
<controller inputForward="true" processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<message-resources parameter="resource"/>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
<set-property property="stopOnFirstError" value="true"/>
</plug-in>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/daoContext.xml,
/WEB-INF/applicationContext.xml,
/WEB-INF/action-Servlet.xml"/>
</plug-in>
</struts-config>
action-Servlet.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="actionTemplate" abstract="true" singleton="false">
<property name="mgr" ref="facadeManager"/>
</bean>
<!-- 处理登陆-->
<bean name="/processLogin" class="org.prolove.action.LoginAction" parent="actionTemplate"/>
<!-- 登出系统-->
<bean name="/logout" class="org.prolove.action.Logout"/>
<!-- 列出所有的新闻分类-->
<bean name="/listCate" class="org.prolove.action.ListCate" parent="actionTemplate"/>
<!-- 根据种类列出所有新闻-->
<bean name="/loadNewsByCategory" class="org.prolove.action.LoadNewsByCategory" parent="actionTemplate"/>
<!-- 添加新闻-->
<bean name="/addNews" class="org.prolove.action.AddNewsAction" parent="actionTemplate"/>
<!-- 根据新闻查看所有的评论-->
<bean name="/loadNewsReviewByNews" class="org.prolove.action.LoadReviewsByNews" parent="actionTemplate"/>
<!-- 添加新闻评论-->
<bean name="/addNewsReview" class="org.prolove.action.AddReviewAction" parent="actionTemplate"/>
</beans>
3.数据校验的选择
validation.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
<formset>
<form name="loginForm">
<field property="user" depends="required,minlength">
<arg key="loginForm.user" position="0"/>
<arg name="minlength" key="${var:minlength}" resource="false" position="1"/>
<var>
<var-name>minlength</var-name>
<var-value>4</var-value>
</var>
</field>
<field property="pass" depends="required,minlength">
<arg key="loginForm.pass" position="0"/>
<arg name="minlength" key="${var:minlength}" resource="false" position="1"/>
<var>
<var-name>minlength</var-name>
<var-value>4</var-value>
</var>
</field>
</form>
<form name="addNewsForm">
<field property="title" depends="required">
<arg key="addNewsForm.title" position="0"/>
</field>
<field property="content" depends="required">
<arg key="addNewsForm.content" position="0"/>
</field>
<field property="categoryId" depends="required,integer">
<arg key="addNewsForm.categoryId" position="0"/>
</field>
</form>
<form name="addNewsReviewForm">
<field property="content" depends="required">
<arg key="addNewsReviewForm.content" position="0"/>
</field>
<field property="newsId" depends="required,integer">
<arg key="addNewsReviewForm.categoryId" position="0"/>
</field>
</form>
</formset>
</form-validation>
4.访问权限的控制
package org.prolove.webapp.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.prolove.webapp.util.AppConstants;
/** *//**
* 设置字符集、过滤未登录的非法请求
*/
public class UserLoginFilter implements Filter ...{
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = false;
protected String forwardPath = null;
public void destroy() ...{
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException ...{
// 设置编码方式,web.xml里面有filter参数的初始化设置
if (ignore || (request.getCharacterEncoding() == null)) ...{
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String requesturi = httpServletRequest.getRequestURI();
// 通过检查session中的变量,过虑请求
HttpSession session = httpServletRequest.getSession();
Object currentUser = session.getAttribute(AppConstants.LOGIN_USER);
// 当前会话用户为空而且不是请求登录,退出登录,欢迎页面和根目录则退回到应用的根目录
if (currentUser == null
&& !requesturi.endsWith("/processLogin.do")
&& !requesturi.endsWith("/logout.do")
&& !requesturi.endsWith("/index.jsp")
&& !requesturi.endsWith(httpServletRequest.getContextPath()
+ "/")) ...{
httpServletResponse.sendRedirect(httpServletRequest
.getContextPath()
+ "/");
return;
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException ...{
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
this.forwardPath = filterConfig.getInitParameter("forwardpath");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) ...{
return (this.encoding);
}
}
5.解决中文编码问题
代码同上,另
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
version="2.4">
<filter>
<filter-name>Login Filter</filter-name>
<filter-class>
org.prolove.webapp.filter.UserLoginFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>forwardpath</param-name>
<param-value>index.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Login Filter</filter-name>
<url-pattern>/**//*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<jsp-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
6.JSP页面输出
-->main.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>版面分类</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(loadNewsForm.categoryId.checked)
{
loadNewsForm.submit();
return true;
}
for (var i = 0 ; i < loadNewsForm.categoryId.length ; i++)
{
if( loadNewsForm.categoryId[i].checked )
{
loadNewsForm.submit();
return true;
}
}
alert('请选择要查看的版面!');
return false;
}
function logout(){
logoutForm.submit();
}
</script>
<body>
<table width="500" align="center" cellpadding="1" bgcolor="#99CCCC">
<form name="loadNewsForm" action="loadNewsByCategory.do" method="POST">
<tr>
<td width="40%" colspan="2" align="center">
<p>欢迎,<bean:write name="login_user"/></p>
</td>
</tr>
<tr>
<td width="10%" align="center">
请选择
</td>
<td width="30%" align="center">
版面名
</td>
</tr>
<logic:iterate id="item" name="categories" indexId="index" scope="request">
<tr>
<td width="10%" align="center">
<input type="radio" name="categoryId" value='<bean:write name="item" property="id"/>'>
</td>
<td width="30%" align="center">
<bean:write name="item" property="name"/>
</td>
</tr>
</logic:iterate>
<tr>
<td colspan="2" align="center">
<input type="button" value="查看" onClick="verifyValue();">
<input type="button" value="登出" onClick="logout();">
</td>
</tr>
</form>
<form name="logoutForm" action="logout.do" method="post"">
</form>
</table>
</body>
</html>
-->index.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>登陆系统</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<body>
<logic:messagesPresent>
<div class="title">
<bean:message key="errors.header"/>
<ul>
<html:messages id="error">
<li><bean:write name="error"/></li>
</html:messages>
</ul>
</div>
</logic:messagesPresent>
<logic:present name="errMsg">
<div class="title">
<li><bean:write name="errMsg" scope="request"/>
</div>
</logic:present>
<logic:present name="logout">
<div class="title">
<li><bean:write name="logout" scope="request"/>
</div>
</logic:present>
<table width="400" align="center" bgcolor="#99CCCC">
<html:form action="/processLogin">
<tr>
<td>
请输入用户名:
</td>
<td>
<html:text property="user" size="20"/>
</td>
</tr>
<tr>
<td>
请输入密码:
</td>
<td>
<input type="password" name="pass" size="20">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="确定"> <input type="reset" value="重置">
</td>
</tr>
</html:form>
</table>
</body>
</html>
-->category_view.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>分类新闻</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(loadNewsForm.newsId.checked)
{
loadNewsForm.submit();
return true;
}
for (var i = 0 ; i < loadNewsForm.newsId.length ; i++)
{
if( loadNewsForm.newsId[i].checked )
{
loadNewsForm.submit();
return true;
}
}
alert('请选择要查看的新闻!');
return false;
}
function goMain(){
mainForm.submit();
}
</script>
<body>
<table width="600" align="center" cellpadding="1" bgcolor="#99CCCC">
<form name="loadNewsForm" action="loadNewsReviewByNews.do" method="POST">
<tr>
<td width="60%" colspan="6" align="center">
<p>新闻列表</p> </td>
</tr>
<tr>
<td width="10%" align="center">
请选择 </td>
<td width="10%" align="center">
主题 </td>
<td width="10%" align="center">
发布人 </td>
<td width="10%" align="center">
发布时间 </td>
<td width="10%" align="center">
最后评论时间 </td>
</tr>
<logic:iterate id="item" name="news" indexId="index" scope="request">
<tr>
<td width="10%" align="center">
<input type="radio" name="newsId" value='<bean:write name="item" property="id"/>'>
</td>
<td width="10%" align="center">
<bean:write name="item" property="title"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="content"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="postDate"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="lastModifyDate"/>
</td>
</tr>
</logic:iterate>
<tr>
<td height="52" colspan="6" align="center">
<input type="button" value="查看" onClick="verifyValue();"> <input type="reset" value="重置"> </td>
</tr>
<tr>
<td height="25" colspan="6" align="center"> </td>
</tr>
<tr>
<td height="25" colspan="6" align="center">发表新的新闻</td>
</tr>
</form>
<html:form action="/addNews">
<tr>
<td colspan="6" align="center">
主题: </td>
</tr>
<tr>
<td colspan="6" align="center">
<html:text property="title" size="80"/>
<input type="hidden" name="categoryId" value='<bean:write name="categoryId"/>'>
</td>
</tr>
<tr>
<td colspan="6" align="center">
内容: </td>
</tr>
<tr>
<td colspan="6" align="center">
<html:textarea property="content" cols="80" rows="20"></html:textarea> </td>
</tr>
<tr>
<td colspan="6" align="center">
<input type="submit" value="提交">
<input type="reset" value="重置">
<input type="button" value="返回" onClick="history.go(-1);">
<input type="reset" value="主页" onClick="goMain();"> </td>
</tr>
</html:form>
<form name="mainForm" action="listCate.do" method="post"">
</form>
</table>
</body>
</html>
-->news_view.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>新闻详细内容</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(addNewsReviewForm.content.value == ""){
alert('请输入评论内容!');
addNewsReviewForm.content.focus();
return false;
}
addNewsReviewForm.submit();
}
function goMain(){
mainForm.submit();
}
</script>
<body>
<table width="600" align="center" cellpadding="1" bgcolor="#99CCCC">
<tr>
<td colspan="2" align="center" bgcolor="#999999"><p>新闻标题:<bean:write name="news" property="title"/></p></td>
</tr>
<tr>
<td width="20%" align="center">新闻内容:</td>
<td width="80%" align="center" bgcolor="#eeeeee"><bean:write name="news" property="content"/></td>
</tr>
<tr>
<td colspan="2" align="center" bgcolor="#999999">所有评论如下:</td>
</tr>
<logic:iterate id="item" name="reviews" indexId="index" scope="request">
<tr>
<td colspan="2" bgcolor="#96dede">由网友${item.poster.username}于<bean:write name="item" property="postDate"/>发表的评论如下:</td>
</tr>
<tr>
<td colspan="2" align="center" bgcolor="#ffffff"><bean:write name="item" property="content"/> </td>
</tr>
</logic:iterate>
<html:form action="/addNewsReview">
<input type="hidden" name="newsId" value='<bean:write name="news" property="id"/>'>
<tr>
<td colspan="2" align="center"> 我要评论: </tr>
<tr>
<td colspan="2" align="center"><textarea name="content" cols="80" rows="6"></textarea> </td>
</tr>
<tr>
<td colspan="2" align="center"><input name="button" type="submit" value="提交">
<input name="reset" type="reset" value="重置">
<input name="button" type="button" onClick="history.go(-1);" value="返回">
<input name="reset" type="reset" onClick="goMain();" value="主页"> </td>
</tr>
</html:form>
<form name="mainForm" action="listCate.do" method="post"">
</form>
</table>
</body>
</html>
Struts+Spring+Hibernate
二、Hibernate持久层
1.编写PO类
====================================================================================
package org.prolove.model;
import java.io.Serializable;
/** *//**
* Base class for Model objects. Child objects should implement toString(),
* equals() and hashCode();
*
* <p>
* <a href="BaseObject.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:prolove@live.cn">PROLOVE</a>
*/
public abstract class BaseObject implements Serializable ...{
public abstract String toString();
public abstract boolean equals(Object o);
public abstract int hashCode();
}
====================================================================================
package org.prolove.model;
import java.util.Date;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
/** *//**
* @hibernate.class table="news"
* @struts.form include-all="false" extends="BaseForm"
*/
public class News extends BaseObject ...{
private Long id;// pk,required
private String title;// required
private String content;// required
private User poster;// fk,required
private Date postDate;// required
private Date lastModifyDate;// required
private Category category;// required
private Set newsReviews;
public News() ...{
}
/** *//**
* @return Returns the newsReview.
*/
public Set getNewsReviews() ...{
return newsReviews;
}
/** *//**
* @param newsReview
* The newsReview to set.
*/
public void setNewsReviews(Set newsReviews) ...{
this.newsReviews = newsReviews;
}
/** *//**
* @hibernate.many-to-one column="id" not-null="true"
*/
public Category getCategory() ...{
return category;
}
public void setCategory(Category category) ...{
this.category = category;
}
/** *//**
* @hibernate.property column="last_modify_date" not-null="true"
*/
public Date getLastModifyDate() ...{
return lastModifyDate;
}
public void setLastModifyDate(Date lastModifyDate) ...{
this.lastModifyDate = lastModifyDate;
}
/** *//**
* @hibernate.property column="post_date" not-null="true"
*/
public Date getPostDate() ...{
return postDate;
}
public void setPostDate(Date postDate) ...{
this.postDate = postDate;
}
/** *//**
* @hibernate.many-to-one column="username" not-null="true"
*/
public User getPoster() ...{
return poster;
}
public void setPoster(User poster) ...{
this.poster = poster;
}
/** *//**
* @hibernate.property column="content" length="3000" not-null="true"
*/
public String getContent() ...{
return content;
}
public void setContent(String content) ...{
this.content = content;
}
/** *//**
* @return Returns the id.
* @hibernate.id column="id" generator-class="increment"
* unsaved-value="null"
*/
public Long getId() ...{
return id;
}
public void setId(Long id) ...{
this.id = id;
}
/** *//**
* @hibernate.property column="title" length="50" not-null="true"
*/
public String getTitle() ...{
return title;
}
public void setTitle(String title) ...{
this.title = title;
}
/** *//**
* @see java.lang.Object#equals(Object)
*/
public boolean equals(Object object) ...{
if (!(object instanceof News)) ...{
return false;
}
News rhs = (News) object;
return this.poster.equals(rhs.getPoster())
&& this.postDate.equals(rhs.getPostDate());
/**//*
* return new EqualsBuilder().append(this.newsReviews, rhs.newsReviews)
* .append(this.title, rhs.title).append(this.category,
* rhs.category).append(this.content, rhs.content).append(
* this.postDate, rhs.postDate).append( this.lastModifyDate,
* rhs.lastModifyDate).append( this.id, rhs.id).append(this.poster,
* rhs.poster) .isEquals();
*/
}
/** *//**
* @see java.lang.Object#hashCode()
*/
public int hashCode() ...{
return this.poster.hashCode() + this.postDate.hashCode();
/**//*
* return new HashCodeBuilder(1595611275, -1477459617).append(
* this.newsReviews).append(this.title).append(this.category)
* .append(this.content).append(this.postDate).append(
* this.lastModifyDate).append(this.id)
* .append(this.poster).toHashCode();
*/
}
/** *//**
* @see java.lang.Object#toString()
*/
public String toString() ...{
return new ToStringBuilder(this).append("id", this.id).append("title",
this.title).append("postDate", this.postDate).append("content",
this.content).append("lastModifyDate", this.lastModifyDate)
.append("poster", this.poster)
.append("category", this.category).append("newsReviews",
this.newsReviews).toString();
}
}
2.编写PO的映射配置文件
====================================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.prolove.model.News" table="news">
<id name="id" column="id" unsaved-value="null">
<!-- The generator-class attribute of @hibernate.id is deprecated, use the @hibernate.generator tag instead -->
<generator class="increment">
</generator>
</id>
<many-to-one name="category" class="org.prolove.model.Category" column="category_id" not-null="true">
</many-to-one>
<property name="lastModifyDate" column="last_modify_date" not-null="true">
</property>
<property name="postDate" column="post_date" not-null="true">
</property>
<many-to-one name="poster" column="username" not-null="true">
</many-to-one>
<property name="content" column="content" length="3000" not-null="true">
</property>
<property name="title" column="title" length="50" not-null="true">
</property>
<!-- bi-directional one-to-many association to NewsReview -->
<set name="newsReviews" lazy="false" inverse="true" cascade="all-delete-orphan">
<meta attribute="field-description">
@hibernate.list lazy="true" inverse="false" cascade="none"
@hibernate.collection-key column="id"
@hibernate.collection-one-to-many class="org.prolove.model.NewsReview"
</meta>
<key>
<column name="news_id" />
</key>
<one-to-many class="org.prolove.model.NewsReview" />
</set>
</class>
</hibernate-mapping>
3.连接数据库
applicationContext-hibernate.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="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!-- property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/-->
<property name="url" value="jdbc:oracle:thin:@10.200.3.81:1521:oranet"/>
<property name="username" value="hm"/>
<property name="password" value="hm123"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="logAbandoned" value="true"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>org/prolove/model/User.hbm.xml</value>
<value>org/prolove/model/News.hbm.xml</value>
<value>org/prolove/model/NewsReview.hbm.xml</value>
<value>org/prolove/model/Category.hbm.xml</value>
</list>
</property>
<!-- The property below is commented out b/c it doesn't work when run via
Ant in Eclipse. It works fine for individual JUnit tests and in IDEA ??
<property name="mappingJarLocations">
<list><value>file:dist/appfuse-dao.jar</value></list>
</property>
-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>
<!-- Create/update the database tables automatically when the JVM starts up
<prop key="hibernate.hbm2ddl.auto">update</prop> -->
<!-- Turn batching off for better error messages under PostgreSQL
<prop key="hibernate.jdbc.batch_size">0</prop> -->
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Generic DAO - can be used when doing standard CRUD -->
<bean id="dao" class="org.prolove.dao.hibernate.BaseDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- UserDAO: Hibernate implementation -->
<bean id="userDAO" class="org.prolove.dao.hibernate.UserDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Add new DAOs here -->
<bean id="newsDAO" class="org.prolove.dao.hibernate.NewsDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="newsReviewDAO" class="org.prolove.dao.hibernate.NewsReviewDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="categoryDAO" class="org.prolove.dao.hibernate.CategoryDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- PersonDAO: Hibernate implementation -->
<bean id="personDAO" class="org.appfuse.dao.hibernate.PersonDAOHibernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
=====================================================================
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- hibernate datasource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/newsboard"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="20"/>
<property name="maxIdle" value="10"/>
<property name="initialSize" value="1"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="logAbandoned" value="true"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>org/prolove/model/User.hbm.xml</value>
<value>org/prolove/model/News.hbm.xml</value>
<value>org/prolove/model/NewsReview.hbm.xml</value>
<value>org/prolove/model/Category.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- service manager Template-->
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- service manager-->
<bean id="facadeManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.prolove.service.impl.FacadeManagerImpl">
<property name="newsDAO" ref="newsDAO"/>
<property name="newsReviewDAO" ref="newsReviewDAO"/>
<property name="categoryDAO" ref="categoryDAO"/>
<property name="userDAO" ref="userDAO"/>
</bean>
</property>
</bean>
</beans>
三、DAO组件层
1.DAO组件的结构
为了让逻辑组件与具体的DAO组件分离,还必须有一个DAO工厂。
2.编写DAO接口
package org.prolove.dao;
import java.io.Serializable;
import java.util.List;
/** *//**
* Data Access Object (DAO) interface. This is an interface
* used to tag our DAO classes and to provide common methods to all DAOs.
*
* <p><a href="DAO.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public interface DAO ...{
/** *//**
* Generic method used to get all objects of a particular type. This
* is the same as lookup up all rows in a table.
* @param clazz the type of objects (a.k.a. while table) to get data from
* @return List of populated objects
*/
public List getObjects(Class clazz);
/** *//**
* Generic method to get an object based on class and identifier. An
* ObjectRetrievalFailureException Runtime Exception is thrown if
* nothing is found.
*
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
* @return a populated object
* @see org.springframework.orm.ObjectRetrievalFailureException
*/
public Object getObject(Class clazz, Serializable id);
/** *//**
* Generic method to save an object - handles both update and insert.
* @param o the object to save
*/
public void saveObject(Object o);
/** *//**
* Generic method to delete an object based on class and id
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
*/
public void removeObject(Class clazz, Serializable id);
}
=========================================================================
package org.prolove.dao;
import java.util.List;
import org.prolove.model.User;
/** *//**
* User Data Access Object (DAO) interface.
*
* <p>
* <a href="UserDAO.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public interface UserDAO extends DAO ...{
/** *//**
* Gets users information based on login name.
* @param username the current username
* @return user populated user object
*/
public User getUser(String username);
/** *//**
* Gets a list of users based on parameters passed in.
*
* @return List populated list of users
*/
public List getUsers(User user);
/** *//**
* Saves a user's information
* @param user the object to be saved
*/
public void saveUser(User user);
/** *//**
* Removes a user from the database by id
* @param username the user's username
*/
public void removeUser(String username);
}
……
3.编写DAO的具体实现
package org.prolove.dao.hibernate;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.prolove.dao.DAO;
/** *//**
* This class serves as the Base class for all other DAOs - namely to hold
* common methods that they might all use. Can be used for standard CRUD
* operations.</p>
*
* <p><a href="BaseDAOHibernate.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public class BaseDAOHibernate extends HibernateDaoSupport implements DAO ...{
protected final Log log = LogFactory.getLog(getClass());
/** *//**
* @see org.leecode.dao.DAO#saveObject(java.lang.Object)
*/
public void saveObject(Object o) ...{
getHibernateTemplate().saveOrUpdate(o);
}
/** *//**
* @see org.leecode.dao.DAO#getObject(java.lang.Class, java.io.Serializable)
*/
public Object getObject(Class clazz, Serializable id) ...{
Object o = getHibernateTemplate().get(clazz, id);
if (o == null) ...{
throw new ObjectRetrievalFailureException(clazz, id);
}
return o;
}
/** *//**
* @see org.leecode.dao.DAO#getObjects(java.lang.Class)
*/
public List getObjects(Class clazz) ...{
return getHibernateTemplate().loadAll(clazz);
}
/** *//**
* @see org.leecode.dao.DAO#removeObject(java.lang.Class, java.io.Serializable)
*/
public void removeObject(Class clazz, Serializable id) ...{
getHibernateTemplate().delete(getObject(clazz, id));
}
}
======================================================================================
package org.prolove.dao.hibernate;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.prolove.dao.NewsDAO;
import org.prolove.model.News;
public class NewsDAOHibernate extends BaseDAOHibernate implements NewsDAO ...{
public News getNews(Long id) ...{
News news = (News) getHibernateTemplate().get(News.class, id);
if (news == null) ...{
throw new ObjectRetrievalFailureException(News.class, id);
}
return news;
}
public void saveNews(News news) ...{
getHibernateTemplate().saveOrUpdate(news);
}
public void removeNews(Long id) ...{
// object must be loaded before it can be deleted
getHibernateTemplate().delete(getNews(id));
}
}
……
4.用Spring容器代替DAO工厂
见上文applicationContext-hibernate.xml
以及
daoContext.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- DAO模板,用于被其他的DAO组件继承 -->
<bean id="daoTemplate" abstract="true" lazy-init="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Generic DAO - can be used when doing standard CRUD -->
<bean id="dao" class="org.prolove.dao.hibernate.BaseDAOHibernate"
parent="daoTemplate"/>
<!-- UserDAO: Hibernate implementation -->
<bean id="userDAO" class="org.prolove.dao.hibernate.UserDAOHibernate"
parent="daoTemplate"/>
<!-- NewsDAO Hibernate implementation -->
<bean id="newsDAO" class="org.prolove.dao.hibernate.NewsDAOHibernate"
parent="daoTemplate"/>
<!-- NewsReviewDAO Hibernate implementation -->
<bean id="newsReviewDAO" class="org.prolove.dao.hibernate.NewsReviewDAOHibernate"
parent="daoTemplate"/>
<!-- CategoryDAO Hibernate implementation -->
<bean id="categoryDAO" class="org.prolove.dao.hibernate.CategoryDAOHibernate"
parent="daoTemplate"/>
</beans>
四、业务逻辑层
1.业务逻辑组件的结构
每个模块设计一个业务逻辑组件。
2.业务逻辑组件的接口
package org.prolove.service;
import java.util.List;
import org.prolove.dao.CategoryDAO;
import org.prolove.dao.NewsDAO;
import org.prolove.dao.NewsReviewDAO;
import org.prolove.dao.UserDAO;
import org.prolove.model.Category;
import org.prolove.model.News;
import org.prolove.model.NewsReview;
import org.prolove.model.User;
//该接口是对DAO的正面包装
public interface FacadeManager ...{
// category的业务方法
public void setCategoryDAO(CategoryDAO dao);
public Category getCategory(String id);
public void saveCategory(Category category);
public void removeCategory(String id);
public List getCategories();
// news的业务方法
public void setNewsDAO(NewsDAO dao);
public News getNews(String id);
public void saveNews(News news);
public void removeNews(String id);
// newsReview的业务方法
public void setNewsReviewDAO(NewsReviewDAO dao);
public NewsReview getNewsReview(String id);
public void saveNewsReview(NewsReview newsReview);
public void removeNewsReview(String id);
// user的业务方法
public void setUserDAO(UserDAO dao);
public User getUser(String username);
public List getUsers(User user);
public void saveUser(User user) throws Exception;
public void removeUser(String username);
public boolean validateUser(User user);
}
3.业务逻辑组件的实现类
package org.prolove.service;
import java.io.Serializable;
import java.util.List;
import org.prolove.dao.DAO;
public interface Manager ...{
/** *//**
* Expose the setDAO method for testing purposes
* @param dao
*/
public void setDAO(DAO dao);
/** *//**
* Generic method used to get a all objects of a particular type.
* @param clazz the type of objects
* @return List of populated objects
*/
public List getObjects(Class clazz);
/** *//**
* Generic method to get an object based on class and identifier.
*
* @param clazz model class to lookup
* @param id the identifier (primary key) of the class
* @return a populated object
* @see org.springframework.orm.ObjectRetrievalFailureException
*/
public Object getObject(Class clazz, Serializable id);
/** *//**
* Generic method to save an object.
* @param o the object to save
*/
public void saveObject(Object o);
/** *//**
* Generic method to delete an object based on class and id
* @param clazz model class to lookup
* @param id the identifier of the class
*/
public void removeObject(Class clazz, Serializable id);
}
package org.prolove.service.impl;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.prolove.dao.DAO;
import org.prolove.service.Manager;
/** *//**
* Base class for Business Services - use this class for utility methods and
* generic CRUD methods.
*
* <p><a href="BaseManager.java.html"><i>View Source</i></a></p>
*
* @author <a href="mailto:prolove@live.cn">Matt Raible</a>
*/
public class BaseManager implements Manager ...{
protected DAO dao = null;
protected final Log log = LogFactory.getLog(getClass());
/** *//**
* @see org.leecode.service.Manager#setDAO(org.leecode.dao.DAO)
*/
public void setDAO(DAO dao) ...{
this.dao = dao;
}
/** *//**
* @see org.leecode.service.Manager#getObject(java.lang.Class, java.io.Serializable)
*/
public Object getObject(Class clazz, Serializable id) ...{
return dao.getObject(clazz, id);
}
/** *//**
* @see org.leecode.service.Manager#getObjects(java.lang.Class)
*/
public List getObjects(Class clazz) ...{
return dao.getObjects(clazz);
}
/** *//**
* @see org.leecode.service.Manager#removeObject(java.lang.Class, java.io.Serializable)
*/
public void removeObject(Class clazz, Serializable id) ...{
dao.removeObject(clazz, id);
}
/** *//**
* @see org.leecode.service.Manager#saveObject(java.lang.Object)
*/
public void saveObject(Object o) ...{
dao.saveObject(o);
}
}
package org.prolove.service.impl;
import java.util.List;
import org.springframework.dao.DataIntegrityViolationException;
import org.prolove.dao.CategoryDAO;
import org.prolove.dao.NewsDAO;
import org.prolove.dao.NewsReviewDAO;
import org.prolove.dao.UserDAO;
import org.prolove.model.Category;
import org.prolove.model.News;
import org.prolove.model.NewsReview;
import org.prolove.model.User;
import org.prolove.service.FacadeManager;
public class FacadeManagerImpl extends BaseManager implements
FacadeManager ...{
private CategoryDAO categoryDAO;
private NewsDAO newsDAO;
private NewsReviewDAO newsReviewDAO;
private UserDAO userDAO;
public void setCategoryDAO(CategoryDAO categoryDAO) ...{
this.categoryDAO = categoryDAO;
}
public Category getCategory(String id) ...{
return categoryDAO.getCategory(Long.valueOf(id));
}
public void saveCategory(Category category) ...{
categoryDAO.saveCategory(category);
}
public void removeCategory(String id) ...{
categoryDAO.removeCategory(Long.valueOf(id));
}
public List getCategories() ...{
return categoryDAO.getCategories();
}
public void setNewsDAO(NewsDAO newsDAO) ...{
this.newsDAO = newsDAO;
}
public News getNews(String id) ...{
return newsDAO.getNews(Long.valueOf(id));
}
public void saveNews(News news) ...{
newsDAO.saveNews(news);
}
public void removeNews(String id) ...{
newsDAO.removeNews(Long.valueOf(id));
}
public void setNewsReviewDAO(NewsReviewDAO newsReviewDAO) ...{
this.newsReviewDAO = newsReviewDAO;
}
public NewsReview getNewsReview(String id) ...{
return newsReviewDAO.getNewsReview(Long.valueOf(id));
}
public void saveNewsReview(NewsReview newsReview) ...{
newsReviewDAO.saveNewsReview(newsReview);
}
public void removeNewsReview(String id) ...{
newsReviewDAO.removeNewsReview(Long.valueOf(id));
}
public void setUserDAO(UserDAO userDAO) ...{
this.userDAO = userDAO;
}
public User getUser(String username) ...{
return userDAO.getUser(username);
}
public List getUsers(User user) ...{
return userDAO.getUsers(user);
}
public void saveUser(User user) throws Exception ...{
try ...{
userDAO.saveUser(user);
} catch (DataIntegrityViolationException e) ...{
throw new Exception("User '" + user.getUsername()
+ "' already exists!");
}
}
public void removeUser(String username) ...{
userDAO.removeUser(username);
}
public boolean validateUser(User aUser) ...{
User user = getUser(aUser.getUsername());
if (user != null && user.getPassword().equals(aUser.getPassword()))
return true;
else
return false;
}
}
4.业务逻辑组件的配置
在applicationContext.xml配置FacadeManager组件
五、Web层设计
1.Action的实现
package org.prolove.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.validator.DynaValidatorForm;
import org.prolove.action.base.BaseAction;
import org.prolove.webapp.util.AppConstants;
import org.prolove.model.*;
import java.util.*;
/** *//**
* @author PROLOVE prolve@live.cn
* @version 1.0
* <br>Copyright (C), 2006-2008, PROLOVE
* <br>This program is protected by copyright laws.
* <br>Program Name:
* <br>Date:
*/
public class AddReviewAction extends BaseAction
...{
//必须重写该核心方法,该方法actionForm将表单的请求参数封装成值对象
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception
...{
DynaValidatorForm addForm = (DynaValidatorForm)form;
String content = (String)addForm.get("content");
String newsId = (String)addForm.get("newsId");
try
...{
News news = mgr.getNews(newsId);
String username = (String)request.getSession(true).getAttribute(AppConstants.LOGIN_USER);
User poster = mgr.getUser(username);
NewsReview newsReview = new NewsReview();
newsReview.setNews(news);
newsReview.setPoster(poster);
newsReview.setContent(content);
newsReview.setPostDate(new Date());
newsReview.setLastModifyDate(new Date());
mgr.saveNewsReview(newsReview);
}
catch (Exception e)
...{
request.setAttribute("newsId" , newsId);
return mapping.findForward("failure");
}
request.setAttribute("newsId" , newsId);
return mapping.findForward("success");
}
}
package org.prolove.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.validator.DynaValidatorForm;
import org.prolove.action.base.BaseAction;
import org.prolove.model.News;
import java.util.Set;
/** *//**
* @author PROLOVE prolve@live.cn
* @version 1.0
* <br>Copyright (C), 2006-2008, PROLOVE
* <br>This program is protected by copyright laws.
* <br>Program Name:
* <br>Date:
*/
public class LoadReviewsByNews extends BaseAction
...{
//必须重写该核心方法,该方法actionForm将表单的请求参数封装成值对象
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception
...{
String newsId = null;
if(request.getAttribute("newsId") == null)
...{
newsId = request.getParameter("newsId");
}
else
...{
newsId = (String)request.getAttribute("newsId");
}
News news = mgr.getNews(newsId);
request.setAttribute("news" , news);
request.setAttribute("reviews",news.getNewsReviews());
return mapping.findForward("success");
}
}
……
2.Spring管理容器Action
采用DelegatingRequestProcessor的整合策略。
struts-config.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<!-- 配置登陆所使用的Form-->
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="user" type="java.lang.String" />
<form-property name="pass" type="java.lang.String" />
</form-bean>
<!-- 添加新闻所用的Form-->
<form-bean name="addNewsForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="title" type="java.lang.String" />
<form-property name="content" type="java.lang.String" />
<form-property name="categoryId" type="java.lang.String" />
</form-bean>
<!-- 添加新闻评论所用的Form-->
<form-bean name="addNewsReviewForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="content" type="java.lang.String" />
<form-property name="newsId" type="java.lang.String" />
</form-bean>
</form-beans>
<global-forwards>
</global-forwards>
<!-- ========================================= Action Mapping Definitions -->
<action-mappings>
<!-- 处理登陆 -->
<action path="/processLogin"
name="loginForm"
scope="request"
validate="true"
input="input">
<forward name="input" path="/index.jsp" />
<forward name="success" path="/listCate.do" />
</action>
<!-- 登出系统 -->
<action path="/logout" scope="request">
<forward name="success" path="/index.jsp"/>
</action>
<!-- 进入主页面 -->
<action path="/listCate" scope="request">
<forward name="success" path="/main.jsp"/>
</action>
<!-- 根据种类加载所有新闻 -->
<action path="/loadNewsByCategory" scope="request">
<forward name="failure" path="/listCate.do"/>
<forward name="success" path="/category_view.jsp"/>
</action>
<!-- 添加新闻 -->
<action path="/addNews"
name="addNewsForm"
scope="request"
validate="true"
input="input">
<forward name="failure" path="/loadNewsByCategory.do"/>
<forward name="success" path="/loadNewsByCategory.do"/>
</action>
<!-- 根据新闻id加载所有评论 -->
<action path="/loadNewsReviewByNews" scope="request">
<forward name="success" path="/news_view.jsp"/>
</action>
<!-- 添加新闻评论 -->
<action path="/addNewsReview"
name="addNewsReviewForm"
scope="request"
validate="true"
input="input">
<forward name="failure" path="/loadNewsReviewByNews.do"/>
<forward name="success" path="/loadNewsReviewByNews.do"/>
</action>
</action-mappings>
<controller inputForward="true" processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<message-resources parameter="resource"/>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
<set-property property="stopOnFirstError" value="true"/>
</plug-in>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/daoContext.xml,
/WEB-INF/applicationContext.xml,
/WEB-INF/action-Servlet.xml"/>
</plug-in>
</struts-config>
action-Servlet.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="actionTemplate" abstract="true" singleton="false">
<property name="mgr" ref="facadeManager"/>
</bean>
<!-- 处理登陆-->
<bean name="/processLogin" class="org.prolove.action.LoginAction" parent="actionTemplate"/>
<!-- 登出系统-->
<bean name="/logout" class="org.prolove.action.Logout"/>
<!-- 列出所有的新闻分类-->
<bean name="/listCate" class="org.prolove.action.ListCate" parent="actionTemplate"/>
<!-- 根据种类列出所有新闻-->
<bean name="/loadNewsByCategory" class="org.prolove.action.LoadNewsByCategory" parent="actionTemplate"/>
<!-- 添加新闻-->
<bean name="/addNews" class="org.prolove.action.AddNewsAction" parent="actionTemplate"/>
<!-- 根据新闻查看所有的评论-->
<bean name="/loadNewsReviewByNews" class="org.prolove.action.LoadReviewsByNews" parent="actionTemplate"/>
<!-- 添加新闻评论-->
<bean name="/addNewsReview" class="org.prolove.action.AddReviewAction" parent="actionTemplate"/>
</beans>
3.数据校验的选择
validation.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
<formset>
<form name="loginForm">
<field property="user" depends="required,minlength">
<arg key="loginForm.user" position="0"/>
<arg name="minlength" key="${var:minlength}" resource="false" position="1"/>
<var>
<var-name>minlength</var-name>
<var-value>4</var-value>
</var>
</field>
<field property="pass" depends="required,minlength">
<arg key="loginForm.pass" position="0"/>
<arg name="minlength" key="${var:minlength}" resource="false" position="1"/>
<var>
<var-name>minlength</var-name>
<var-value>4</var-value>
</var>
</field>
</form>
<form name="addNewsForm">
<field property="title" depends="required">
<arg key="addNewsForm.title" position="0"/>
</field>
<field property="content" depends="required">
<arg key="addNewsForm.content" position="0"/>
</field>
<field property="categoryId" depends="required,integer">
<arg key="addNewsForm.categoryId" position="0"/>
</field>
</form>
<form name="addNewsReviewForm">
<field property="content" depends="required">
<arg key="addNewsReviewForm.content" position="0"/>
</field>
<field property="newsId" depends="required,integer">
<arg key="addNewsReviewForm.categoryId" position="0"/>
</field>
</form>
</formset>
</form-validation>
4.访问权限的控制
package org.prolove.webapp.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.prolove.webapp.util.AppConstants;
/** *//**
* 设置字符集、过滤未登录的非法请求
*/
public class UserLoginFilter implements Filter ...{
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = false;
protected String forwardPath = null;
public void destroy() ...{
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException ...{
// 设置编码方式,web.xml里面有filter参数的初始化设置
if (ignore || (request.getCharacterEncoding() == null)) ...{
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String requesturi = httpServletRequest.getRequestURI();
// 通过检查session中的变量,过虑请求
HttpSession session = httpServletRequest.getSession();
Object currentUser = session.getAttribute(AppConstants.LOGIN_USER);
// 当前会话用户为空而且不是请求登录,退出登录,欢迎页面和根目录则退回到应用的根目录
if (currentUser == null
&& !requesturi.endsWith("/processLogin.do")
&& !requesturi.endsWith("/logout.do")
&& !requesturi.endsWith("/index.jsp")
&& !requesturi.endsWith(httpServletRequest.getContextPath()
+ "/")) ...{
httpServletResponse.sendRedirect(httpServletRequest
.getContextPath()
+ "/");
return;
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException ...{
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
this.forwardPath = filterConfig.getInitParameter("forwardpath");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) ...{
return (this.encoding);
}
}
5.解决中文编码问题
代码同上,另
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
version="2.4">
<filter>
<filter-name>Login Filter</filter-name>
<filter-class>
org.prolove.webapp.filter.UserLoginFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>forwardpath</param-name>
<param-value>index.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Login Filter</filter-name>
<url-pattern>/**//*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<jsp-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
6.JSP页面输出
-->main.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>版面分类</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(loadNewsForm.categoryId.checked)
{
loadNewsForm.submit();
return true;
}
for (var i = 0 ; i < loadNewsForm.categoryId.length ; i++)
{
if( loadNewsForm.categoryId[i].checked )
{
loadNewsForm.submit();
return true;
}
}
alert('请选择要查看的版面!');
return false;
}
function logout(){
logoutForm.submit();
}
</script>
<body>
<table width="500" align="center" cellpadding="1" bgcolor="#99CCCC">
<form name="loadNewsForm" action="loadNewsByCategory.do" method="POST">
<tr>
<td width="40%" colspan="2" align="center">
<p>欢迎,<bean:write name="login_user"/></p>
</td>
</tr>
<tr>
<td width="10%" align="center">
请选择
</td>
<td width="30%" align="center">
版面名
</td>
</tr>
<logic:iterate id="item" name="categories" indexId="index" scope="request">
<tr>
<td width="10%" align="center">
<input type="radio" name="categoryId" value='<bean:write name="item" property="id"/>'>
</td>
<td width="30%" align="center">
<bean:write name="item" property="name"/>
</td>
</tr>
</logic:iterate>
<tr>
<td colspan="2" align="center">
<input type="button" value="查看" onClick="verifyValue();">
<input type="button" value="登出" onClick="logout();">
</td>
</tr>
</form>
<form name="logoutForm" action="logout.do" method="post"">
</form>
</table>
</body>
</html>
-->index.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>登陆系统</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<body>
<logic:messagesPresent>
<div class="title">
<bean:message key="errors.header"/>
<ul>
<html:messages id="error">
<li><bean:write name="error"/></li>
</html:messages>
</ul>
</div>
</logic:messagesPresent>
<logic:present name="errMsg">
<div class="title">
<li><bean:write name="errMsg" scope="request"/>
</div>
</logic:present>
<logic:present name="logout">
<div class="title">
<li><bean:write name="logout" scope="request"/>
</div>
</logic:present>
<table width="400" align="center" bgcolor="#99CCCC">
<html:form action="/processLogin">
<tr>
<td>
请输入用户名:
</td>
<td>
<html:text property="user" size="20"/>
</td>
</tr>
<tr>
<td>
请输入密码:
</td>
<td>
<input type="password" name="pass" size="20">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="确定"> <input type="reset" value="重置">
</td>
</tr>
</html:form>
</table>
</body>
</html>
-->category_view.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>分类新闻</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(loadNewsForm.newsId.checked)
{
loadNewsForm.submit();
return true;
}
for (var i = 0 ; i < loadNewsForm.newsId.length ; i++)
{
if( loadNewsForm.newsId[i].checked )
{
loadNewsForm.submit();
return true;
}
}
alert('请选择要查看的新闻!');
return false;
}
function goMain(){
mainForm.submit();
}
</script>
<body>
<table width="600" align="center" cellpadding="1" bgcolor="#99CCCC">
<form name="loadNewsForm" action="loadNewsReviewByNews.do" method="POST">
<tr>
<td width="60%" colspan="6" align="center">
<p>新闻列表</p> </td>
</tr>
<tr>
<td width="10%" align="center">
请选择 </td>
<td width="10%" align="center">
主题 </td>
<td width="10%" align="center">
发布人 </td>
<td width="10%" align="center">
发布时间 </td>
<td width="10%" align="center">
最后评论时间 </td>
</tr>
<logic:iterate id="item" name="news" indexId="index" scope="request">
<tr>
<td width="10%" align="center">
<input type="radio" name="newsId" value='<bean:write name="item" property="id"/>'>
</td>
<td width="10%" align="center">
<bean:write name="item" property="title"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="content"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="postDate"/>
</td>
<td width="10%" align="center">
<bean:write name="item" property="lastModifyDate"/>
</td>
</tr>
</logic:iterate>
<tr>
<td height="52" colspan="6" align="center">
<input type="button" value="查看" onClick="verifyValue();"> <input type="reset" value="重置"> </td>
</tr>
<tr>
<td height="25" colspan="6" align="center"> </td>
</tr>
<tr>
<td height="25" colspan="6" align="center">发表新的新闻</td>
</tr>
</form>
<html:form action="/addNews">
<tr>
<td colspan="6" align="center">
主题: </td>
</tr>
<tr>
<td colspan="6" align="center">
<html:text property="title" size="80"/>
<input type="hidden" name="categoryId" value='<bean:write name="categoryId"/>'>
</td>
</tr>
<tr>
<td colspan="6" align="center">
内容: </td>
</tr>
<tr>
<td colspan="6" align="center">
<html:textarea property="content" cols="80" rows="20"></html:textarea> </td>
</tr>
<tr>
<td colspan="6" align="center">
<input type="submit" value="提交">
<input type="reset" value="重置">
<input type="button" value="返回" onClick="history.go(-1);">
<input type="reset" value="主页" onClick="goMain();"> </td>
</tr>
</html:form>
<form name="mainForm" action="listCate.do" method="post"">
</form>
</table>
</body>
</html>
-->news_view.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@ include file="taglibs.jsp"%>
<html>
<head>
<title>新闻详细内容</title>
<link href="styles/news.css" rel="stylesheet" type="text/css">
</head>
<script language="javascript">
function verifyValue(){
if(addNewsReviewForm.content.value == ""){
alert('请输入评论内容!');
addNewsReviewForm.content.focus();
return false;
}
addNewsReviewForm.submit();
}
function goMain(){
mainForm.submit();
}
</script>
<body>
<table width="600" align="center" cellpadding="1" bgcolor="#99CCCC">
<tr>
<td colspan="2" align="center" bgcolor="#999999"><p>新闻标题:<bean:write name="news" property="title"/></p></td>
</tr>
<tr>
<td width="20%" align="center">新闻内容:</td>
<td width="80%" align="center" bgcolor="#eeeeee"><bean:write name="news" property="content"/></td>
</tr>
<tr>
<td colspan="2" align="center" bgcolor="#999999">所有评论如下:</td>
</tr>
<logic:iterate id="item" name="reviews" indexId="index" scope="request">
<tr>
<td colspan="2" bgcolor="#96dede">由网友${item.poster.username}于<bean:write name="item" property="postDate"/>发表的评论如下:</td>
</tr>
<tr>
<td colspan="2" align="center" bgcolor="#ffffff"><bean:write name="item" property="content"/> </td>
</tr>
</logic:iterate>
<html:form action="/addNewsReview">
<input type="hidden" name="newsId" value='<bean:write name="news" property="id"/>'>
<tr>
<td colspan="2" align="center"> 我要评论: </tr>
<tr>
<td colspan="2" align="center"><textarea name="content" cols="80" rows="6"></textarea> </td>
</tr>
<tr>
<td colspan="2" align="center"><input name="button" type="submit" value="提交">
<input name="reset" type="reset" value="重置">
<input name="button" type="button" onClick="history.go(-1);" value="返回">
<input name="reset" type="reset" onClick="goMain();" value="主页"> </td>
</tr>
</html:form>
<form name="mainForm" action="listCate.do" method="post"">
</form>
</table>
</body>
</html>
- J2EE项目:整合SSH开发『新闻发布系统』
- SSH整合项目(新闻发布)
- [ssh新闻发布系统二] 读取新闻
- [ssh新闻发布系统三]存储新闻
- [ssh新闻发布系统五]删除新闻
- [ssh新闻发布系统二] 读取新闻
- [ssh新闻发布系统三]存储新闻
- [ssh新闻发布系统五]删除新闻
- [ssh新闻发布系统二] 读取新闻
- [ssh新闻发布系统一]搭建开发环境
- [ssh新闻发布系统一]搭建开发环境
- 在使用SSH框架整合新闻发布系统时候遇到的问题的解决
- 新闻发布系统-项目总结
- 项目案例:新闻发布系统
- J2EE项目之整合Struts+Hibernate开发电子留言系统
- 牛腩新闻发布系统开发流程
- Web开发之新闻发布系统详解
- 牛腩新闻发布系统后台开发总结
- OpenBravo 2.35 安装
- c#读取word内容,c#写入word内容,C#操作word
- 提升JSP应用程序的七大绝招
- 超级实用且不花哨的js代码大全 (六) ----代码判断,幻灯片播放器,广告效果
- “Internet来宾帐户”的设置的问题
- J2EE项目:整合SSH开发『新闻发布系统』
- C#创建、打开、读取、写入、保存Excel,Excel打印输出
- OpenBravo 在eclipse下项目的建立
- 用了半天时间做的一个简单的递归下降分析器
- 一个程序员如何月进万金的?
- 数据库建表时所用到的各类型的索引
- 需求测试总结
- 密码学个人简要笔记
- 想拿到风投?技术创业者请备好五双跑鞋