基於javaweb的網上書城項目開發全過程之第一步:注冊


注冊是本項目的第一步,首先要分析注冊的流程。

  第一步:創建用戶相關類

      ** domain:User

     ** dao:UserDao

     ** service:UserService

    ** servlet:UserServlet

 注:包名習慣以:cn.域名.項目名.相關類名:如:cn.baidu.bookstore.domain.User

  第二步:用戶注冊流程如下圖

    

第三步:用戶激活功能如下圖

 

 接下來就是代碼的設計

    1、 建立相應的數據庫,並建立以下幾張表:

       

tb_user
tb_category
tb_book
tb_orders
tb_orderitem

表的架構如下

  

 

 

2、導包

   數據庫用c3p0連接池鏈接,所以需要用到和c3p0相關的包

       c3p0-0.9.2-pre1.jar,這是核心包,其依賴包為:mchange-commons-0.2.jar ,還有mysql-connector-java-5.1.28-bin.jar  驅動架包

  當然還需要commons-dbutils這樣的工具包,方便我們設計;commons-beanutils-1.8.3.jar創建javabean的工具包,其依賴包commons-logging-1.1.1.jar

 項目需要發送郵件激活注冊,與javamail相關的包有:mail.jar,activation.jar。同時用要用到ajax相關的包,由於包比較多,這里不再一一列出

  導入配置文件,c3p0配置文件如下:

    

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <c3p0-config>
 3     <!-- 默認配置0~1 -->
 4     <default-config> 
 5         <property name="jdbcUrl">jdbc:mysql://localhost:3306/數據庫名</property>
 6         <property name="driverClass">com.mysql.jdbc.Driver</property>
 7         <property name="user">root</property>
 8         <property name="password">數據庫密碼</property>
 9         
10         <property name="acquireIncrement">3</property>
11         <property name="initialPoolSize">10</property>
12         <property name="minPoolSize">2</property>
13         <property name="maxPoolSize">10</property>
14     </default-config>>
15 </c3p0-config>

為了以后便於把郵件發送人修改,我統一把與郵件有關的設置在一個配置文件中。代碼如下:

  

host=smtp.qq.com    //主機,采用qq郵箱的服務器
uname=郵箱(不帶后面的@qq.com)
pwd=郵箱的密碼
from=郵箱的全部名稱
subject=\u8FD9\u662F\u6765\u81EAYouth\u7F51\u4E0A\u4E66\u57CE\u7684\u6FC0\u6D3B\u90AE\u4EF6  //主題,這里已經轉碼了
content=<a href\="http\://localhost/bookstore/UserServlet?method\=active&code\={0}">\u70B9\u51FB\u8FD9\u91CC\u5B8C\u6210\u6FC0\u6D3B</a>  激活鏈接

3、創建包。

   關於注冊界面,需要創建如下包和類

    com.youth.bookstore.user.domain---->User(javabean類),這是User的領域對象類,其中的字段必須要數據庫對應,包括uid,uname,password,email,code,state

    com.youth.bookstore.user.Dao --->UserDao,這是User持久層

   com.youth.bookstore.user.service --->UserService和UserException類,前者為業務層,后者為繼承了exception的異常類,用於拋出異常信息

   com.youth.bookstore.user.web.servlet --->UserServlet,這是User的表述層

 

這是MVC設計模式,就是把表述層、業務層、數據層分開,這樣做的好處是有利於以后的移植,同時表述層值依賴於業務層,業務層值只依賴於持久層,持久層與數據庫打交道,極大的減少了各類之間的耦合度。

 4、類的設計

   1、UserDao類必須具備五個方法.

      1、User findByUsername(String name)  //通過用戶名查找用戶

      2、User findByEmail(String name)    //通過email查找用戶

      3、void add(User user)    //添加用戶

      4、 User findByCode(String code)  //通過激活碼來查找用戶

      5、void updateState(String uid,boolean state)  //更新用戶狀態,用戶已激活,則其state為true,,否則為false

  2、UserService類的設計

      1、void regist(User form) throws UserException  //用戶注冊,如果用戶名以及郵箱已被注冊,則拋出UserException異常,否則在數據庫中添加注冊

           UserException類為自己寫的類,繼承自Exception。

      2、void active(String code) throws UserException //用戶激活,首先查看用戶的激活狀態,如果已經激活或激活碼不存在,則拋出異常

  3、UserServlet類的設計

      1、激活方法

      2、注冊方法

每個類的具體代碼如下:

   1、UserDao.java

package com.youth.bookstore.user.dao;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import cn.itcast.jdbc.TxQueryRunner;

import com.youth.bookstore.user.domain.User;

/**
 * User持久層
 * @author 11937
 *
 */
public class UserDao {
   private QueryRunner qr = new TxQueryRunner(); 
   
   /**
    * 按用戶名查詢
    * @param username
    * @return
    */
   public User findByUsername(String username){
       try {
        String sql = "select * from tb_user where username=?";
        return qr.query(sql, new BeanHandler<User>(User.class),username);
    } catch (SQLException  e) {
        throw new RuntimeException(e);
    }
   }
   
   /**
    * 按用戶郵箱查詢
    * @param email
    * @return
    */
   public User findByEmail(String email){
       try {
        String sql = "select * from tb_user where email=?";
        return qr.query(sql, new BeanHandler<User>(User.class),email);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
   }
   
   /**
    * 添加用戶
    * @param user
    */
   public void add(User user){
      try {
        String sql = "insert into tb_user values(?,?,?,?,?,?)";
        Object[] params = {user.getUid(),user.getUsername(),
                user.getPassword(),user.getEmail(),
                user.getCode(),user.isState()};
        qr.update(sql, params);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }  
   }
  
   /**
    * 按激活碼查詢
    * @param code
    * @return
    */
   public User findByCode(String code){
       try {
        String sql = "select * from tb_user where code=?";
        return qr.query(sql, new BeanHandler<User>(User.class),code);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
   }
   
   /**
    * 更新用戶激活狀態信息
    * @param uid
    * @param state
    */
   public void updateState(String uid,boolean state){
       try {
         String sql = "update tb_user set state=? where uid=?";
         qr.update(sql, state,uid);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
   }
   
}

 

  2、UserService.java

  

package com.youth.bookstore.user.service;

import com.youth.bookstore.user.dao.UserDao;
import com.youth.bookstore.user.domain.User;

/**
 * User業務層
 * @author 11937
 *
 */
public class UserService {
  private UserDao userDao = new UserDao();
  
  /**
   * 注冊功能
   * @param user
 * @throws UserException 
   */
  public void regist(User form) throws UserException{
      User user = userDao.findByUsername(form.getUsername());
      if(user != null) throw new UserException("用戶名已被注冊");
      user = userDao.findByEmail(form.getEmail());
      if(user != null) throw new UserException("郵箱已被注冊");
      userDao.add(form); 
  }
  
  /*
   * 激活功能
   */
  public void active(String code) throws UserException{
     /*
      * 1、使用code查詢數據庫 ,得到user
      */
      User user = userDao.findByCode(code);
      /*
       * 2、校驗,如果user不存在,拋異常
       */
      if(user == null) throw new UserException("激活碼無效!");
      /*
       * 3、再次校驗,用戶是否已經激活
       */
      if(user.isState()) throw new UserException("您已經激活過了,請直接登錄!");
      /*
       * 4、激活成功
       */
      userDao.updateState(user.getUid(), true);
  }
  
  
}

  3、UserException.java

  

package com.youth.bookstore.user.service;

public class UserException extends Exception{

	public UserException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public UserException(String message) {
		super(message);
	}
   
}

    4、 UserServlet.java

package com.youth.bookstore.user.web.servlet;



import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcast.commons.CommonUtils;
import cn.itcast.mail.Mail;
import cn.itcast.mail.MailUtils;
import cn.itcast.servlet.BaseServlet;

import com.youth.bookstore.user.domain.User;
import com.youth.bookstore.user.service.UserException;
import com.youth.bookstore.user.service.UserService;
 /**
  * User表述層
  * @author 11937
  *
  */
public class UserServlet extends BaseServlet {
  private UserService userService = new UserService();

  /**
   * 激活功能
   * @param request
   * @param response
   * @return
   * @throws ServletException
   * @throws IOException
   */

public String active(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
     /*
      * 1、獲取參數激活碼
      * 2、調用service方法激活
      *   > 保存異常信息到request域,轉發到msg.jsp
      * 3、保存成功信息到request域,轉發到msg.jsp
      */
      String code = request.getParameter("code");
      try {
          userService.active(code);
          request.setAttribute("msg", "恭喜,您已激活成功,請趕快登錄吧!");
        } catch (UserException e) {
          request.setAttribute("msg", e.getMessage());
        }     
          return "f:/jsps/msg.jsp";
  }
  /**
   * 注冊功能
   * @param request
   * @param response
   * @return
   * @throws ServletException
   * @throws IOException
   */

public String regist(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
   /*
    * 1.封裝表單數據到form對象中
    * 2.補全uid、code
    * 3、輸入校驗
    *   >保存錯誤信息、form到request域,轉發到regist.jsp
    * 4、調用service方法完成注冊
    *   >保存錯誤信息、form到request域,轉發到regist.jsp
    * 5、發郵件
    * 6、保存成功信息轉發到regist.jsp
    */
    //封裝表單數據
    User form = CommonUtils.toBean(request.getParameterMap(), User.class);
    //補全
    form.setUid(CommonUtils.uuid());
    form.setCode(CommonUtils.uuid() + CommonUtils.uuid());
    /*輸入校驗
     *   1.創建一個map,用來封裝錯誤信息
     */
    Map<String,String> errors = new HashMap<String,String>();
    String username = form.getUsername();
    if(username == null || username.trim().isEmpty()){
        errors.put("username", "用戶名不能為空");
    }else if(username.length() < 3 || username.length() >10){
        errors.put("username", "用戶名長度必須在3~10之間");
    }
    
    String password = form.getPassword();
    if(password == null || password.trim().isEmpty()){
        errors.put("password", "密碼不能為空");
    }else if(password.length() < 3 || password.length() >10){
        errors.put("password", "密碼長度必須在3~10之間! ");
    }
    
    String email = form.getEmail();
    if(email == null || email.trim().isEmpty()){
        errors.put("email", "郵箱不能為空");
    }else if(!email.matches("\\w+@\\w+\\.\\w+")){
        errors.put("email", "Email格式錯誤 ");
    } 
    
    /*
     * 3、判斷是否存在錯誤信息
     */
    if(errors.size() > 0){
        //保存錯誤信息
        //保存表單數據
        //轉發至regist.jsp
       request.setAttribute("errors", errors);
       request.setAttribute("form", form);
       return "f:/jsps/user/regist.jsp";
    }
    
    /*
     * 調用service的regist方法
     */
    try {
        userService.regist(form);
    } catch (UserException e) {
        //保存錯誤信息
        //保存表單數據
        //轉發至regist.jsp
        request.setAttribute("msg", e.getMessage());
        request.setAttribute("form", form);
        return "f:/jsps/user/regist.jsp";
    }
    /*
     * 說明userService執行成功
    */
    
    /*
     * 發送郵件
     *  准備配置文件
     */
    //獲取配置文件內容
     Properties props = new Properties();
     props.load(this.getClass().getClassLoader().
             getResourceAsStream("email_template.properties"));
     String host = props.getProperty("host"); //獲取主機
     String uname = props.getProperty("uname"); //獲取用戶名
     String pwd = props.getProperty("pwd");
     String from = props.getProperty("from");
     String to = form.getEmail();  //獲取發件人
     String subject = props.getProperty("subject");
     String content = props.getProperty("content");  //獲取郵件內容
     //{0}為占位符的格式
     //MessageFormat.format('{0}或者{1}出錯','name','password')
     content = MessageFormat.format(content,form.getCode()); //替換{0}
     Session session = MailUtils.createSession(host, uname, pwd);
     Mail mail = new Mail(from,to,subject,content);
     try{
     MailUtils.send(session, mail);
     } catch(Exception e){
        throw new RuntimeException(e); 
     }
     /*  1、保存成功信息
     *  2、轉發到msg.jsp
     */
    request.setAttribute("msg", "恭喜,注冊成功!請馬上到郵箱激活 ");
    return "f:/jsps/msg.jsp";
 }
}

   5、User.java

  

package com.youth.bookstore.user.domain;

/**
 * User的領域對象
 * 
 * @author 11937
 * 
 */
public class User {
    /**
     * 對應數據庫
     */
    private String uid; // 主鍵
    private String username;
    private String password;
    private String email;
    private String code; // 激活碼
    private boolean state; // 激活狀態

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }

    public User(String uid, String username, String password, String email,
            String code, boolean state) {
        super();
        this.uid = uid;
        this.username = username;
        this.password = password;
        this.email = email;
        this.code = code;
        this.state = state;
    }

    @Override
    public String toString() {
        return "User [uid=" + uid + ", username=" + username + ", password="
                + password + ", email=" + email + ", code=" + code + ", state="
                + state + "]";
    }

    public User() {
        super();
    }
}

   6、數據庫建立如下:

   

CREATE DATABASE bookstore;

/*用戶表*/
CREATE TABLE tb_user(
  uid CHAR(32) PRIMARY KEY,/*主鍵*/
  username VARCHAR(50) NOT NULL,/*用戶名*/
  `password` VARCHAR(50) NOT NULL,/*密碼*/
  email VARCHAR(50) NOT NULL,/*郵箱*/
  `code` CHAR(64) NOT NULL,/*激活碼*/
  state BOOLEAN/*用戶狀態,有兩種是否激活*/
);

SELECT * FROM tb_user;

/*分類*/
CREATE TABLE category (
  cid CHAR(32) PRIMARY KEY,/*主鍵*/
  cname VARCHAR(100) NOT NULL/*分類名稱*/
);

INSERT  INTO category(cid,cname) VALUES ('1','JavaSE');
INSERT  INTO category(cid,cname) VALUES ('2','JavaEE');
INSERT  INTO category(cid,cname) VALUES ('3','Javascript');

SELECT * FROM category;

/*圖書表*/
CREATE TABLE book (
  bid CHAR(32) PRIMARY KEY,/*主鍵*/
  bname VARCHAR(100),/*圖書名*/
  price DECIMAL(5,1),/*單價*/
  author VARCHAR(20),/*作者*/
  image VARCHAR(200),/*圖片*/
  cid CHAR(32),/*所屬分類*/
  FOREIGN KEY (cid) REFERENCES category(cid)/*建立主外鍵關系*/
);

INSERT  INTO book VALUES ('1','Java編程思想(第4版)','75.6','qdmmy6','book_img/9317290-1_l.jpg','1');
INSERT  INTO book VALUES ('2','Java核心技術卷1','68.5','qdmmy6','book_img/20285763-1_l.jpg','1');
INSERT  INTO book VALUES ('3','Java就業培訓教程','39.9','張孝祥','book_img/8758723-1_l.jpg','1');
INSERT  INTO book VALUES ('4','Head First java','47.5','(美)塞若','book_img/9265169-1_l.jpg','1');
INSERT  INTO book VALUES ('5','JavaWeb開發詳解','83.3','孫鑫','book_img/22788412-1_l.jpg','2');
INSERT  INTO book VALUES ('6','Struts2深入詳解','63.2','孫鑫','book_img/20385925-1_l.jpg','2');
INSERT  INTO book VALUES ('7','精通Hibernate','30.0','孫衛琴','book_img/8991366-1_l.jpg','2');
INSERT  INTO book VALUES ('8','精通Spring2.x','63.2','陳華雄','book_img/20029394-1_l.jpg','2');
INSERT  INTO book VALUES ('9','Javascript權威指南','93.6','(美)弗蘭納根','book_img/22722790-1_l.jpg','3');

SELECT * FROM book;

/*訂單表*/
CREATE TABLE orders (
  oid CHAR(32) PRIMARY KEY,/*主鍵*/
  ordertime DATETIME,/*訂單生成時間*/
  total DECIMAL(10,0),/*訂單合計*/
  state SMALLINT(1),/*訂單狀態:未付款、已付款但未發貨、已發貨但未確認收貨、收貨已結束*/
  uid CHAR(32),/*訂單的主人*/
  address VARCHAR(200),/*訂單的收貨地址*/
  FOREIGN KEY (uid) REFERENCES tb_user(uid)/*建立主外鍵關系*/
);

SELECT * FROM orders;

/*訂單項表*/
CREATE TABLE orderitem (
  iid CHAR(32) PRIMARY KEY,/*主鍵*/
  `count` INT,/*數量*/orderitem
  subtotal DECIMAL(10,0),/*小計*/
  oid CHAR(32),/*所屬訂單*/
  bid CHAR(32),/*訂單項所指的商品*/
  FOREIGN KEY (oid) REFERENCES orders (oid),/*建立主外鍵關系*/
  FOREIGN KEY (bid) REFERENCES book (bid)/*建立主外鍵關系*/
);

SELECT * FROM orderitem;

   

   總結:在設計過程中,有一個問題我幾乎弄了一個下午,就是我在發送郵件的時候,郵箱服務器指定為stmp.qq.com時,用qq郵箱給其他郵箱發郵件時,如果發給對方的是qq郵箱,對方可以接收到郵件,但是無法打開設定的超鏈接,我查看了它的源碼,在相應位置處,確實是一個a標簽,同時鏈接也並有錯誤,單獨把鏈接復制過來去訪問,則可以成功。我用此qq郵箱給163郵箱發送郵件,163郵箱可以直接點開鏈接。后來我又用163郵箱給qq發送郵件,發現根本無法連接163服務器,我確認已經登錄網頁163郵箱,打開了了 POP3/SMTP/IMAP,但是依舊沒有解決此問題,希望看到這篇博客的博友,如果好的解決方案,請分享到下面,感激不盡。

   寫於2015-12-18  21:22:16。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM