Struts構(gòu)建netstore項目
一.數(shù)據(jù)庫的連接 : 1.在server.xml(Host中)中的配置: (tomcat5.5)
<Context path="/netstorelm" docBase="C:\tomcat\webapps\shop\netstorelm\WebRoot" debug="0" reloadable="true">
<Resource name="jdbc/netstorelm" auth="Container" type="javax.sql.DataSource" maxActive="5" maxIdle="5" maxWait="10000" username="root" password="root" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/netstore?autoReconnect=true" /> </Context>
2.在DBUtil.java中獲得數(shù)據(jù)庫的連接:
public final class DBUtil { public static Connection getConnection() throws SQLException { return getConnection(true); } //無參數(shù)的連接
public static Connection getConnection(boolean isAutoCommit) throws SQLException { Connection conn = null; try { Context initContext =
new InitialContext();
DataSource ds=(DataSource)initContext.lookup("java:/comp/env/jdbc/netstorelm");
conn = ds.getConnection(); conn.setAutoCommit(isAutoCommit);
} catch (NamingException e) { e.printStackTrace();
throw new SQLException(e.getMessage()); } return conn; }
public static void commit(Connection conn) {
try { if (conn != null && !conn.isClosed()) { conn.commit(); }
} catch (SQLException e) { e.printStackTrace(); } }
public static void rollback(Connection conn) {
try { if (conn != null && !conn.isClosed()) { conn.rollback(); }
} catch (SQLException e) { e.printStackTrace(); } }
public static void release(Connection conn) { if (conn != null) {
try { conn.close();} catch (SQLException e){ e.printStackTrace();}} }
二.關(guān)于異常的處理: public class DataAccessException extends RuntimeException {
public DataAccessException() { super(); }
public DataAccessException(String arg0, Throwable arg1) {super(arg0, arg1);}
public DataAccessException(String arg0) {super(arg0); }
public DataAccessException(Throwable arg0) {super(arg0); } }
三.將程序中的常量單獨存放用于提高Action的獨立性:
public final class Constants {
public static final String SESSION_CONTAINER_KEY = "SessionContainer";
public static final String SIGNON_KEY = "Login";
public static final String SUCCESS_KEY = "Success";
public static final String FAILURE_KEY = "Failure";
public static final String IMAGE_RESOURCE_KEY = "IMAGE_RESOURCE_KEY"; }
四.用戶注冊和登陸模塊:
1.模型層(Model):
public class Customer { private Long id; private String name;
private String password; private String email;
getter( )/setter( ); }
2.DAO持久化層:(Data Access Object):提供該層所有訪問數(shù)據(jù)庫的接口
a.dao接口: public interface CustomerDao {
public Customer getCustomer(Long id);
public List<Customer> getAllCustomers();
public Customer getCustomer(String email, String password);
public int addCustomer(Customer customer);
public int updateCustomer(Customer customer);
public int deleteCustomer(Long id); }
3.daoImpl實現(xiàn): public class CustomerDaoImpl implements CustomerDao {
public Customer getCustomer(String email, String password) {//實現(xiàn)登陸
Connection conn = null; PreparedStatement pstmt = null;
ResultSet rs = null; try { conn = DBUtil.getConnection();
String sql = "select * from CUSTOMERS where email=? and password=?";
pstmt = conn.prepareStatement(sql); pstmt.setString(1, email);
pstmt.setString(2, password); rs = pstmt.executeQuery();
return assembleCustomer(rs); } catch (SQLException e) {
throw new DataAccessException(e);
} finally { DBUtil.release(rs, pstmt, conn); } }
private Customer assembleCustomer(ResultSet rs) throws SQLException {
Customer customer = null;
if (rs != null && rs.next()) { customer = new Customer();
customer.setId(rs.getLong(1)); customer.setName(rs.getString(2));
customer.setPassword(rs.getString(3));customer.setEmail(rs.getString(4));}
return customer; } //實現(xiàn)注冊
public int addCustomer(Customer customer) {//從Action中傳遞過來,ActionForm結(jié)束
Connection conn = null; PreparedStatement pstmt = null;
try { conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(INSERT_SQL);
pstmt.setString(1, customer.getName());
pstmt.setString(2, customer.getPassword());
pstmt.setString(3, customer.getEmail());
return pstmt.executeUpdate();
} catch(SQLException e) { return -1;
} finally { DBUtil.release(pstmt, conn); } }
public List<Customer> getAllCustomers() { //實現(xiàn)用戶管理功能
pstmt = conn.prepareStatement(SELECT_SQL);
rs = pstmt.executeQuery(); return assembleCustomers(rs);....}
private List<Customer> assembleCustomers(ResultSet rs) throws SQLException {
List<Customer> records = new ArrayList<Customer>();
while (rs != null && rs.next()) { Customer customer = new Customer();
customer.setId(rs.getLong(1)); customer.setName(rs.getString(2));
customer.setPassword(rs.getString(3));customer.setEmail(rs.getString(4));
records.add(customer); } return records; }} //返回集合供傳遞
4.通過Dao工廠提供所有DAO層方法的接口: public final class NetstoreDaoFactory {
public static CustomerDao getCustomerDao( ) {return new CustomerDaoImpl();}
public static ItemDao getItemDao() { return new ItemDaoImpl(); }
public static LineItemDao getLineItemDao() {return new LineItemDaoImpl();}
public static OrderDao getOrderDao() { return new OrderDaoImpl(); } }
5.通過業(yè)務(wù)代理接口讓業(yè)務(wù)對象和客戶層分離,有利于隱藏業(yè)務(wù)邏輯的實現(xiàn)
a.接口: public interface NetstoreService {
public List<Item> getItems();
public Customer login(String email, String password);
public Item getItemById(Long id); public void deleteItemById(Long id);
public int addCustomer(Customer customer);
public Customer getCustomerById(Long id); public void saveOrder(Order order);
public List<Customer> getAllCustomers(); public int deleteCustomer(Long id);
public List<Order> getOrders(); public Order getOrder(Long id); }
b.業(yè)務(wù)代理的實現(xiàn)public class NetstoreServiceImpl implements NetstoreService {
private static final CustomerDao customerDao=NetstoreDaoFactory.getCustomerDao();
private static final ItemDao itemDao = NetstoreDaoFactory.getItemDao();
private static final OrderDao orderDao = NetstoreDaoFactory.getOrderDao();
private static final LineItemDao lineItemDao=NetstoreDaoFactory.getLineItemDao();
public List<Item> getItems() { return itemDao.getAllItems(); }
public Customer login(String email, String password) {
return customerDao.getCustomer(email, password); }
public int addCustomer(Customer customer) {
return customerDao.addCustomer(customer); } }
6.登陸過程:a.頁面<logic:notPresent name="SessionContainer" property="customer"
scope="session"> //屬性值須與ActionForm綁定或相同
<html:form action="signin.do" method="post">
<table border=0>
登陸email: <html:text property=" loginForm.email" size="12"/>
登陸密碼 <html:password property=" loginForm.password"/>
<html:submit>登陸</html:submit> </table> </html:form> </logic:notPresent>
b.ActionForm的在config中的實例化:
<form-bean name="loginForm"
type="org.apache.struts.validator.DynaValidatorForm"> //采取動態(tài)驗證表單
<form-property name="email" type="java.lang.String"></form-property>
<form-property name="password" type="java.lang.String" /> </form-bean>
c.配置文件:<action path="/signin"
type="netstore.security.LoginAction"
name="loginForm" scope="request" input="/index.jsp">
<forward name="Success" path="/welcome.jsp"></forward>
<forward name="Failure" path="/security/reg.jsp"></forward>
</action>
d.Action中的處理:public class LoginAction extends NetstoreBaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception {
DynaValidatorForm loginForm = (DynaValidatorForm) form;
String email = (String) loginForm.get("email");
String password = (String) loginForm.get("password");
NetstoreService service = getNetstoreService();
Customer customer = service.login(email, password);
if (customer==null) { ActionMessages errors = new ActionMessages();
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("notmatch"));
saveErrors(request, errors);return mapping.findForward(Constants.FAILURE_KEY);}
else{ SessionContainer sessionContainer = getSessionContainer(request);
sessionContainer.setCustomer(customer);
return mapping.findForward(Constants.SUCCESS_KEY); }} }
Action的實現(xiàn)方式還得考慮保存實體(用戶和購物車)的存在
e. NetstoreService service = getNetstoreService();方法的由來:
public abstract class NetstoreBaseAction extends Action { //所有Action的基類
protected NetstoreService getNetstoreService(){return new NetstoreServiceImpl()}
protected Object getSessionObject(HttpServletRequest req, String attrName) {
Object sessionObj = null;
HttpSession session = req.getSession(false);//不產(chǎn)生一個新的session
if (session != null) { sessionObj = session.getAttribute(attrName); }
return sessionObj; }
protected SessionContainer getSessionContainer(HttpServletRequest request) {
SessionContainer sessionContainer = (SessionContainer) getSessionObject(
request, Constants.SESSION_CONTAINER_KEY);
if (sessionContainer == null) {sessionContainer = new SessionContainer();
HttpSession session = request.getSession(true);
session.setAttribute(Constants.SESSION_CONTAINER_KEY,sessionContainer);
} return sessionContainer; }
protected boolean isLoggedIn(HttpServletRequest request) {
SessionContainer container = getSessionContainer(request);
if (container.getCustomer()!=null&&container.getCustomer().getId() != null) {
return true; } else { return false; } }}
f.SessionContainer用于保存Customer和ShoppingCart信息
public class SessionContainer {
private Customer customer;
private ShoppingCart cart = new ShoppingCart();。。。。。setter()/getter()。。。
public void cleanUp() { setCart(null); setCustomer(null); }}
7.注冊功能的實現(xiàn)過程:a.頁面:
<logic:notPresent name="SessionContainer" property="customer" scope="session">
<html:form action="/reg.do" >
姓名:<html:text property="name" /> email: <html:text property="email" />
密碼: <html:password property="password"/>
<html:submit>注冊</html:submit> </html:form> </logic:notPresent>
b.配置文件:<form-bean name="regForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="password" type="java.lang.String" />
<form-property name="email" type="java.lang.String" />
<form-property name="name" type="java.lang.String" /> </form-bean>
<action path="/reg" name="regForm"
type="netstore.security.RegAction" scope="request" input="/welcome.jsp">
<forward name="Success" path="/welcome.jsp"></forward>
<forward name="Failure" path="/security/reg.jsp"></forward> </action>
c.Aciton: public class RegAction extends NetstoreBaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)throws Exception{
DynaValidatorForm regForm = (DynaValidatorForm) form;
NetstoreService service = getNetstoreService();
Customer customer=new Customer();
customer.setEmail((String) regForm.get("email"));
customer.setPassword((String) regForm.get("password"));
customer.setName((String) regForm.get("name"));
int rs=service.addCustomer(customer);
if (rs ==0) {ActionMessages errors = new ActionMessages();
errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("notmatch"));
saveErrors(request, errors);return mapping.findForward(KEY);
}else{return mapping.findForward(Constants.SUCCESS_KEY);}} }
d.代理接口:
public interface NetstoreService{public int addCustomer(Customer customer);}
e.代理的實現(xiàn):public class NetstoreServiceImpl implements NetstoreService {
private static final CustomerDao customerDao=NetstoreDaoFactory.getCustomerDao()
public int addCustomer(Customer customer){//通過代理得到工廠的方法接口
return customerDao.addCustomer(customer); }}
f:工廠方法的集合:public final class NetstoreDaoFactory {
public static CustomerDao getCustomerDao() {return new CustomerDaoImpl();}}
g:DAO層與關(guān)系數(shù)據(jù)庫的訪問:
public interface CustomerDao { public int addCustomer(Customer customer);}
h.DAO實現(xiàn)層:public int addCustomer(Customer customer) {//與模型層進(jìn)行交互
Connection conn = null; PreparedStatement pstmt = null;
try {conn = DBUtil.getConnection();pstmt=conn.prepareStatement(INSERT_SQL);
pstmt.setString(1, customer.getName()); 。。。return pstmt.executeUpdate(); }
五.購物車模塊:
1.顯示出所有商品:a.歡迎頁面: <logic:forward name="welcome"/>//可實現(xiàn)自動跳轉(zhuǎn)
b.配置全局變量:<forward name="welcome" path="/home.do" redirect="true" />
<action path="/home" type="netstore.item.FeaturedPageAction"
scope="request"> <forward name="Success" path="/index.jsp" /> </action>
c. public class FeaturedPageAction extends NetstoreBaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception {
NetstoreService service = getNetstoreService();
List<Item> featuredItems = service.getItems();
request.setAttribute("FeaturedItemsKey", featuredItems);
return mapping.findForward(Constants.SUCCESS_KEY); }}
d.DAO層實現(xiàn): public List<Item> getAllItems() {
Connection conn = null; PreparedStatement pstmt = null;
ResultSet rs = null; try { conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(SELECT_SQL);
rs = pstmt.executeQuery(); return assembleItems(rs); }
e.頁面顯示: <logic:iterate id="item" name="FeaturedItemsKey">
<html:link page="/viewitemdetail.do" paramName="item" paramProperty="id">
<img border="0" src="<bean:write name="item" property="smallImageURL"/>"/>
</html:link> //通過連接顯示圖片 <bean:write name="item" property="name"/>
<bean:write name="item" format="#,##0.00" property="basePrice"/></b><br>
<bean:write name="item" property="description"/> </logic:iterate>
2.顯示商品的詳細(xì)信息:a.配置信息: <form-bean name="itemDetailForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="view" type="netstore.model.Item" /> </form-bean>
<action path="/viewitemdetail" type="netstore.item.GetItemDetailAction"
name="itemDetailForm" scope="request" input="/index.jsp">
<forward name="Success" path="/catalog/itemdetail.jsp"></forward> </action>
b.Action: public class GetItemDetailAction extends NetstoreBaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception {
Long itemId = new Long(request.getParameter("id"));
NetstoreService service = getNetstoreService();
Item item = service.getItemById(itemId);
((DynaValidatorForm) form).set("view", item);//對動態(tài)表單對象賦值
return mapping.findForward(Constants.SUCCESS_KEY); }}
c.頁面顯示: <img border="0" src="<bean:write name="itemDetailForm" property="view.largeImageURL"/>"/> //顯示一個表單的對象的屬性值
<bean:write name="itemDetailForm" property="view.name"/>
<bean:write name="itemDetailForm" property="view.modelNumber"/>
<html:link page="/cart.do?method=addItem" paramId="id"paramName="itemDetailForm"
paramProperty="view.id" paramScope="request">添加到購物車 </html:link>
3.購物車: a.配置信息(需要繼承DispatchAction)<action path="/cart" type="netstore.order.ShoppingCartAction" parameter="method">
<forward name="Success" path="/order/shoppingcart.jsp"/> </action>
b.Action: public class ShoppingCartAction extends NetstoreDispatchAction {
public ActionForward addItem(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {
SessionContainer sessionContainer = getSessionContainer(request);
Long itemId = new Long(request.getParameter("id"));
String qtyParameter = request.getParameter("qty");
int quantity = 1; if (qtyParameter != null) {
quantity = Integer.parseInt(qtyParameter); }
NetstoreService service = getNetstoreService();
Item item = service.getItemById(itemId);
sessionContainer.getCart().addItem(new ShoppingCartItem(item, quantity));
return mapping.findForward(Constants.SUCCESS_KEY); }
4.檢測是否登陸: public class CheckoutAction extends NetstoreBaseAction {
public ActionForward execute( ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response )throws Exception {
if(!isLoggedIn(request)){return mapping.findForward(Constants.SIGNON_KEY);
} return mapping.findForward( Constants.SUCCESS_KEY ); }}
5.產(chǎn)生隨機(jī)定單號
new Double(Math.random()* System.currentTimeMillis()).toString().substring(3, 8)
6.注銷功能: public class LogoutAction extends NetstoreBaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws Exception {
HttpSession session = request.getSession(false);
if (session != null) {
SessionContainer sessionContainer = getSessionContainer(request);
if (sessionContainer != null) { sessionContainer.cleanUp(); } session.invalidate(); }
return mapping.findForward(Constants.SUCCESS_KEY); }}
7.Action得到動態(tài)表單對象:
a.<form-bean name="updateCusForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="updateCus" type="netstore.model.Customer" />
</form-bean>
b.Action:DynaValidatorForm updateCus = (DynaValidatorForm) form;
Customer cus=(Customer)updateCus.get("updateCus");
8.將表單設(shè)置為只讀: <html:text property="updateCus.name" value="${SessionContainer.customer.name}" readonly="true"/>