https://download.csdn.net/download/weixin_40789841/12496057
3 系統實現
3.1 表示層
3.1.1 登錄界面(loginForm.jsp):
(1)初始化application,採用以下代碼:
ArrayList customers = (ArrayList)application.getAttribute("customers"); //初始化customers
if(customers==null) {
customers = new ArrayList();
application.setAttribute("customers",customers);
}
ArrayList msgs = (ArrayList)application.getAttribute("msgs");//初始化msgs
if(msgs==null) {
msgs = new ArrayList();
application.setAttribute("msgs",msgs);
}
(2)使用javascript實現驗證碼的點擊刷新功能,代碼如下:
<script type="text/javascript">
function refresh(){
loginForm.imgValidate.src = "validate.jsp?id=" + Math.random();//驗證碼點擊刷新
}
</script>
(3)添加登錄界面表單,並用<p style="text-align:center">,實現表單居中顯示,代碼如下:
<p style="text-align:center">
★★歡迎登錄在線交流系統★★<br>
<form action="login.action" name="loginForm" method="post">
輸入賬號:<input name="account" type="text"><BR>
輸入密碼:<input name="password" type="password"><br>
請輸入驗證碼: <input type="text" name="code" size="10">
<img name="imgValidate" src="validate.jsp" οnclick="refresh()"><BR>
<input type="submit" value="登錄" ><br>
<a href = "logininsert.jsp">還沒賬號,點擊這裏註冊</a>
</form> </p>
- 在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。
- 實現效果如圖2
圖 2 登錄界面
3.1.2 註冊界面(logininsert.jsp):
(1)添加註冊的表單,,並用<p style="text-align:center">,實現表單居中顯示,代碼如下:
<p style="text-align:center">
---歡迎來到註冊頁面---<br>
<form action="insert.action" name="form1" method="post">
輸入賬號:<input name="account" type="text"><BR>
輸入密碼:<input name="password" type="password"> <br>
輸入名字:<input name="cname" type="text"> <br>
請輸入驗證碼: <input type="text" name="code" size="10">
<img name="imgValidate" src="validate.jsp" οnclick="refresh()"><BR>
<input type="submit" value="註冊" >
</p>
</form>
(2)使用javascript實現驗證碼的點擊刷新功能,代碼如下:
<script type="text/javascript">
function refresh(){
form1.imgValidate.src = "validate.jsp?id=" + Math.random();//驗證碼點擊刷新
}
</script>
(3)在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。
圖 3 註冊界面
3.1.3 驗證碼實現(validate.jsp)
(1)在內存中創建圖象,代碼如下:
int width = 60, height = 20;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
(2)獲取畫筆,代碼如下:
Graphics g = image.getGraphics();
(3)設定背景色,代碼如下:
g.setColor(new Color(200, 200, 200));
g.fillRect(0, 0, width, height);
(4)取隨機產生的驗證碼(4位數字),代碼如下:
Random rnd = new Random();
int randNum = rnd.nextInt(8999) + 1000;
String randStr = String.valueOf(randNum);
(5)將驗證碼存入session,實現代碼如下
session.setAttribute("randStr", randStr);
(6)將驗證碼顯示到圖象中,代碼如下:
g.setColor(Color.black);
g.setFont(new Font("", Font.PLAIN, 20));
g.drawString(randStr, 10, 17);
(7)隨機產生100個干擾點,使圖象中的驗證碼不易被其他程序探測到,代碼如下:
for (int i = 0; i < 100; i++){
int x = rnd.nextInt(width);
int y = rnd.nextInt(height);
g.drawOval(x, y, 1, 1);
}
(8)輸出圖象到頁面,代碼如下:
ImageIO.write(image, "JPEG", response.getOutputStream());
out.clear();
out = pageContext.pushBody();
(9)驗證碼實現截圖,如圖4:
圖 4 驗證碼實現
3.1.4 登錄失敗頁面、註冊失敗頁面:基本原理都一樣,至於登錄成功的話,將跳轉到聊天界面,註冊成功將跳轉到登錄界面。以登錄失敗爲例:
(1)輸出文字,以及返回相應界面的連接。代碼如下:
<p style="text-align:center">
----- 密碼或賬號錯誤,登錄失敗 -----<br>
<a href = "loginForm.jsp">---點擊這裏,重新登錄---</a>.
</p>
(2)使用轉向語句,實現3秒未操作返回上一個界面。代碼如下:
response.setHeader("Refresh", "3;URL=javascript:history.back(-1)");
(3)在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。
(4)頁面實現如圖5:
圖 5 登錄失敗
3.1.5 驗證碼錯誤頁面(vfail.jsp):跟3.1.4的代碼差不多,不同的是用了javascript:history.back(-1)來返回到上一頁。頁面如圖6:
3.2 業務邏輯層
3.2.1 登錄驗證(loginAction.java、strurs2.xml、loginsuccess.jsp):
(1)用javabean獲取account、password及code(驗證碼)。代碼如下:
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
(2)編寫execute(),先用HttpSession類的API接口獲得存在session中的源驗證碼randStr,讓code與源驗證碼進行對比,如果不同,則return “fail1”;如果相同,則進入賬號密碼驗證。賬號密碼驗證:通過輸入的賬號,查詢數據庫中該賬號的密碼,將查詢得到的密碼與輸入的密碼進行對比,如果相同,則return“success”,否則return “fail”。代碼如下:
public String execute()throws Exception{
CustomerDao cdao = new CustomerDao();
HttpSession session = ServletActionContext.getRequest().getSession(); //用HttpSession類的API接口獲得存在session中的源驗證碼randStr
String checkcode = (String)session.getAttribute("randStr");
if(!code.equals(checkcode)) //讓code與源驗證碼進行對比
{
return "fail1";
}
else{
Customer customer = cdao.getCustomerByAccount(account);// 通過輸入的賬號,查詢數據庫中該賬號的密碼。
if(customer==null || !customer.getPassword().equals(password)){// 將查詢得到的密碼與輸入的密碼進行對比
return "fail";
}
return "success";
}
}
(3)編寫strurs2.xml。先寫入相應action的跳轉界面,實現從表單跳轉到loginAction.java,然後編寫loginAction.java中execute()返回的字符串所要跳轉的相應JSP網頁。代碼如下:
<action name = "login" class="login.loginAction">
<result name="success">/loginsuccess.jsp</result>
<result name="fail">/loginfail.jsp</result>
<result name="fail1">/vfail.jsp</result>
</action>
(4)編寫loginsuccess.jsp。如果只有以上的代碼,會出現一個賬戶同時在線多個。因此需要一個判斷機制,來判斷一個賬戶是否已經登錄。該系統將在線的賬號添加到application類的customers中,該jsp通過輸入的賬號,與customers中的所有的賬號進行對比,如果相同,讓temp這個標誌變量爲1,直接進入聊天界面,不在讓其加入到customers中,如果不相同,則temp爲0,將該customer加入到session中和application類的customers中。不過只有以上判斷還不夠,這缺少第一次登錄時customers爲空的判斷,所以要添加改判斷。代碼如下:
int temp = 0;
request.setCharacterEncoding("gb2312");
String account = request.getParameter("account");
String password = request.getParameter("password");
CustomerDao cdao = new CustomerDao();
Customer customer = cdao.getCustomerByAccount(account);
ArrayList cuss = (ArrayList)application.getAttribute("customers");
if(cuss.size()>0) //判斷是否時該系統第一次啓動
{
for(int i=cuss.size()-1;i>=0;i--)
{
Customer cus = (Customer)cuss.get(i);
if(cus.getAccount().equals(account))//判斷customers的account是否與輸入的account相同
{
temp=1;
break;
}
}
if(temp==1) //如果相同則跳轉到聊天界面
{
response.sendRedirect("chatForm.jsp");
}
else{ //不同則將該customer加入到session中和application類的customers中。
session.setAttribute("customer",customer);
ArrayList customers = (ArrayList)application.getAttribute("customers");
ArrayList msgs = (ArrayList)application.getAttribute("msgs");
customers.add(customer); //將customer添加到customers中
msgs.add(customer.getCname() + "上線啦!");
response.sendRedirect("chatForm.jsp");
}
}
else if(cuss.size()==0){ //如果爲第一次登錄,直接將該customer加入到session中和application類的customers中。
session.setAttribute("customer",customer);
ArrayList customers = (ArrayList)application.getAttribute("customers");
ArrayList msgs = (ArrayList)application.getAttribute("msgs");
customers.add(customer);
msgs.add(customer.getCname() + "上線啦!");
response.sendRedirect("chatForm.jsp"); }
(5)相關實現截圖如圖6:
圖 6 登錄成功跳轉至聊天界面
3.2.2 註冊驗證(loginAction.java、strurs2.xml)
(1)用javabean獲取account、password、cname及code(驗證碼)。代碼如下:
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
(2)編寫execute(),先用HttpSession類的API接口獲得存在session中的源驗證碼randStr,讓code與源驗證碼進行對比,如果不同,則return “fail1”;如果相同,則驗證新加入的賬號是否數據庫中已經存在。驗證新加入的賬號是否數據庫中已經存在:通過輸入的賬號,查詢數據庫中是否存在該賬號如果存在則return “fail”,並判斷賬號、密碼、用戶名是否有沒輸入的,如果沒有輸入,也return “fail”,否則將其插入數據庫,並return “success”,代碼如下:
public String execute()throws Exception{
HttpSession session = ServletActionContext.getRequest().getSession(); // 用HttpSession類的API接口獲得存在session中的源驗證碼randStr
String checkcode = (String)session.getAttribute("randStr");
if(!code.equals(checkcode))// 讓code與源驗證碼進行對比
{
return "fail1";
}
else{
CustomerDao cdao = new CustomerDao();
Customer customer = cdao.getCustomerByAccount(account);
System.out.println(account);
if(customer != null||account.equals("")||password.equals("")||cname.equals(""))//驗證新加入的賬號是否數據庫中已經存在:通過輸入的賬號,查詢數據庫中是否存在該賬號
{
return "fail";
}
else{
int i = cdao.insertCustomer(account,password,cname);
if(i>0)
{
System.out.println("註冊成功 ");
return "success";
}
return "fail";
}
}
}
(3)編寫strurs2.xml。先寫入相應action的跳轉界面,實現從表單跳轉到insertAction.java,然後編寫insertAction.java中execute()返回的字符串所要跳轉的相應JSP網頁。代碼如下:
<action name = "insert" class="login.insertAction">
<result name="success">/loginForm.jsp</result> //當返回success時跳轉到登錄界面,以方便剛註冊的賬號進行登錄
<result name="fail">/insertfail.jsp</result>//返回fail時跳轉到insertfail.jsp
<result name="fail1">/vfail.jsp</result>//返回fail1時跳轉到vfail.jsp
</action>
(4)相關實現截圖如圖7、圖8:
圖 7 註冊
圖 8 註冊失敗
3.2.3 聊天消息及相關功能(msgs.jsp、chatAction.jsp):
(1)編寫chatAction.jsp。使用request對象獲取用戶發送的信息,然後將發送信息的用戶名和信息內容加入到application的msgs對象中。
<%
Customer customer = (Customer)session.getAttribute("customer");
%>
<%
request.setCharacterEncoding("UTF-8");
String msg = request.getParameter("msg");//使用request對象獲取用戶發送的信息
ArrayList msgs = (ArrayList)application.getAttribute("msgs");
if(msg!=null && !msg.equals("")){
msgs.add(customer.getCname() + "說:" + msg); //將發送信息的用戶名和信息內容加入到application的msgs對象中
response.sendRedirect("chatForm.jsp");
}
%>
(2)編寫msgs.jsp。將application中的msgs對象輸出、顯示,然後從application中的customers中將所有用戶賬戶和用戶名顯示在當前在線列,並加入response.setHeader("Refresh","3")進行3秒一次的刷新,以保證信息的實時顯示。代碼如下:
<%
response.setHeader("Refresh","3"); //進行3秒一次的刷新,以保證信息的實時顯示
%>
<table width="80%" border="0" align="center">
<tr bgcolor="orange" align="center">
<td width="75%">消息</td>
<td width="25%">當前在線</td>
</tr>
<tr bgcolor="yellow">
<td><%
ArrayList msgs = (ArrayList)application.getAttribute("msgs");
for(int i=msgs.size()-1;i>=0;i--){ //將application中的msgs對象輸出、顯示
out.println(msgs.get(i) + "<BR>");
}
%></td>
<td valign="top"><%
ArrayList customers = (ArrayList)application.getAttribute("customers");
for(int i=customers.size()-1;i>=0;i--){
Customer customer = (Customer)customers.get(i);
out.println(customer.getAccount() + "(" + customer.getCname() + ")" + "<BR>"); 從application中的customers中將所有用戶賬戶和用戶名顯示在當前在線列
}
%></td>
</tr>
</table>
(3)相關截圖如圖9:
圖 9 聊天功能
3.3數據訪問層
3.3.1 編寫Customer.java,將用戶信息用VO封裝,將輸入的數據進行封裝。代碼如下:
package vo;
public class Customer {
private String account;
private String password;
private String cname;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
3.3.2 編寫CustomerDao.java。該類主要進行對數據庫的訪問和操作。
(1)編寫一個連接數據庫的函數,同時要將相應的驅動程序導入本系統中。因爲本系統採用的時sqlserver2008,所以驅動包爲sqljdbc4.jar,連接數據庫函數爲:
public void initConnection() throws Exception {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn= DriverManager.getConnection("jdbc:sqlserver://192.168.11.128:1433;DatabaseName=SalesDB;user=123;password=12345");
}
(2)編寫查詢函數getCustomerByAccount()。首先,調用上一步的函數連接數據庫,然後設置sql語句,並使用PreparedStatement方法對sql語句設置,以防止sql語句因組織依賴變量導致的出錯發生。接着,用executeQuery()運行sql語句,實現數據的查詢,並使用ResultSet對查詢所得數據進行存儲。然後將這些數據添加進customer中,關閉數據庫連接。代碼如下:
public Customer getCustomerByAccount(String account) throws Exception {
Customer cus = null;
initConnection(); //連接數據庫
String sql =
"SELECT ACCOUNT,PASSWORD,CNAME FROM T_CUSTOMER WHERE ACCOUNT=?"; //sql語句
PreparedStatement ps = conn.prepareStatement(sql);//sql語句設置
ps.setString(1, account);
ResultSet rs = ps.executeQuery(); //運行sql語句
if(rs.next()){
cus = new Customer();
cus.setAccount(rs.getString("ACCOUNT")); //將查詢的數據添加到customer中
cus.setPassword(rs.getString("PASSWORD"));
cus.setCname(rs.getString("CNAME"));
}
closeConnection(); //關閉數據庫連接
return cus;
}
(3)編寫查詢函數insertCustomer()。首先,調用第一步的函數連接數據庫,然後設置sql語句,並使用PreparedStatement方法對sql語句設置,以防止sql語句因組織依賴變量導致的出錯發生。接着,用executeUpdate ()運行sql語句,實現數據的插入,最後關閉數據庫連接。代碼如下:
public int insertCustomer(String account,String password,String cname) throws Exception {
initConnection();//連接數據庫
String sql =
"insert into T_CUSTOMER(ACCOUNT,PASSWORD,CNAME) values(?,?,?)";//插入的sql語句
PreparedStatement ps = conn.prepareStatement(sql);//設置sql語句
ps.setString(1, account);
ps.setString(2, password);
ps.setString(3, cname);
int i= ps.executeUpdate();//運行sql語句
closeConnection();//關閉數據庫連接
return i;