mapengpeng1999@163.com MVC设计模式

所有的网页开发都需要遵守MVC设计模式,M表示Model,V表示View,C表示Controller(控制器)。

Servlet(控制层)调用service(业务层)调用dao(接口层)
控制层:接受请求参数,响应前端数据。几个业务写几个service和几个service实现类。
以后开发中,JSP中不允许连接数据库。在JSP中看不到java代码,在servlet中看不到html代码。
MVC模式:M(model模型)V(view视图)C(controller控制器)
显示层(view):JSP显示页面,不允许有Java代码
控制层(servlet):servlet就是一个java类,可编写大量的java代码,但是很难显示页面。
数据模型(model)dao操作数据库,dao就是一个Java Bean组件,可以重复使用。
除了dao和mvc还有业务层service。
Dao数据访问层或持久化层,进行数据库的数据操作。
客户层:客户端浏览器;显示层:用JSP进行页面渲染;
控制层:servlet连接显示层和业务层;业务层:service层,连接控制层和持久化层,并进行业务处理,如事务;
持久化层:数据访问层,由JDBC完成。

1.两种开发模式

在实际的开发中,有两种模式:
- 模式一:像最早学习JSP语法基础的时候,将显示,数据操作都放在JSP中完成,没有任何的DAO,没有任何架构,
像我们最早的登录程序,loginCheck.jsp中就进行了数据库的校验操作,这种代码的开发,效率非常高,
但是缺点也很明显:代码的耦合度非常高,JSP中存在大量的Java代码,JSP和JAVA代码耦合在一起,很难进行维护。
-  优点:开发效率高,优点类似于php或者asp开发
-  缺点:代码的耦合度很高,jsp中的html代码和Java代码紧密的耦合在一起,造成程序的可读性可维护性很低。

- 模式二:在实际的开发中,几乎都使用MVC设计模式,实际上就是将显示、控制和数据模型相分离:
- 显示层View: jsp:显示非常简单,因为里面可以直接编写html代码,
- 控制层Controller:servlet:本身就是一个Java类,所以可以任意多的编写Java代码,但是显示非常苦难
- 数据模型Model:dao:生产数据模型,就是一个JavaBean的组件,可以重复调用
以后的开发中,就是在JSP中看不到任何实际的Java代码,在Servlet中看不到任何实际的HTML代码,
目前市场上比较流行的MVC框架:
- Struct1:已经N多年没有用过了,并且也没有企业在用。
- Struct2:有巨大的漏洞,现在企业最多10%再用。
- SpringMVC:是目前最流行的MVC框架,并且适用于互联网的RestFul风格的开发

2.MVC的实现

除了DAO和MVC之外,我们还存在一层叫做业务层,不属于DAO和MVC,是独立出来进行业务处理的。
学习了DAO和MVC之后,以后的程序中,JSP是绝对不允许再连接数据库的。

以后的开发中,就是在JSP中看不到任何实际的Java代码,在Servlet中看不到任何实际的HTML代码。
控制层调用业务层,业务层调用dao层。
用户登入和查看图书信息
package com.wanbangee.util;
import java.sql.Connection;
import java.sql.DriverManager;
public class MySQLUtil {
	public final static String DRIVER = "com.mysql.jdbc.Driver";
	public final static String URL = "jdbc:mysql://127.0.0.1:3306/buybook";
	public final static String USER = "root";
	public final static String PASSWORD = "3306";
	public static Connection getConnection() throws Exception {
		Connection conn = null;
		//2 加载驱动程序[实现了JDBC标准接口的MySQL实现程序]
		Class.forName(DRIVER);
		//3取得数据库连接
		conn = DriverManager.getConnection(URL, USER, PASSWORD);
		return conn;
	}
}
package com.wanbangee.entities;
public class Account {
	private Integer accId;
	private String accName;
	private String accPass;
	private Double accBalance;
	public Integer getAccId() {
		return accId;
	}
	public void setAccId(Integer accId) {
		this.accId = accId;
	}
	public String getAccName() {
		return accName;
	}
	public void setAccName(String accName) {
		this.accName = accName;
	}
	public String getAccPass() {
		return accPass;
	}
	public void setAccPass(String accPass) {
		this.accPass = accPass;
	}
	public Double getAccBalance() {
		return accBalance;
	}
	public void setAccBalance(Double accBalance) {
		this.accBalance = accBalance;
	}
	public Account(Integer accId, String accName, String accPass, Double accBalance) {
		super();
		this.accId = accId;
		this.accName = accName;
		this.accPass = accPass;
		this.accBalance = accBalance;
	}
	public Account() {
		super();
		// TODO Auto-generated constructor stub
	}
}
package com.wanbangee.entities;
public class BookInfo {
	private Integer bookNo;
	private String bookName;
	private Double bookPrice;
	private Integer stockId;
	
	private BookStock bookStock;

	public Integer getBookNo() {
		return bookNo;
	}

	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}

	public String getBookName() {
		return bookName;
	}

	public void setBookName(String bookName) {
		this.bookName = bookName;
	}

	public Double getBookPrice() {
		return bookPrice;
	}

	public void setBookPrice(Double bookPrice) {
		this.bookPrice = bookPrice;
	}

	public Integer getStockId() {
		return stockId;
	}

	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}

	public BookStock getBookStock() {
		return bookStock;
	}

	public void setBookStock(BookStock bookStock) {
		this.bookStock = bookStock;
	}

	public BookInfo(Integer bookNo, String bookName, Double bookPrice, Integer stockId) {
		super();
		this.bookNo = bookNo;
		this.bookName = bookName;
		this.bookPrice = bookPrice;
		this.stockId = stockId;
	}

	public BookInfo() {
		super();
		// TODO Auto-generated constructor stub
	}
}
package com.wanbangee.entities;
public class BookStock {
	private Integer stockId;
	private Integer bookNo;
	private Integer stockNum;
	public Integer getStockId() {
		return stockId;
	}
	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public Integer getStockNum() {
		return stockNum;
	}
	public void setStockNum(Integer stockNum) {
		this.stockNum = stockNum;
	}
	public BookStock(Integer stockId, Integer bookNo, Integer stockNum) {
		super();
		this.stockId = stockId;
		this.bookNo = bookNo;
		this.stockNum = stockNum;
	}
	public BookStock() {
		super();
		// TODO Auto-generated constructor stub
	}
}
package com.wanbangee.dao;
import com.wanbangee.entities.Account;
public interface AccountDao {
	//登入:根据用户名和密码返回用户对象
	public Account selectAccountByaccNameAndaccPass(String accName,String accPass);
}
package com.wanbangee.dao;
import java.util.List;
import com.wanbangee.entities.BookInfo;
public interface BookInfoDao {
	//查询所有图书信息,用集合来存储
public List<BookInfo> selectBookInfo();
}
package com.wanbangee.dao;
import com.wanbangee.entities.BookStock;
public interface BookStockDao {
	//根据库存ID查看库存信息,返回一笔数据为库存信息
public BookStock selectBookStockByStockId(Integer stockId);
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.entities.Account;

public class AccountDaoImp implements AccountDao {
	private Connection conn;
	public AccountDaoImp(Connection conn) {
		this.conn = conn;
	}
	@Override
	public Account selectAccountByaccNameAndaccPass(String accName, String accPass) {
		Account account = null;
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql = "select acc_id,acc_name,acc_balance from account where acc_name = ? and acc_pass = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, accName);
			pstate.setString(2, accPass);
			res = pstate.executeQuery();
			while(res.next()) { 
				//不能把密码加进来
				//Account account = new Account(accId, accName, accPass, accBalance)
				//account = new Account(res.getInt(1), res.getString(2), null, res.getDouble(3));
				
				  account = new Account();
				  account.setAccId(res.getInt("acc_id"));
				  account.setAccName(res.getString("acc_name"));
				  account.setAccBalance(res.getDouble("acc_balance")); 
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return account;
	}
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.entities.BookInfo;

public class BookInfoDaoImp implements BookInfoDao {
private Connection conn;
public BookInfoDaoImp(Connection conn) {
	this.conn = conn;
}
	@Override
	public List<BookInfo> selectBookInfo() {
		//查询所有图书信息,用集合来存储
		List<BookInfo> bookInfos = new ArrayList<>();
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql = "select book_no,book_name,book_price,stock_id from book_info ";
			pstate = this.conn.prepareStatement(sql);
			res = pstate.executeQuery();
			while(res.next()) {
				BookInfo bookInfo = new BookInfo(res.getInt("book_no"), res.getString(2), res.getDouble(3), res.getInt(4));
				bookInfos.add(bookInfo);//将对象添加到集合中
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return bookInfos;
	}
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.wanbangee.dao.BookStockDao;
import com.wanbangee.entities.BookInfo;
import com.wanbangee.entities.BookStock;
public class BookStockDaoImp implements BookStockDao {
private Connection conn;
public BookStockDaoImp(Connection conn) {
	this.conn = conn;
}
	@Override
	public BookStock selectBookStockByStockId(Integer stockId) {
		BookStock bookStock = null;
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql = "select stock_id,stock_num,book_no from book_stock where stock_id = ? ";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, stockId);
			res = pstate.executeQuery();
			while(res.next()) {
				bookStock = new BookStock(res.getInt(1), res.getInt(2), res.getInt(3));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return bookStock;
	}
}
package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.dao.imp.AccountDaoImp;
public class AccountDaoFactory {
	public static AccountDao getAccountDaoInstance(Connection conn) {
		return new AccountDaoImp(conn);
	}
}
package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.dao.imp.BookInfoDaoImp;
public class BookInfoDaoFactory {
public static BookInfoDao getBookInfoDaoInstance(Connection conn) {
	return new BookInfoDaoImp(conn);
}
}
package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.BookStockDao;
import com.wanbangee.dao.imp.BookStockDaoImp;
public class BookStockDaoFactory {
	public static BookStockDao getBookStockDaoInstance(Connection conn) {
		return new BookStockDaoImp(conn);
	}
}
package com.wanbangee.service;
import com.wanbangee.entities.Account;
public interface LoginService {
	//登入业务
public Account login(String accName,String accPass);
}
package com.wanbangee.service;
import java.util.List;
import com.wanbangee.entities.BookInfo;
public interface BookService {
	//查看所有图书信息业务
	public List<BookInfo> selectBookInfo();
	//买书业务
	public boolean buyBook(Integer accId,Integer bookNo);
}
package com.wanbangee.service.imp;
import java.sql.Connection;
import com.wanbangee.dao.factory.AccountDaoFactory;
import com.wanbangee.entities.Account;
import com.wanbangee.service.LoginService;
import com.wanbangee.util.MySQLUtil;
public class LoginServiceImp implements LoginService {
	
	@Override
	public Account login(String accName, String accPass) {
		Account account =  null;
		Connection conn = null;
		
		try {
			conn = MySQLUtil.getConnection();
			account = AccountDaoFactory.getAccountDaoInstance(conn).selectAccountByaccNameAndaccPass(accName, accPass);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return account;
	}
}
package com.wanbangee.service.imp;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import com.wanbangee.dao.factory.BookInfoDaoFactory;
import com.wanbangee.dao.factory.BookStockDaoFactory;
import com.wanbangee.entities.BookInfo;
import com.wanbangee.service.BookService;
import com.wanbangee.util.MySQLUtil;

public class BookServiceImp implements BookService {
	//查看图书信息业务
	@Override
	public List<BookInfo> selectBookInfo() {
		Connection conn = null;
		List<BookInfo> bookInfos = null;
		try {
			conn = MySQLUtil.getConnection();
			bookInfos = BookInfoDaoFactory.getBookInfoDaoInstance(conn).selectBookInfo();
			for (BookInfo bookInfo : bookInfos) {//将遍历到的查询结果放到集合中
				bookInfo.setBookStock(BookStockDaoFactory.getBookStockDaoInstance(conn).selectBookStockByStockId(bookInfo.getStockId()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return bookInfos;
	}
	//买书业务
	@Override
	public boolean buyBook(Integer accId, Integer bookNo) {
		return false;
	}
}
package com.wanbangee.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.wanbangee.entities.Account;
import com.wanbangee.service.BookService;
import com.wanbangee.service.LoginService;
import com.wanbangee.service.imp.BookServiceImp;
import com.wanbangee.service.imp.LoginServiceImp;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String path = request.getContextPath();
		
		//根据用户名密码查询数据库
		LoginService loginService = new LoginServiceImp();
		Account account = loginService.login(username, password);
		
		if(null != account) {
			//登录成功
			//将用户信息设置到session域中
			HttpSession session = request.getSession();
			session.setAttribute("account", account);
			
			//查询图书信息,将图书信息加入到request请求域中
			BookService bookService = new BookServiceImp();
			request.setAttribute("bookInfos", bookService.selectBookInfo());//将图书数据加入到请求域中
			request.getRequestDispatcher("/jsp/books.jsp").forward(request, response);//转发
			
		}else {
			//跳转到登录失败页面
			response.sendRedirect(path+"/jsp/fail.jsp");//重定向
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
		String path = request.getContextPath();
%>
	<form action="<%= path %>/LoginServlet" method="post">
		用户名:<input type="text" name="username">
		密码:<input type="password" name="password">
		<input type="submit" value="登录">
	</form>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>登录失败,请重新<a href="login.jsp">登录</a></h1>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
		session.invalidate();//session失效
		response.sendRedirect("login.jsp");//重定向
		//logout.jsp和login.jsp在同一目录
%>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*,com.wanbangee.entities.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){//给注销按钮添加单击事件
	$("#logout").click(function(event){
		
		event.preventDefault();//取消组件的默认行为
		
		if(confirm("确认注销登录吗?")){
			var href = $(this).attr("href");
			//在href属性中获得超链接地址
			//jQuery中attr("href")函数根据属性名取得属性值
			window.location.href = href;//执行重定向
		}
		
	//return false;//取消超链接的默认行为
	});
	
});
</script>
</head>
<body>
	<%
		Account account = (Account)session.getAttribute("account");//得到的是Object类型
		List<BookInfo> bookInfos = (List<BookInfo>)request.getAttribute("bookInfos");
		String path = request.getContextPath();
	%>

	<h2>登录成功,欢迎您:<%= account.getAccName() + ",您的账户余额为:" + account.getAccBalance()%> <a id="logout" href="<%=path %>/jsp/logout.jsp">注销</a></h2>

	<table border="1">
		<caption>图书信息列表</caption>
		<tr>
			<th>图书ID</th>
			<th>图书名</th>
			<th>图书单价</th>
			<th>图书库存</th>
			<th>操作</th>
		</tr>
		<%
			for(BookInfo bookInfo:bookInfos){
				%>
				<tr>
					<td><%=bookInfo.getBookNo()  %></td>
					<td><%=bookInfo.getBookName()  %></td>
					<td><%=bookInfo.getBookPrice()  %></td>
					<td><%=bookInfo.getBookStock().getStockNum()  %></td>
					<!-- 获得BookStock对象    -->
					<td><a href="javascript:;">购买</a></td>
					 <!-- javascript:;用#代替一样的效果,都是没有跳转效果 -->
				</tr>
				<%
			}
		%>
	</table>
</body>
</html>

监听最常用的操作就是进在线用户的列表操作,查看在线用户列表。

·监听最常用的操作就是进在线用户的列表操作,查看在线用户列表。
·把所有的登陆的用户保存到application范围属性中,属性内容是一个List集合
·如果用户进行注销,则移除此用户
和new个class一样new个监听器Listener,next选择相应对象的changes to attributes实现监听接口。
在servlet包中加个监听器取名为OnLineListener

package com.wanbangee.servlet;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import com.wanbangee.entities.Account;

@WebListener
public class OnLineListener implements HttpSessionAttributeListener,HttpSessionListener,ServletContextListener {
	//List<Account> accounts = null;//保存在线用户列表,设置全局变量没有用,每次用户重新登入都要重新取得在线用户列表
	ServletContext application;//把application对象设置为全局的,在这些方法中就都能使用
	
   //用户登入,触发attributeAdded方法执行,
    public void attributeAdded(HttpSessionBindingEvent event)  { 
        Account account = (Account) event.getValue();
        //登入时将account对象放入session域中
        //当session域信息设置时,取得设置的值
        List<Account> accounts = (List<Account>) application.getAttribute("onlines");//每次用户重新登入都要重新取得在线用户列表
        accounts.add(account);//用户登入时将登入的用户信息添加到在线用户列表
        application.setAttribute("onlines", accounts);//再次设置到application域中
        //每次用户登入都能保证application域中用户列表是最新的
    }

	//用户注销时,session域信息移除
    //session注销要实现HttpSessionListener接口
    public void attributeRemoved(HttpSessionBindingEvent event)  { 
    	//Account account = (Account) event.getValue();
    	//当session域信息移除时,取得设置的值
    }
    public void attributeReplaced(HttpSessionBindingEvent event)  { 
    }
	@Override
	public void sessionCreated(HttpSessionEvent event) {
		// session创建不管,只管session注销
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent event) {
		//实现HttpSessionListener接口,获得session注销的信息
		HttpSession session = event.getSession();//取得注销的session
		List<Account> accounts = (List<Account>) application.getAttribute("onlines");//每次用户注销都要重新取得在线用户列表
		
		Account account = (Account)session.getAttribute("account");//注销session前先取得account用户信息
		accounts.remove(account);//用户注销时,将注销的用户移除出在线用户列表
	
		application.setAttribute("onlines", accounts);//再次设置到application域中
	}

	@Override
	public void contextDestroyed(ServletContextEvent event) {
	}

	@Override
	public void contextInitialized(ServletContextEvent event) {
		// 实现ServletContextListener接口,监听服务器的启动和销毁
		//把用户信息放入application域,让所有用户信息取到信息(session域只是当前用户取得,一旦浏览器关闭或重启就取不到了)
		//List<Account> accounts = null;//保存在线用户列表
		List<Account> accounts = new ArrayList<>();//服务器启动时把集合实例化出来
		application = event.getServletContext();//获得application对象
		application.setAttribute("onlines", accounts);//将在线用户列表设置进application域中
	}
}
books.jsp更改下代码,显示在线用户列表

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*,com.wanbangee.entities.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){//给注销按钮添加单击事件
	$("#logout").click(function(event){
		
		event.preventDefault();//取消组件的默认行为
		
		if(confirm("确认注销登录吗?")){
			var href = $(this).attr("href");
			//在href属性中获得超链接地址
			//jQuery中attr("href")函数根据属性名取得属性值
			window.location.href = href;//执行重定向
		}
		
	//return false;//取消超链接的默认行为
	});
	
});
</script>
</head>
<body>
	<%
		Account account = (Account)session.getAttribute("account");//得到的是Object类型
		List<BookInfo> bookInfos = (List<BookInfo>)request.getAttribute("bookInfos");
		String path = request.getContextPath();
		
		 List<Account> accounts = (List<Account>) application.getAttribute("onlines");//每次用户登入成功都要重新取得在线用户列表
	%>

	<h2>登录成功,欢迎您:<%= account.getAccName() + ",您的账户余额为:" + account.getAccBalance()%> <a id="logout" href="${pageContext.request.contextPath}/jsp/logout.jsp">注销</a></h2>

	<table border="1">
		<caption>图书信息列表</caption>
		<tr>
			<th>图书ID</th>
			<th>图书名</th>
			<th>图书单价</th>
			<th>图书库存</th>
			<th>操作</th>
		</tr>
		<%
			for(BookInfo bookInfo:bookInfos){
				%>
				<tr>
					<td><%=bookInfo.getBookNo()  %></td>
					<td><%=bookInfo.getBookName()  %></td>
					<td><%=bookInfo.getBookPrice()  %></td>
					<td><%=bookInfo.getBookStock().getStockNum()  %></td>
					<!-- 获得BookStock对象    -->
					<td><a href="javascript:;">购买</a></td>
					 <!-- javascript:;用#代替一样的效果,都是没有跳转效果 -->
				</tr>
				<%
			}
		%>
	</table>
	<hr/>
	<h3>在线用户列表</h3>
	<ul>
		<!-- 循环在线用户的集合 -->
		<%
		for(Account acc: accounts){
			%>
			<li><%= acc.getAccName() %></li>
			<%
		}
		%>	
	</ul>
</body>
</html>

在jsp中使用EL表达式减少了JSP中的java代码,一定要导包,和引入标签库

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*,com.wanbangee.entities.*" %>
<!-- 导入标签库 : 导入jstl的核心库,prefix前缀-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){
	$("#logout").click(function(event){
		event.preventDefault();//取消组件的默认行为
		if(confirm("确认注销登录吗?")){
			var href = $(this).attr("href");
			window.location.href = href;//执行重定向
			
		}
	//return false;//取消超链接的默认行为
	});
});
</script>
</head>
<body>
	<!--<h3>${bookInfos}</h3>取得集合,但循环不了集合-->
	
	<!-- 取得集合中某个元素  并且获得此元素的bookName属性-->
	<h3>${bookInfos[0].bookName}</h3>
	
	<h2>登录成功,欢迎您:${account.accName},您的账户余额为:${account.accBalance}<a id="logout" href="${pageContext.request.contextPath}/jsp/logout.jsp">注销</a></h2>

	<table border="1">
		<caption>图书信息列表</caption>
		<tr>
			<th>图书ID</th>
			<th>图书名</th>
			<th>图书单价</th>
			<th>图书库存</th>
			<th>操作</th>
		</tr>
		<!-- 
			遍历El表达式取到的集合  bookInfos ,每次循环取得集合中的某个数据赋值给bookInfo
				c:forEach : 遍历标签
					- iteams : 遍历的是哪个集合,通过EL表达式获取集合中的域对象或者其他的信息
					- var : 指定遍历集合的每个元素要赋值的变量
					- begin : 指定集合从什么位置开始遍历,默认是0
					- end : 指定集合遍历结束的位置,默认是集合长度-1
					- step : 步长,每次遍历相隔的数量,默认是1
					- varStatus : 遍历状态,可以从此状态中获得到遍历的元素在集合中的索引
					遍历集合的状态复制给新的变量,可以获取index,fist,last 等等信息
		-->
		<c:forEach var="bookInfo" items="${bookInfos}" varStatus="status">
		<tr>
			<td>${bookInfo.bookNo }</td>
			<td>${bookInfo.bookName }</td>
			<td>${bookInfo.bookPrice }</td>
			<td>${bookInfo.bookStock.stockNum }</td>
			<td><a href="javascript:;"> ${status.index}</a></td>
		</tr>
		</c:forEach>
		
	</table>
	
	<hr/>
	<h3>在线用户列表</h3>
	<ul>
		<c:forEach items="${onlines }" var="account">
			<li>${account.accName }</li>
		</c:forEach>
	</ul>
</body>
</html>

用户注册操作,用户注册信息为:

- 用户名
- 密码
- 头像
要求:
1. 需要两次输入密码,并且两次密码必须相同,在js中验证
2. 上传的头像要求保存在pic目录中,在根目录WebContent下new个pic目录用来存放上传的头像
3. 要求上传头像的文件命名为,客户端IP+时间戳+三位0-9之间随机数.后缀 ,比如1270011607849864318056.jpg
这样是ipv4地址形式,用localhost所访问的是ipv6的地址,用127.0.0.1所访问的是ipv4的地址
4. 注册完成,要求数据表account新增一笔数据,数据列acc_pic 存储是用户注册的头像信息(保存头像图片的路径)
数据表account有5个字段,acc_id自增,acc_name,acc_pass,acc_balance默认为0,acc_pic
package com.wanbangee.util;
import java.sql.Connection;
import java.sql.DriverManager;
public class MySQLUtil {
	public final static String DRIVER = "com.mysql.jdbc.Driver";
	public final static String URL = "jdbc:mysql://127.0.0.1:3306/buybook?useUnicode=true&characterEncoding=utf-8";
	public final static String USER = "root";
	public final static String PASSWORD = "3306";
	public static Connection getConnection() throws Exception {
		Connection conn = null;
		//2 加载驱动程序[实现了JDBC标准接口的MySQL实现程序]
		Class.forName(DRIVER);
		//3取得数据库连接
		conn = DriverManager.getConnection(URL, USER, PASSWORD);
		return conn;
	}
}
package com.wanbangee.util;
//此方法为获得新文件名,客户端IP+时间戳+三位0-9之间随机数.后缀
import javax.servlet.http.HttpServletRequest;
public class NewFileName {
//要取得客户端ip,得有request对象
	public static String getNewFileName(HttpServletRequest request) {
		StringBuffer sb = new StringBuffer();
		//要进行字符串的追加用StringBuffer,String效率比较低
		//取得客户端ip
		//String remoteAddr = request.getRemoteAddr();
		//request.getRemoteAddr()可能是ipv4或ipv6地址
		//用localhost所访问的是ipv6的地址,用127.0.0.1所访问的是ipv4的地址
		//ipv6地址是以冒号:分割的,ipv4地址是以点.分割,所以取得地址时要移除冒号:和点.
		String remoteAddr = request.getRemoteAddr().replaceAll(":", "").replaceAll("\\.", "");
		//replaceAll("\\.", "")和split("\\.")一样,也是支持正则的方法,.要加转义字符
		sb.append(remoteAddr);
		//取得时间戳
		Long currentTime = System.currentTimeMillis();
		sb.append(currentTime);
		//取得三位0-9之间随机数
		for (int i = 0; i < 3; i++) {
			int random = (int) Math.round(Math.random()*9);//Math.round()四舍五入方法结果为long型,要强转为int
			sb.append(random);
		}
		//把它们全部追加到StringBuffer对象sb,最后return这个StringBuffer对象sb
		return sb.toString();
	}
}
package com.wanbangee.entities;
public class Account {
	private Integer accId;
	private String accName;
	private String accPass;
	private Double accBalance;
	private String accPic;
	
	public String getAccPic() {
		return accPic;
	}
	public void setAccPic(String accPic) {
		this.accPic = accPic;
	}
	public Integer getAccId() {
		return accId;
	}
	public void setAccId(Integer accId) {
		this.accId = accId;
	}
	public String getAccName() {
		return accName;
	}
	public void setAccName(String accName) {
		this.accName = accName;
	}
	public String getAccPass() {
		return accPass;
	}
	public void setAccPass(String accPass) {
		this.accPass = accPass;
	}
	public Double getAccBalance() {
		return accBalance;
	}
	public void setAccBalance(Double accBalance) {
		this.accBalance = accBalance;
	}

	public Account(Integer accId, String accName, String accPass, Double accBalance, String accPic) {
		super();
		this.accId = accId;
		this.accName = accName;
		this.accPass = accPass;
		this.accBalance = accBalance;
		this.accPic = accPic;
	}
	public Account() {
		super();
	}
}
package com.wanbangee.dao;
import com.wanbangee.entities.Account;
public interface AccountDao {
	//新增操作,将注册的一个用户信息插入到数据库中,实体类的一个对象就是表的一笔数据
	public void insertAccount(Account account);
}


package com.wanbangee.factory;
import java.sql.Connection;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.imp.AccountDaoImp;
public class AccountDaoFactory {
	public static AccountDao getAccountDaoInstance(Connection conn) {
		return new AccountDaoImp(conn);
	}
}
package com.wanbangee.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.entities.Account;
public class AccountDaoImp implements AccountDao {
	private Connection conn;
	public AccountDaoImp(Connection conn) {
		this.conn = conn;
	}
	@Override
	public void insertAccount(Account account) {
		PreparedStatement pstate = null;
		try {//acc_id自增,acc_balance默认为0,都不用管
			String sql = "insert into account(acc_name,acc_pass,acc_pic) values(?,?,?)";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, account.getAccName());
			pstate.setString(2, account.getAccPass());
			pstate.setString(3, account.getAccPic());
			pstate.execute();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
package com.wanbangee.service;
import com.wanbangee.entities.Account;
public interface RegisterService {
	//注册信息业务
	public void register(Account account);
}
//控制层调用业务层,业务层调用数据访问层
package com.wanbangee.service.imp;
import java.sql.Connection;
import java.sql.SQLException;
import com.wanbangee.entities.Account;
import com.wanbangee.factory.AccountDaoFactory;
import com.wanbangee.service.RegisterService;
import com.wanbangee.util.MySQLUtil;
public class RegisterServiceImp implements RegisterService {
	Connection conn = null;
	@Override
	public void register(Account account) {
		try {
			conn = MySQLUtil.getConnection();
			AccountDaoFactory.getAccountDaoInstance(conn).insertAccount(account);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
package com.wanbangee.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.wanbangee.entities.Account;
import com.wanbangee.service.RegisterService;
import com.wanbangee.service.imp.RegisterServiceImp;
import com.wanbangee.util.NewFileName;

//多次提交不会重复提交,只会覆盖前面的内容
//每次改动程序,都会重新部署,原来上传的文件会消失
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
	//注册信息提交,文件上传的步骤
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1.创建磁盘工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//2.创建处理工具
		ServletFileUpload upload = new ServletFileUpload(factory);
		//3.设置上传文件的大小
		upload.setFileSizeMax(1024*1024*5);//最大可上传5M内容
		
		String accName = "";//用户名
		String accPass = "";//用户密码
		String accPic = "";//用户头像
		
		try {//4.用集合接收表单提交的全部内容
			List<FileItem> fileItems = upload.parseRequest(request);
			//遍历循环集合,用增强for循环foreach
			for (FileItem fileItem : fileItems) {
				if(fileItem.isFormField()) {//不是文件
					if(fileItem.getFieldName().equals("accName")) {
						//如果传过来的是accName,则值就是accName
						//accName = fileItem.getString();//获取accName的值
						//accName = fileItem.getString();//用户名中文传到数据库会乱码马鹏鹏,密码是非中文的不用管
						accName = new String(fileItem.getString().getBytes("ISO8859-1"),"utf-8");
						//但数据库依然乱码???,这里能保证accName不乱码,
						//是连接数据库时乱码,在连库URL后加上?useUnicode=true&characterEncoding=utf-8
					}else if(fileItem.getFieldName().equals("accPass")) {
						accPass = fileItem.getString();//获取accPass的值
					}
				}else {//是文件,就要保存文件
					//首先要取得文件的各种信息,但是要给文件重命名
					//获得文件名后缀suffix,fileItem.getName()获得文件名
					//如取得abc.jpg,按照.来分割,用split(".")方法分割字符串,分割成数组的两个元素,
					//fileItem.getName().split(".")分割后结果是个数组,有2个元素abc和jpg,
					//split(".")分割方法是支持正则的方法,.在正则表达式里表示任意字符,即会将abc.jpg分割成7个字符
					//加个斜杆split("\.")表示它就是一个点,斜杆\是转义字符不能写单个斜杆,必须写两个斜杆\\,split("\\.")
					String suffix = fileItem.getName().split("\\.")[1];
					//给文件accPic重命名,要求上传头像的文件命名为 客户端IP+时间戳+三位1-10之间随机数.后缀
					//取得客户端ip要request对象才能获取,request.getRemoteAddr()
					//在工具类util中写个静态方法取得客户端ip
					accPic = NewFileName.getNewFileName(request)+"."+suffix;//新的文件名
					//在根目录WebContent下new个pic目录用来存放上传的头像
					//保存文件
					InputStream in = fileItem.getInputStream();//取得文件输入流(字节输入流)
					byte[] b = new byte[(int) fileItem.getSize()];//取得集合的字节长度是个long类型要强转为int
					in.read(b);//将内容读取到字节数组中
					//将字节数组写入到新的文件中,文件的路径是pic路径,pic+/+新的文件名,pic路径+File.separator+accPic
					//取得项目虚拟目录真实路径(在硬盘中位置),this.getServletContext()获得application对象,application.getRealPath("/pic")取得硬盘中实际运行项目的地址
					File file = new File(this.getServletContext().getRealPath("/pic")+File.separator+accPic);
					OutputStream out = new FileOutputStream(file);
					out.write(b);//将字节数组写入到流中,把这个流写入到这个文件
					in.close();
					out.close();
					
					//控制层servlet调用业务层
					//将注册的用户信息保存到账户表
					RegisterService service = new RegisterServiceImp();
					Account account = new Account();
					account.setAccName(accName);
					account.setAccPass(accPass);
					account.setAccPic(accPic);
					service.register(account);//传递的是account对象,得将上面那些信息封装成account对象
					
					//注册成功后跳转到登入页面,重定向到/jsp/login.jsp中
					response.sendRedirect(request.getContextPath()+"/jsp/login.jsp");
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/loginServlet" method = "post">
用户名:<input type = "text" name = "username">
密码:<input type = "password" name = "password">
<input type = "submit" value = "登入">
<a href = "register.jsp">注册</a>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src = "${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
 //验证两次输入密码必须一致 
$(function(){
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName">
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>

要求用户名和头像信息一起显示到在线用户列表

修改登录程序,和在线用户列表,要求将用户的头像信息也能够加入到session域中。
当初获取在线用户列表,在监听器OnLineListener.java中,将在线用户信息放到集合中List<Account> accounts,然后在books.jsp页面中获取。集合是从session域中取得的account对象放到List,session中取得的account对象就是登录时放到Account中的对象。


就是在account对象中加个acc_pic属性,即在accountDaoImp.java中查询sql加个acc_pic字段,
然后加入到account对象中account.setAccPic(res.getString("acc_pic"));

在books.jsp中在线用户列表加上头像信息
<h3>在线用户列表</h3>
	<ul>
		<!-- 循环在线用户的集合 -->
		<c:forEach items="${onlines }" var="account">
			<li>${account.accName }----><img src="${pageContext.request.contextPath }/pic/${account.accPic}" width="50px" height="50px"></li>
		</c:forEach>
	</ul>
用EL表达式做循环遍历集合元素,一定要导包和引入标签库

点击在线用户列表的头像就会下载头像

文件下载和FileUpload没关系。图片下载,将图片二进制字节响应给用户。设置响应头和下载路径。

在books.jsp中在线用户列表加上头像a标签下载
<h3>在线用户列表</h3>
	<ul>
		<!-- 循环在线用户的集合 -->
		<c:forEach items="${onlines }" var="account">
			<li>${account.accName }----><a href="${pageContext.request.contextPath }/DownPicServlet?fileName=${account.accPic}"><img src="${pageContext.request.contextPath }/pic/${account.accPic}" width="50px" height="50px"></a></li>
		</c:forEach>
	</ul>
new 个Servlet命名为DownPicServlet用来做图片的下载操作

package com.wanbangee.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//图片下载,将图片二进制字节响应给用户
//设置响应头和下载路径
@WebServlet("/DownPicServlet")
public class DownPicServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//取得超链接用地址栏传递过来得参数fileName
		String fileName = request.getParameter("fileName");
		//获得文件的真实路径
		File file = new File(this.getServletContext().getRealPath("/pic")+File.separator+fileName);
		//获得文件字节输入流
		InputStream in = new FileInputStream(file);
		//这里是file对象,和RegisterServlet.java中fileItem对象不一样的
		byte[] b = new byte[(int) file.length()];
		//将文件内容写到字节数组中,就是一个二进制字节数组
		in.read(b);
		//设置MIME类型,表示是一个文件或二进制流
		response.setContentType("application/octet-stream");
		//不再是以text/html形式了,而是以流的形式进行响应
		//设置响应头(设置为文件下载的形式)
		response.addHeader("Content-Disposition", "attachment;filename="+fileName);
		//文件下载的形式,以这个文件名fileName下载
		//只要将字节数组响应给浏览器就行
		
		// PrintWriter out = response.getWriter(); //字符打印流,不能响应字节,Writer是字符输出流,响应的得是字节
		// out.print(b);//打印的是一个字符
		 
		//向浏览器输出字节数组,一行行输出,但是还不能下载,必须设置MIME类型和响应头
		//要想输出字节得用OutputStream或者PrintStream
		OutputStream out = response.getOutputStream();//这才是字节输出流
		in.close();//关闭字节输入流
		out.write(b);//输出的是字节
		out.close();
		//下载是将文件的二进制字节响应给用户,文件下载和FileUpload组件没有关系
		//断点只能在java程序中
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
//jsp访问和目录有关,映射地址和在哪个目录下无关

Ajax简介

Ajax: Asynchronous JavaScript and xml,叫做异步执行JavaScript和xml,
Ajax并不是一个新的技术,在Ajax这个名字出来之前,叫做局部页面刷新技术,我们之前写过的代码,比如买书程序,
每当向服务器发送一个请求,哪怕只是一点点的局部的内容,都会将整个页面进行刷新,既然是刷新整个页面的话,
那么肯定会重新加载页面的所有内容,导致程序执行效率下降,而如果使用了Ajax之后,就可以实现局部的页面刷新,
不需要再将整个页面刷新,性能显然会比之前好很多。

Ajax主要使用XMLHttpRequest这个对象发送异步请求和响应处理,这个对象也称为Ajax的核心对象,但是这个对象有很大的问题,就是不同的内核的浏览器此对象获取方式不同,也就说兼容性不高。我们目前只关注火狐或者谷歌,IE不管,
IE浏览器执行原生的ajax是有问题的。IE浏览器兼容能执行jQuery封装的ajax

在我们开发中实际上就是可以并发执行JavaScript和Servlet 程序,我们之前所编写所有的jsp和Servlet 程序,
实际上在某一个时间点上,要么只执行Jsp,要么只执行Servlet(后端),两者不能够同时执行,
这样实际上就浪费系统的资源,而且降低了执行的效率。使用了Ajax之后,我们就可以更加高效,快捷的处理器请求。

在这里插入图片描述

原生ajax异步请求

用ajax请求来验证,注册时用户名不能重复。
ajax跳转时地址栏没有发送改变,是个转发操作。
每次都去执行servlet,service,dao来判断用户名是否存在。
从用户感觉上没执行servlet,前后端异步执行了。

Ajax异步请求的步骤:
1.创建XMLHttpRequest对象
2.调用XMLHttpRequest对象的open函数创建提交路径,提交路径为一个Servlet的URL映射地址
3.为XMLHttpRequest对象设置状态改变事件(设置回调函数)
4.调用XMLHttpRequest对象的send函数进行提交
5.获取Servelt响应结果
new个servlet命名为RegisterCheckServlet

package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.service.RegisterService;
import com.wanbangee.service.imp.RegisterServiceImp;


@WebServlet("/RegisterCheckServlet")
public class RegisterCheckServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//ajax提交到servlet,此时ajax状态为2,状态值为2:表示Ajax核心对象已经提交到了Servlet
		
		response.setCharacterEncoding("utf-8");//设置响应内容得字符集,不加的话显示的信息会乱码
		response.setContentType("text/html;charset=uft-8");//设置响应内容的MIME类型
		
		//获得out对象,servlet中把内容响应到页面用out.print()一行行输出
		PrintWriter out = response.getWriter();	
		//如果把内容放到请求域request.setAttribute;放到session就是session.setAttribute
		
		//取得请求参数
		String accName = request.getParameter("accName");
		//获得了用户名就可以去数据库进行校验,用户名在数据库存在就不让注册
		
		//调用业务层
		RegisterService service = new RegisterServiceImp();
		boolean flag = service.checkAccName(accName);
		
		out.print(flag);//将flag响应给前端,前端接收到flag为true表示用户名可用
		
//out.println(false);//开始响应内容给页面,这时ajax状态为3,状态值为3:表示Servlet已经开始响应内容了
//out.println("666");//print加ln表示换行输出,可以多次响应信息
		
		out.close();
		//响应结束,ajax状态为4,状态值为4:表示Servelt响应信息结束
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
在AccountDao加个用户名查询判断:
//根据用户名查询数据笔数,查询为0笔数据说明没有这个用户名,查询为1笔说明这个用户名已经存在
	public int selectCountByAccName(String accName);
在AccountDaoImp复写此方法:
@Override
	public int selectCountByAccName(String accName) {
		int count = 0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select count(*) from account where acc_name = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, accName);
			res = pstate.executeQuery();
			while(res.next()) {
				count = res.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return count;
	}
在业务层RegisterService加个验证用户名是否可用的业务:
//验证用户名是否可用
public boolean checkAccName(String accName);
在RegisterServiceImp复写此方法:
@Override
	public boolean checkAccName(String accName) {
		boolean flag =false;
		Connection conn = null;
		try {
			conn = MySQLUtil.getConnection();
			int count = AccountDaoFactory.getAccountDaoInstance(conn).selectCountByAccName(accName);
			if(count == 0) {
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}
在register.jsp页面展现出来,获取servlet响应的信息。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src = "${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
 //验证两次输入密码必须一致 
$(function(){
	//做ajax异步请求
	var xmlhttp = new XMLHttpRequest();//创建ajax核心对象
	
	var accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
	
	
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		
		if(!accNameCheck){ //accNameCheck响应的信息控制表单能否提交的问题
			alert("用户名不可用"); //true才执行if,false进不来if
			return false;
		}
		
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
	
	
	
	//给这个用户名一个失去焦点的事件(blur)
	$("#accName").blur(function(){
		//alert(123);
		var accName = $(this).val();
		//alert(accName);
		xmlhttp.onreadystatechange = ajaxback;//设置ajax核心对象状态改变事件
		
		xmlhttp.open("get","${pageContext.request.contextPath}/RegisterCheckServlet?accName="+accName);//设置异步请求地址
		//随便用哪种请求方式,在js中用EL表达式
		/*ajax核心对象状态有四种:
			状态值为1 : 表示Ajax核心对象已经设置了提交的路径
			状态值为2:  表示Ajax核心对象已经提交到了Servlet
			状态值为3 : 表示Servlet已经开始响应内容了
			状态值为4 : 表示Servelt响应信息结束  */
	
		xmlhttp.send(null);//ajax提交到Servlet
	});
	
	function ajaxback(){
		//状态改变,执行这个ajaxback事件
		//等Servlet响应信息结束,才获取响应的内容,当ajax状态为4时,获取响应的内容
		//alert(xmlhttp.readyState);//状态1,2,3,4弹出来没有意义
		if(xmlhttp.readyState == 4){//servlet已经响应内容结束了
			//获得响应内容
			var responseContent = xmlhttp.responseText;//获得servlet响应的内容
			//alert(responseContent);
			//servlet响应什么信息能在jsp获取到就行
			if(responseContent == "true" || responseContent == true){
				$("#checkMessage").html("<font style = 'color:green'>用户名可用</font>");
				accNameCheck = true;//accNameCheck响应的信息控制表单能否提交的问题
			}else{
				$("#checkMessage").html("<font style = 'color:red'>用户名不可用</font>");
				accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
			}
		}
	}
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName"><span id = "checkMessage"></span>
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>

jQuery完成异步请求

jQuery对原生js进行了封装,提供一套函数库,也对原生Ajax异步请求进行了封装,使得异步请求更加简单。
通过jQuery帮助手册查看jQuery封装的异步请求的函数(常用的三个函数):
$.ajax(url,[settings]) : 常用,发送请求,[settings]可以设置为get请求或者post请求
$.get(url,[data],[fn],[type]) : 常用,发送get请求
$.post(url,[data],[fn],[type]) : 常用,发送post请求

语法一:$.ajax(url,[settings]) , 通常设置请求类型,参数,请求地址,成功回调函数,失败回调函数等

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src = "${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
 //验证两次输入密码必须一致 
$(function(){
	var accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
	
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		
		if(!accNameCheck){ //accNameCheck响应的信息控制表单能否提交的问题
			alert("用户名不可用"); //true才执行if,false进不来if
			return false;
		}
		
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
	
	
	
	//给这个用户名一个失去焦点的事件(blur)
	$("#accName").blur(function(){
		var accName = $(this).val();
		var param = {
			accName : accName //js中对象的写法
		};
		
		$.ajax({
			type:"post",//请求方式
			url:"${pageContext.request.contextPath}/RegisterCheckServlet",//请求地址
			data:param,//请求参数
			success:function(data){ //表示请求成功的回调函数,data表示接收到的响应内容
				if(data == "true" || data == true){
					$("#checkMessage").html("<font style = 'color:green'>用户名可用</font>");
					accNameCheck = true;//accNameCheck响应的信息控制表单能否提交的问题
				}else{
					$("#checkMessage").html("<font style = 'color:red'>用户名不可用</font>");
					accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
				}
			},
			error:function(data){ //表示请求失败的回调函数,data表示接收到的响应内容
				
			} 
		});
		
	});
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName"><span id = "checkMessage"></span>
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>

语法二:$.get(url,[data],[fn],[type]) 简单的get请求

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src = "${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
 //验证两次输入密码必须一致 
$(function(){
	var accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
	
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		
		if(!accNameCheck){ //accNameCheck响应的信息控制表单能否提交的问题
			alert("用户名不可用"); //true才执行if,false进不来if
			return false;
		}
		
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
	
	
	
	//给这个用户名一个失去焦点的事件(blur)
	$("#accName").blur(function(){
		var accName = $(this).val();
		var param = {
				accName : accName  //js中对象的写法
			};
		
		var url = "${pageContext.request.contextPath}/RegisterCheckServlet";
		$.get(url,param,function(data){//参数3响应完成后的回调函数,data表示接收到的响应内容
			if(data == "true" || data == true){
				$("#checkMessage").html("<font style = 'color:green'>用户名可用</font>");
				accNameCheck = true;//accNameCheck响应的信息控制表单能否提交的问题
			}else{
				$("#checkMessage").html("<font style = 'color:red'>用户名不可用</font>");
				accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
			}
		
		});
		
	});
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName"><span id = "checkMessage"></span>
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>

语法三:$.post(url,[data],[fn],[type]) 简单的post请求

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src = "${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
 //验证两次输入密码必须一致 
$(function(){
	var accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
	
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		
		if(!accNameCheck){ //accNameCheck响应的信息控制表单能否提交的问题
			alert("用户名不可用"); //true才执行if,false进不来if
			return false;
		}
		
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
	
	
	
	
	//给这个用户名一个失去焦点的事件(blur)
	$("#accName").blur(function(){
		var accName = $(this).val();
		var param = {
			accName : accName  //js中对象的写法
		};
		
		var url = "${pageContext.request.contextPath}/RegisterCheckServlet";
		$.post(url,param,function(data){//参数3响应完成后的回调函数,data表示接收到的响应内容
			if(data == "true" || data == true){
				$("#checkMessage").html("<font style = 'color:green'>用户名可用</font>");
				accNameCheck = true;//accNameCheck响应的信息控制表单能否提交的问题
			}else{
				$("#checkMessage").html("<font style = 'color:red'>用户名不可用</font>");
				accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
			}
		
		});
		
	});
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName"><span id = "checkMessage"></span>
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>

JSON数据交互

前后端的异步请求,数据交互往往不是简单的String,boolean等简单类型,
而往往是Map,List,Object(数组,集合,对象)等,这种格式的数据在前端如何解析呢?
为了便于JavaScript解析数据,我们使用JSON格式,步骤如下:
- 导这6个包
commons-beanutils-1.7.0.jar
commons-collections-3.2.jar
commons-lang-2.4.jar
commons-logging-1.1.jar
ezmorph-1.0.4.jar
json-lib-2.2.2-jdk15.jar

编写Servlet,new个Servlet命名为TestJsonDataServlet

package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.entities.BookInfo;
import com.wanbangee.service.BookService;
import com.wanbangee.service.imp.BookServiceImp;
import net.sf.json.JSONArray;
//Json数据交互,复杂数据类型像数组,对象,集合等,要用json数据格式
@WebServlet("/TestJsonDataServlet")
public class TestJsonDataServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setCharacterEncoding("utf-8");//设置响应内容得字符集,不加的话显示的信息会乱码
		response.setContentType("text/html;charset=uft-8");//设置响应内容的MIME类型
		
		//查询图书信息,将图书信息加入到请求域中
		BookService bookService = new BookServiceImp();
		List<BookInfo> bookInfos = bookService.selectBookInfo();
		
		//Map<String,Object> map = new HashMap<>();
		//map.put("books", bookInfos); //响应Map键值对给前端
		//map.put("name", "姜建民");
		//map.put("total", 2);

		//获得out对象,servlet中把内容响应到页面用out.print()一行行输出
		PrintWriter out = response.getWriter();	
		
		//响应的内容不再是普通的格式,而是JSON数据格式
		JSONArray jsonArray = new JSONArray();//实例化JSONArray对象jsonArray
		jsonArray.addAll(bookInfos);//将集合添加到jsonArray中
		
		//jsonArray.element(map);//现在响应的是map键值对
		out.print(jsonArray);//响应jsonArray给前端
		
//out.print(bookInfos);直接响应集合给前端,控制台会收到下面内容,这样的内容js无法解析
//[com.wanbangee.entities.BookInfo@9665b69, com.wanbangee.entities.BookInfo@4e50e443]
//这样的内容js无法解析,这个时候就该用json数据格式
		
		out.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

编写JSP发送异步请求

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){
	var url = "${pageContext.request.contextPath}/TestJsonDataServlet";
	//参数是空的可以不写 var param = {};   $.post(url,param,function(data){
	$.post(url,function(data){//参数为空可以省略
		data = eval(data);//解析字符串为JSON格式
		console.log(data);
		var content = "";
	 	for (var i = 0; i < data.length; i++) {
			//创建一个组件,这种写法很麻烦,没有拼接方便
			//var tr = document.createElement("tr");
			
			/* console.log(data[i].name);
			console.log(data[i].total); //响应Map键值对给前端
			console.log(data[i].books); */
			
			content += "<tr>"
			content += "<td>"+ data[i].bookNo +"</td>"
			content += "<td>"+ data[i].bookName +"</td>"
			content += "<td>"+ data[i].bookPrice +"</td>"
			content += "<td>"+ data[i].bookStock.stockNum +"</td>"
			content += "</tr>"
		} 
		//数据遍历后放到下面的showBook表格中 
		$("#showBook").html(content);//把js中数据放到html中
		//java程序在服务器运行,造成服务器压力大,js代码在浏览器执行
		//这种写法能降低服务器压力,提高服务器效率,提升服务器性能
	});
});
</script>
</head>
<body><!-- 把数据渲染到表格中 -->
	<table border = "1">
		<caption>图书信息表</caption>
		<thead>
			<tr>
				<td>图书号</td>
				<td>图书名</td>
				<td>图书单价</td>
				<td>图书库存</td>
			</tr>
		</thead>
		<tbody id="showBook">
		</tbody>
	</table>
</body>
</html>

总结:

1. 在以后的开发中,不会再使用表单提交,或者超链接等形式直接访问后端,而全使用Ajax异步请求
2. 原生的Ajax异步请求比较麻烦,以后都使用jQuery封装好的请求处理。
3. 异步请求的数据交互一定是使用JSON格式,不仅仅是JavaScript中,
包括Android,IOS端,各种小程序都是发送异步请求,获得JSON数据。
终极项目练习
将登录,注册,图书信息显示,买书程序完成编写,要求
- 所有的请求都是用异步请求
- 图书信息展示,要求分页显示图书信息
package com.wanbangee.util;
import java.sql.Connection;
import java.sql.DriverManager;
public class MYSQLUtil {
	public final static String DRIVER = "com.mysql.jdbc.Driver";
	public final static String URL = "jdbc:mysql://127.0.0.1:3306/buybook";
	public final static String USER = "root";
	public final static String PASSWORD = "3306";
	public static Connection getConnection() throws Exception {
		Connection conn = null;
		//2 加载驱动程序[实现了JDBC标准接口的MySQL实现程序]
		Class.forName(DRIVER);
		//3取得数据库连接
		conn = DriverManager.getConnection(URL, USER, PASSWORD);
		return conn;
	}
}

//为上传的文件重命名
package com.wanbangee.util;
import javax.servlet.http.HttpServletRequest;
public class NewFileName {
	public static String getNewFileName(HttpServletRequest request) {
		StringBuffer sb = new StringBuffer();
		// IPV6 地址是以冒号分割,IPV4以.分割
String remoteAddr = request.getRemoteAddr().replaceAll(":", "").replaceAll("\\.", "");
		sb.append(remoteAddr);
		Long currentTime = System.currentTimeMillis();//取得时间戳
		sb.append(currentTime);
		//三位随机数
		for(int i = 0;i<3;i++) {
			int random = (int) Math.round(Math.random()*9);
			sb.append(random);
		}
		return sb.toString();
	}
}
package com.wanbangee.entities;
public class Account {
	private Integer accId;
	private String accName;
	private String accPass;
	private Double accBalance;
	private String accPic;
	public String getAccPic() {
		return accPic;
	}
	public void setAccPic(String accPic) {
		this.accPic = accPic;
	}
	public Integer getAccId() {
		return accId;
	}
	public void setAccId(Integer accId) {
		this.accId = accId;
	}
	public String getAccName() {
		return accName;
	}
	public void setAccName(String accName) {
		this.accName = accName;
	}
	public String getAccPass() {
		return accPass;
	}
	public void setAccPass(String accPass) {
		this.accPass = accPass;
	}
	public Double getAccBalance() {
		return accBalance;
	}
	public void setAccBalance(Double accBalance) {
		this.accBalance = accBalance;
	}
	public Account() {
	}
	public Account(Integer accId, String accName, String accPass, Double accBalance, String accPic) {
		super();
		this.accId = accId;
		this.accName = accName;
		this.accPass = accPass;
		this.accBalance = accBalance;
		this.accPic = accPic;
	}
}


package com.wanbangee.entities;
public class BookInfo {
	private Integer bookNo;
	private String bookName;
	private Double bookPrice;
	private Integer stockId;
	private BookStock bookStock;
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public Double getBookPrice() {
		return bookPrice;
	}
	public void setBookPrice(Double bookPrice) {
		this.bookPrice = bookPrice;
	}
	public Integer getStockId() {
		return stockId;
	}
	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}
	public BookStock getBookStock() {
		return bookStock;
	}
	public void setBookStock(BookStock bookStock) {
		this.bookStock = bookStock;
	}
	public BookInfo(Integer bookNo, String bookName, Double bookPrice, Integer stockId) {
		super();
		this.bookNo = bookNo;
		this.bookName = bookName;
		this.bookPrice = bookPrice;
		this.stockId = stockId;
	}
	public BookInfo() {
		super();
	}
}


package com.wanbangee.entities;
public class BookStock {
	private Integer stockId;
	private Integer bookNo;
	private Integer stockNum;
	public Integer getStockId() {
		return stockId;
	}
	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public Integer getStockNum() {
		return stockNum;
	}
	public void setStockNum(Integer stockNum) {
		this.stockNum = stockNum;
	}
	public BookStock(Integer stockId, Integer bookNo, Integer stockNum) {
		super();
		this.stockId = stockId;
		this.bookNo = bookNo;
		this.stockNum = stockNum;
	}
	public BookStock() {
		super();
	}
}
package com.wanbangee.dao;
import com.wanbangee.entities.Account;
public interface AccountDao {
	//根据用户名和密码查询用户信息
	public Account selectAccountByAccNameAndAccPass(String accName,String accPass);
	//新增用户信息操作
	public void insertAccount(Account account);
	//根据用户名查询数据笔数
	public int selectCountByAccName(String accName);
	//修改账户余额
	public void updateAccBalanceByAccId(Integer accId,Double bookPrice);
	//查询账户余额
	public Double selectAccBalanceByAccId(Integer accId);
}
package com.wanbangee.dao;
import java.util.List;
import com.wanbangee.entities.BookInfo;
public interface BookInfoDao {
	//查询所有的图书信息,模糊查询和分页查询
	/*@param pageSize 每页显示的数据笔数
	 * @param pageCurrent 当前显示第几页*/
	public List<BookInfo> selectBookInfo(String bookName,Integer pageSize,Integer pageCurrent);
	//查询数据笔数
	public int selectCountByBookName(String bookName);
	//查询图书单价
	public Double selectBookPriceByBookNo(Integer bookNo);
}
package com.wanbangee.dao;
import com.wanbangee.entities.BookStock;
public interface BookStockDao {
	//根据库存ID查询图书的库存信息
	public BookStock selectStockInfoByStockId(Integer stockId);
	//减少库存
	public void updateStockNumByBookNo(Integer bookNo,Integer buyNum);
	//查询图书库存
	public Integer selectStockNumByBookNo(Integer bookNo);
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.entities.Account;
public class AccountDaoImp implements AccountDao {
private Connection conn;
public AccountDaoImp(Connection conn) {
	this.conn = conn;
}
	@Override
	public Account selectAccountByAccNameAndAccPass(String accName, String accPass) {
		Account account  = null;
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql = "select acc_id,acc_balance,acc_pic from account where acc_name = ? and acc_pass = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, accName);
			pstate.setString(2, accPass);
			res = pstate.executeQuery();
			while(res.next()) {
				account = new Account();
				account.setAccName(accName);
				account.setAccId(res.getInt(1));
				account.setAccBalance(res.getDouble(2));
				account.setAccPic(res.getString(3));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return account;
	}

	@Override
	public void insertAccount(Account account) {
		PreparedStatement pstate = null;
		
		try {
			String sql = "insert into account (acc_name,acc_pass,acc_pic) values (?,?,?)";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, account.getAccName());
			pstate.setString(2, account.getAccPass());
			pstate.setString(3, account.getAccPic());
			pstate.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public int selectCountByAccName(String accName) {
		int count = 0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql ="select count(*) from account where acc_name = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, accName);
			res = pstate.executeQuery();
			while(res.next()) {
				count = res.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return count;
	}
	@Override
	public void updateAccBalanceByAccId(Integer accId, Double bookPrice) {
		PreparedStatement pstate = null;
		try {
			String sql = "update account set acc_balance = acc_balance + ? where acc_id = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setDouble(1, bookPrice);
			pstate.setInt(2, accId);
			pstate.execute();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	@Override
	public Double selectAccBalanceByAccId(Integer accId) {
		Double accBalance = 0.0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select acc_balance from account where acc_id = ? ";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, accId);
			res = pstate.executeQuery();
			while(res.next()) {
				accBalance = res.getDouble(1);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return accBalance;
	}
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.entities.BookInfo;
public class BookInfoDaoImp implements BookInfoDao {
	private Connection conn;
	public BookInfoDaoImp(Connection conn) {
		this.conn = conn;
	}
	@Override
	public List<BookInfo> selectBookInfo(String bookName,Integer pageSize,Integer pageCurrent) {
		List<BookInfo> bookInfos = new ArrayList<>();
		PreparedStatement pstate = null;
		ResultSet res = null;
		
		try {
			String sql ="select book_no,book_name,book_price,stock_id from book_info where book_name like ? limit ?,?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1,"%"+bookName+"%");
			pstate.setInt(2, (pageCurrent-1) * pageSize );
			pstate.setInt(3,pageSize );
			res = pstate.executeQuery();
			while(res.next()) {//Integer bookNo, String bookName, Double bookPrice, Integer stockId
				BookInfo bookInfo = new BookInfo(res.getInt(1), res.getString(2), res.getDouble(3), res.getInt(4));
				bookInfos.add(bookInfo);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return bookInfos;
	}

	@Override
	public int selectCountByBookName(String bookName) {
		int  count = 0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select count(*) from book_info where book_name like ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setString(1, "%"+bookName+"%");
			res = pstate.executeQuery();
			while(res.next()) {
				count = res.getInt(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return count;
	}

	@Override
	public Double selectBookPriceByBookNo(Integer bookNo) {
		Double bookPrice = 0.0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select book_price from book_info where book_no = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, bookNo);
			res = pstate.executeQuery();
			while(res.next()) {
				bookPrice = res.getDouble(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return bookPrice;
	}
}
package com.wanbangee.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.wanbangee.dao.BookStockDao;
import com.wanbangee.entities.Account;
import com.wanbangee.entities.BookStock;
public class BookStockDaoImp implements BookStockDao {
	private Connection conn;
	public BookStockDaoImp(Connection conn) {
		this.conn = conn;
	}
	@Override
	public BookStock selectStockInfoByStockId(Integer stockId) {
		BookStock bookStock = null;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select book_no,stock_num from book_stock where stock_id = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, stockId);
			res = pstate.executeQuery();
			while(res.next()) {
				//Integer stockId, Integer bookNo, Integer stockNum
				bookStock = new BookStock(stockId,res.getInt(1),res.getInt(2));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return bookStock;
	}
	@Override
	public void updateStockNumByBookNo(Integer bookNo, Integer buyNum) {
		PreparedStatement pstate = null;
		try {
			String sql = "update book_stock set stock_num = stock_num+? where book_no = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, buyNum);
			pstate.setInt(2, bookNo);
			pstate.execute();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				pstate.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	@Override
	public Integer selectStockNumByBookNo(Integer bookNo) {
		Integer stockNum = 0;
		PreparedStatement pstate = null;
		ResultSet res = null;
		try {
			String sql = "select stock_num from book_stock where book_no = ?";
			pstate = this.conn.prepareStatement(sql);
			pstate.setInt(1, bookNo);
			res = pstate.executeQuery();
			while(res.next()) {
				stockNum = res.getInt(1);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				res.close();
				pstate.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return stockNum;
	}
}
package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.AccountDao;
import com.wanbangee.dao.imp.AccountDaoImp;
public class AccountDaoFactory {
	public static AccountDao getAccountDaoInstance(Connection conn) {
		return new AccountDaoImp(conn);
	}
}

package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.dao.imp.BookInfoDaoImp;
public class BookInfoDaoFactory {
	public static BookInfoDao getBookInfoDaoInstance(Connection conn) {
		return new BookInfoDaoImp(conn);
	}
}

package com.wanbangee.dao.factory;
import java.sql.Connection;
import com.wanbangee.dao.BookStockDao;
import com.wanbangee.dao.imp.BookStockDaoImp;
public class BookStockDaoFactory {
	public static BookStockDao getBookStockDaoInstance(Connection conn) {
		return new BookStockDaoImp(conn);
	}
}

过滤器

package com.wanbangee.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.annotation.WebFilter;
//过滤器,设置请求的统一编码
@WebFilter("/*")
public class CharSetFilter implements Filter {
	public void destroy() {
	}
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding("utf-8");//设置请求的统一编码
		chain.doFilter(request, response);
	}
	public void init(FilterConfig fConfig) throws ServletException {
	}
}
package com.wanbangee.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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//过滤所有请求地址,把不需要过滤的写进if条件中
@WebFilter("/*") //过滤非法用户
public class LoginFiter implements Filter {
	public void destroy() {
	}
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		String path = req.getContextPath();
		String URI = req.getRequestURI();
		HttpSession session = req.getSession();
		if(null != session.getAttribute("account") 
				|| URI.indexOf("login.jsp") != -1 
				|| URI.indexOf("LoginServlet") != -1
				|| URI.indexOf("register.jsp") != -1
				|| URI.indexOf("RegisterCheckServlet") != -1
				|| URI.indexOf("RegisterServlet") != -1 
				|| URI.indexOf("jquery-1.10.1.js") != -1) {
			chain.doFilter(request, response);
		}else {
			res.sendRedirect(path + "/jsp/login.jsp");
		}
	}
	public void init(FilterConfig fConfig) throws ServletException {
	}
}
package com.wanbangee.service;
import java.util.List;
import com.wanbangee.entities.BookInfo;
public interface BookService {
	//模糊查询
	public List<BookInfo> selectBookInfoLikeBookName(String bookName,Integer pageSize,Integer pageCurrent);
	//查询数据笔数
	public int selectCountByBookName(String bookName);
	/**
	 * 	买书
	 * @param accId
	 * @param bookNo
	 * return 
	 *  1 表示买书成功
	 *  2 表示账户余额不足
	 *  3 表示图书库存不足
	 */
	public int buyBook(Integer accId,Integer bookNo);

	/**
	 * 	买多本
	 * @param accId
	 * @param bookNos
	 * return 
	 *  1 表示买书成功
	 *  2 表示账户余额不足
	 *  3 表示图书库存不足
	 */
	public int buyBooks(Integer accId,String bookNos);
}
package com.wanbangee.service;
import com.wanbangee.entities.Account;
public interface LoginService {
	public Account login(String accName,String accPass);
}
package com.wanbangee.service;
import com.wanbangee.entities.Account;
public interface RegisterService {
	//注册业务
	public void register(Account account);
	//验证用户名是否可用
	public boolean checkAccName(String accName);
}
package com.wanbangee.service.imp;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import com.wanbangee.dao.factory.AccountDaoFactory;
import com.wanbangee.dao.factory.BookInfoDaoFactory;
import com.wanbangee.dao.factory.BookStockDaoFactory;
import com.wanbangee.entities.BookInfo;
import com.wanbangee.service.BookService;
import com.wanbangee.util.MYSQLUtil;
public class BookServiceImp implements BookService {
	@Override
	public List<BookInfo> selectBookInfoLikeBookName(String bookName,Integer pageSize,Integer pageCurrent) {
		Connection conn = null;
		List<BookInfo> bookInfos = null;
		
		try {
			conn = MYSQLUtil.getConnection();
			bookInfos = BookInfoDaoFactory.getBookInfoDaoInstance(conn).selectBookInfo(bookName,pageSize,pageCurrent);
			for (BookInfo bookInfo : bookInfos) {
				bookInfo.setBookStock(BookStockDaoFactory.getBookStockDaoInstance(conn).selectStockInfoByStockId(bookInfo.getStockId()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return bookInfos;
	}

	@Override
	public int selectCountByBookName(String bookName) {
		int count = 0;
		Connection conn = null;
		try {
			conn = MYSQLUtil.getConnection();
			count =  BookInfoDaoFactory.getBookInfoDaoInstance(conn).selectCountByBookName(bookName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return count;
	}

	@Override
	public int buyBook(Integer accId, Integer bookNo) {
		int flag = 1;
		Connection conn = null;
		try {
			conn = MYSQLUtil.getConnection();
			conn.setAutoCommit(false);//取消事务的自动提交
			//1查询图书单价
			Double bookPrice = BookInfoDaoFactory.getBookInfoDaoInstance(conn).selectBookPriceByBookNo(bookNo);
			//2 减少图书库存
			BookStockDaoFactory.getBookStockDaoInstance(conn).updateStockNumByBookNo(bookNo, -1);
			//2.1 查询图书库存
			Integer stockNum = BookStockDaoFactory.getBookStockDaoInstance(conn).selectStockNumByBookNo(bookNo);
			if(stockNum < 0) {
				flag = 3;
				throw new RuntimeException("图书库存不足");
			}
			//3 减少账户余额
			AccountDaoFactory.getAccountDaoInstance(conn).updateAccBalanceByAccId(accId, bookPrice*(-1));
			//3.1查询账户余额
			Double accBalance  = AccountDaoFactory.getAccountDaoInstance(conn).selectAccBalanceByAccId(accId);
			if(accBalance < 0) {
				flag = 2;
				throw new RuntimeException("账户余额不足");
			}
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return flag;
	}

	@Override
	public int buyBooks(Integer accId, String bookNos) {
		int flag = 1;
		String bookNoStrs[] = bookNos.split(",");
		Connection conn = null;
		try {
			conn = MYSQLUtil.getConnection();
			conn.setAutoCommit(false);//取消事务的自动提交
			
			for (String bookNoStr : bookNoStrs) {
				//1查询图书单价
				Double bookPrice = BookInfoDaoFactory.getBookInfoDaoInstance(conn).selectBookPriceByBookNo(Integer.parseInt(bookNoStr));
				//2 较少图书库存
				BookStockDaoFactory.getBookStockDaoInstance(conn).updateStockNumByBookNo(Integer.parseInt(bookNoStr), -1);
				//2.1 查询图书库存
				Integer stockNum = BookStockDaoFactory.getBookStockDaoInstance(conn).selectStockNumByBookNo(Integer.parseInt(bookNoStr));
				if(stockNum < 0) {
					flag = 3;
					throw new RuntimeException("图书库存不足");
				}
				//3 减少账户余额
				AccountDaoFactory.getAccountDaoInstance(conn).updateAccBalanceByAccId(accId, bookPrice*(-1));
				//3.1查询账户余额
				Double accBalance  = AccountDaoFactory.getAccountDaoInstance(conn).selectAccBalanceByAccId(accId);
				if(accBalance < 0) {
					flag = 2;
					throw new RuntimeException("账户余额不足");
				}
			}
			
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return flag;
	}
}
package com.wanbangee.service.imp;
import java.sql.Connection;
import com.wanbangee.dao.factory.AccountDaoFactory;
import com.wanbangee.entities.Account;
import com.wanbangee.service.LoginService;
import com.wanbangee.util.MYSQLUtil;
public class LoginServiceImp implements LoginService {
	@Override
	public Account login(String accName, String accPass) {
		Connection conn = null;
		Account account = null;
		
		try {
			conn = MYSQLUtil.getConnection();
			account = AccountDaoFactory.getAccountDaoInstance(conn).selectAccountByAccNameAndAccPass(accName, accPass);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return account;
	}
}
package com.wanbangee.service.imp;
import java.sql.Connection;
import com.wanbangee.dao.factory.AccountDaoFactory;
import com.wanbangee.entities.Account;
import com.wanbangee.service.RegisterService;
import com.wanbangee.util.MYSQLUtil;
public class RegisterServiceImp implements RegisterService {
	@Override
	public void register(Account account) {
		Connection conn = null;
		try {
			conn = MYSQLUtil.getConnection();
			AccountDaoFactory.getAccountDaoInstance(conn).insertAccount(account);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

	@Override
	public boolean checkAccName(String accName) {
		Connection conn = null;
		boolean flag = false;
		
		try {
			conn = MYSQLUtil.getConnection();
			int count = AccountDaoFactory.getAccountDaoInstance(conn).selectCountByAccName(accName);
			if(count == 0) {
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return flag;
	}

}
package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.entities.BookInfo;
import com.wanbangee.service.BookService;
import com.wanbangee.service.imp.BookServiceImp;
import net.sf.json.JSONArray;
@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setCharacterEncoding("UTF-8");//设置响应内容的字符集
		response.setContentType("text/html;charset=utf-8");//设置响应内容的MIME类型
		//获得out对象
		PrintWriter out = response.getWriter();
		//取得请求参数
		String bookName = request.getParameter("bookName");
		Integer pageSize = Integer.parseInt(request.getParameter("pageSize"));
		Integer pageCurrent = Integer.parseInt(request.getParameter("pageCurrent"));
		//调用业务层
		BookService bookService = new BookServiceImp();
		List<BookInfo> bookInfos = bookService.selectBookInfoLikeBookName(bookName,pageSize, pageCurrent);
		int count = bookService.selectCountByBookName(bookName);//查询数据笔数
		
		Map<String,Object> map = new HashMap<>();
		if(bookInfos == null || bookInfos.isEmpty()) {
			map.put("code", "102");
			map.put("message", "查询失败");
		}else {
			map.put("code", 1001);
			map.put("message", "查询成功");
			map.put("bookInfos", bookInfos);//把查询结果集响应给前端
			map.put("total", count);//把查询数据笔数响应给前端
		}
		JSONArray jsonArray = new JSONArray();
		jsonArray.element(map);
		out.print(jsonArray);
		out.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.service.BookService;
import com.wanbangee.service.imp.BookServiceImp;
import net.sf.json.JSONArray;
@WebServlet("/BuyBookServlet")
public class BuyBookServlet extends HttpServlet {
		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		Integer bookNo = Integer.parseInt(request.getParameter("bookNo"));
		Integer accId = Integer.parseInt(request.getParameter("accId"));
		
		response.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();
		
		BookService service = new BookServiceImp();
		
		int flag = service.buyBook(accId, bookNo);
		
		Map<String,Object> map = new HashMap<>();
		
		if(flag == 1) {
			map.put("code", 1001);
			map.put("message", "买书成功");
		}else if(flag == 2) {
			map.put("code", 1002);
			map.put("message", "买书失败,账户余额不足");
		}else if(flag == 3) {
			map.put("code", 1002);
			map.put("message", "买书失败,图书库存不足");
		}
		
		JSONArray json = new JSONArray();
		json.element(map);
		out.print(json);;
		out.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}
}
package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.service.BookService;
import com.wanbangee.service.imp.BookServiceImp;
import net.sf.json.JSONArray;
@WebServlet("/BuyBooksServlet")
public class BuyBooksServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String bookNos = request.getParameter("bookNos");
		Integer accId = Integer.parseInt(request.getParameter("accId"));
		
		response.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();
		
		BookService service = new BookServiceImp();
		
		int flag = service.buyBooks(accId, bookNos);
		
		Map<String,Object> map = new HashMap<>();
		
		if(flag == 1) {
			map.put("code", 1001);
			map.put("message", "买书成功");
		}else if(flag == 2) {
			map.put("code", 1002);
			map.put("message", "买书失败,账户余额不足");
		}else if(flag == 3) {
			map.put("code", 1002);
			map.put("message", "买书失败,图书库存不足");
		}
		
		JSONArray json = new JSONArray();
		json.element(map);
		out.print(json);;
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.wanbangee.entities.Account;
import com.wanbangee.service.LoginService;
import com.wanbangee.service.imp.LoginServiceImp;
import net.sf.json.JSONArray;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String username = request.getParameter("username");//通过参数名取得值,取得的是字符串
		String password = request.getParameter("password");//这个参数名是jsp页面中控件的name给开发人员看的
		//控制层调用业务层
		LoginService loginService = new LoginServiceImp();
		Account account = loginService.login(username, password);
		response.setCharacterEncoding("utf-8");
		//获得out对象,servlet中把内容响应到页面用out.print()一行行输出
		PrintWriter out = response.getWriter();
		Map<String,Object> map = new HashMap<>();
		//map对象存放返回前端的消息
		if(account != null) {
			//登录成功,将用户信息设置到session域中
			HttpSession session = request.getSession(true);
			session.setAttribute("account", account);
			map.put("code", 1001);//map对象的两个属性code和message
			map.put("message", "登录成功");
		}else {
			map.put("code", 1002);
			map.put("message", "登录失败,用户名或密码输入错误");
		}
		//把map信息响应给前端
		JSONArray jsonArray = new JSONArray();	
		jsonArray.element(map);//把一个map对象放进jsonArray
		out.print(jsonArray);//把jsonArray打印到前端页面
		out.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
package com.wanbangee.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wanbangee.service.RegisterService;
import com.wanbangee.service.imp.RegisterServiceImp;
@WebServlet("/RegisterCheckServlet")
public class RegisterCheckServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//ajax提交到servlet,此时ajax状态为2
				response.setCharacterEncoding("utf-8");//设置响应内容得字符集
				response.setContentType("text/html;charset=utf-8");//设置响应内容的MIME类型
				//获得out对象,servlet响应内容用out一行行输出
				PrintWriter out = response.getWriter();	
				//servlet中把内容响应到页面用out.print()
				//如果把内容放到请求域request.setAttribute(name, o);放到session就是session.setAttribute
				
				
				//取得请求参数
				String accName = request.getParameter("accName");
				//获得了用户名就可以去数据库进行校验,用户名在数据库存在就不让注册
				
				//调用业务层
				RegisterService service = new RegisterServiceImp();
				boolean flag = service.checkAccName(accName);
				
				out.print(flag);//将flag响应给前端,前端接收到为true表示用户名可用
				
				
				//out.println(false);//开始响应内容给页面,这时ajax状态为3
				//out.println("666");//可以多次响应,这时ajax状态为3
				
				out.close();//响应结束,ajax状态为4
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
package com.wanbangee.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.wanbangee.entities.Account;
import com.wanbangee.service.RegisterService;
import com.wanbangee.service.imp.RegisterServiceImp;
import com.wanbangee.util.NewFileName;

@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {

		//注册信息提交,文件上传的步骤
		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			//1.创建磁盘工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//2.创建处理工具
			ServletFileUpload upload = new ServletFileUpload(factory);
			//3.设置上传文件的大小
			upload.setFileSizeMax(1024*1024*5);//最大可上传5M内容
			
			String accName = "";//用户名
			String accPass = "";//用户密码
			String accPic = "";//用户头像
			
			try {//4.用集合接收表单提交的全部内容
				List<FileItem> fileItems = upload.parseRequest(request);
				//遍历循环集合,用增强for循环foreach
				for (FileItem fileItem : fileItems) {
					if(fileItem.isFormField()) {//不是文件
						if(fileItem.getFieldName().equals("accName")) {
							//如果传过来的是accName,则值就是accName
							//accName = fileItem.getString();//获取accName的值
							//accName = fileItem.getString();//用户名中文传到数据库会乱码马鹏鹏,密码是非中文的不用管
							accName = new String(fileItem.getString().getBytes("ISO8859-1"),"utf-8");
							//但数据库依然乱码???,这里能保证accName不乱码,
							//是连接数据库时乱码,在连库URL后加上?useUnicode=true&characterEncoding=utf-8
						}else if(fileItem.getFieldName().equals("accPass")) {
							accPass = fileItem.getString();//获取accPass的值
						}
					}else {//是文件,就要保存文件
						//首先要取得文件的各种信息,但是要给文件重命名
						//获得文件名后缀suffix,fileItem.getName()获得文件名
						//如取得abc.jpg,按照.来分割,用split(".")方法分割字符串,分割成数组的两个元素,
						//fileItem.getName().split(".")分割后结果是个数组,有2个元素abc和jpg,
						//split(".")分割方法是支持正则的方法,.在正则表达式里表示任意字符,即会将abc.jpg分割成7个字符
						//加个斜杆split("\.")表示它就是一个点,斜杆\是转义字符不能写单个斜杆,必须写两个斜杆\\,split("\\.")
						String suffix = fileItem.getName().split("\\.")[1];
						//给文件accPic重命名,要求上传头像的文件命名为 客户端IP+时间戳+三位1-10之间随机数.后缀
						//取得客户端ip要request对象才能获取,request.getRemoteAddr()
						//在工具类util中写个静态方法取得客户端ip
						accPic = NewFileName.getNewFileName(request)+"."+suffix;//新的文件名
						//在根目录WebContent下new个pic目录用来存放上传的头像
						//保存文件
						InputStream in = fileItem.getInputStream();//取得文件输入流(字节输入流)
						byte[] b = new byte[(int) fileItem.getSize()];//取得集合的字节长度是个long类型要强转为int
						in.read(b);//将内容读取到字节数组中
						//将字节数组写入到新的文件中,文件的路径是pic路径,pic+/+新的文件名,pic路径+File.separator+accPic
						//取得项目虚拟目录真实路径(在硬盘中位置),this.getServletContext()获得application对象,application.getRealPath("/pic")取得硬盘中实际运行项目的地址
						File file = new File(this.getServletContext().getRealPath("/pic")+File.separator+accPic);
						OutputStream out = new FileOutputStream(file);
						out.write(b);//将字节数组写入到流中,把这个流写入到这个文件
						in.close();
						out.close();
						
						//控制层servlet调用业务层
						//将注册的用户信息保存到账户表
						RegisterService service = new RegisterServiceImp();
						Account account = new Account();
						account.setAccName(accName);
						account.setAccPass(accPass);
						account.setAccPic(accPic);
						service.register(account);//传递的是account对象,得将上面那些信息封装成account对象
						
						//注册成功后跳转到登入页面,重定向到/jsp/login.jsp中
						response.sendRedirect(request.getContextPath()+"/jsp/login.jsp");
					}
				}
			} catch (FileUploadException e) {
				e.printStackTrace();
			}
		}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
books.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){
	//加上查询条件
	var bookName = "";
	
	var pageSize = 5;//默认每页显示5笔数据
	var pageCurrent = 1;//默认显示第一页
	var total = 0;//数据笔数
	var totalPage = 0;//总的数据页数
	
	//从session中获取用户信息
	var accId = '${account.accId}';
	
	
	getAllBooks();//页面加载完成之后就执行查询方法
	//查询图书信息,getAllBooks()函数
	function getAllBooks(){
		var url = "${pageContext.request.contextPath}/BookServlet";
		var param = {
				bookName:bookName,
				pageSize:pageSize,
				pageCurrent:pageCurrent
		};
		$.get(url,param,function(data){
			data = eval(data);
			if(data[0].code == 1002){
				alert(data[0].message);
			}else if(data[0].code == 1001){
				total = data[0].total;//获得总数据笔数
				var content = "";
				var currentSize = data[0].bookInfos.length; //当前页的数据笔数
				var selectAll = $("#selectAll").prop("checked");//获得全选复选框是否被选中
				for(var i = 0;i<data[0].bookInfos.length;i++){
					var bookInfo = data[0].bookInfos[i];
					if(selectAll){
						if(i == 0){ //第一笔数据跨行
							content += "<tr><td><input type='checkBox' class='select' value='"+bookInfo.bookNo+"' checked></td><td>"+bookInfo.bookNo+"</td><td>"+bookInfo.bookName+"</td><td>"+bookInfo.bookPrice+"</td><td>"+bookInfo.bookStock.stockNum+"</td><td><a class='buyBook' abc='"+bookInfo.bookNo+"' href='#'>购买</a></td><td rowspan='"+currentSize+"'><input type='button' class='buyBooks' value='购买所选图书'></td></tr>";
						}else{
							content += "<tr><td><input type='checkBox' class='select' value='"+bookInfo.bookNo+"' checked></td><td>"+bookInfo.bookNo+"</td><td>"+bookInfo.bookName+"</td><td>"+bookInfo.bookPrice+"</td><td>"+bookInfo.bookStock.stockNum+"</td><td><a class='buyBook' abc='"+bookInfo.bookNo+"' href='#'>购买</a></td></tr>";
						}
					}else{
						if(i == 0){ //第一笔数据跨行
							content += "<tr><td><input type='checkBox' class='select' value='"+bookInfo.bookNo+"'></td><td>"+bookInfo.bookNo+"</td><td>"+bookInfo.bookName+"</td><td>"+bookInfo.bookPrice+"</td><td>"+bookInfo.bookStock.stockNum+"</td><td><a class='buyBook' abc='"+bookInfo.bookNo+"' href='#'>购买</a></td><td rowspan='"+currentSize+"'><input type='button' class='buyBooks' value='购买所选图书'></td></tr>";
						}else{
							content += "<tr><td><input type='checkBox' class='select' value='"+bookInfo.bookNo+"'></td><td>"+bookInfo.bookNo+"</td><td>"+bookInfo.bookName+"</td><td>"+bookInfo.bookPrice+"</td><td>"+bookInfo.bookStock.stockNum+"</td><td><a class='buyBook' abc='"+bookInfo.bookNo+"' href='#'>购买</a></td></tr>";
						}
					}
				}
				$("#showBookInfos").html(content);
			}
			scal();
			
		});
	}
	//计算数据页数
	function scal(){
		if(total % pageSize == 0){
			totalPage = total / pageSize;
		}else{
			totalPage = parseInt(total / pageSize) + 1;
		}
		$("#pageMessage").html("共" + total + "笔数据,当前显示第" + pageCurrent + "页,共" + totalPage + "页");
		
		
		//按钮控制
		$("#first").prop("disabled",false);
		$("#up").prop("disabled",false);
		$("#next").prop("disabled",false);
		$("#last").prop("disabled",false);
		if(pageCurrent == totalPage && pageCurrent == 1){//总共只有一页
			$("#first").prop("disabled",true);
			$("#up").prop("disabled",true);
			$("#next").prop("disabled",true);
			$("#last").prop("disabled",true);
		}else if(pageCurrent == totalPage){ //最后一页
			$("#next").prop("disabled",true);
			$("#last").prop("disabled",true);
		}else if(pageCurrent == 1){
			$("#first").prop("disabled",true);
			$("#up").prop("disabled",true);
		}
	}
	
	//查询按钮事件
	$("#queryForm").submit(function(){
		bookName = $("input[name='bookName']").val();
		pageCurrent = 1;
		getAllBooks();//执行查询
		return false;
	});
	
	//分页按钮事件
	$("#first").click(function(){
		pageCurrent = 1;
		getAllBooks();//执行查询
	});
	$("#up").click(function(){
		pageCurrent = pageCurrent - 1;
		getAllBooks();//执行查询
	});
	$("#next").click(function(){
		pageCurrent = pageCurrent + 1;
		getAllBooks();//执行查询
	});
	$("#last").click(function(){
		pageCurrent = totalPage;
		getAllBooks();//执行查询
	});
	
	//下拉列表的更改选项事件
	$("#changeSize").change(function(){
		pageCurrent = 1;
		pageSize = $(this).val();
		getAllBooks();//执行查询
	});
	
	$("#logout").click(function(event){
		event.preventDefault();//取消组件的默认行为
		if(confirm("确认注销登录吗?")){
			var href = $(this).attr("href");
			window.location.href = href;//执行重定向
		}
	//return false;//取消超链接的默认行为
	});
	
	//买书事件
	$("#showBookInfos").delegate(".buyBook","click",function(){
		var bookNo = $(this).attr("abc");
		var url = "${pageContext.request.contextPath}/BuyBookServlet";
		var param = {
				accId:accId,
				bookNo:bookNo
		};
		$.get(url,param,function(data){
			data = eval(data);
			if(data[0].code == 1001){
				alert(data[0].message);
				getAllBooks();//执行查询
				
			}else if(data[0].code == 1002){
				alert(data[0].message);
			}
		});
		return false;
	});
	
	//全选/全不选的操作
	$("#selectAll").click(function(){
		if($(this).prop("checked") == true){ //表示全选按钮被选中
			$(".select").prop("checked",true);//其余的复选框全部选中
		}else{
			$(".select").prop("checked",false);//其余的复选框全不选中
		}
		
	});
	//单独选择复选框,若全部选中的情况,全选/全不选 也必须选中
	$("#showBookInfos").delegate(".select","click",function(){
		if($(this).prop("checked") == true){
		//如果当前的是被选种,那么得判断所有的是否都选择
		//判断所有的是否都被选中 
		
			var flag = true;// 默认都被选中
			var checkBoxs = $(".select"); //取得所有的复选框
			for(var i = 0;i < checkBoxs.length;i++){
				if($(checkBoxs[i]).prop("checked") == false){ //只要一个不被选中,flag = false
					flag = false;
					break;
				}
			}
			if(flag){
				$("#selectAll").prop("checked",true);
			}else{
				$("#selectAll").prop("checked",false);
			}
		
		}else if($(this).prop("checked") == false){
			//如果当前是取消选中,那么全选/全不选 取消选中
			$("#selectAll").prop("checked",false);
		}
	});
	
	
	$("#showBookInfos").delegate(".buyBooks","click",function(){
		var bookNos = "";
		var checkBoxs = $(".select"); //取得所有的复选框
		for(var i = 0;i < checkBoxs.length;i++){
			if($(checkBoxs[i]).prop("checked") == true){ //如果被选中
				bookNos += $(checkBoxs[i]).val() + ","
			}
		}
		if(bookNos == ""){
			alert("请选择要购买的图书");
			return false;
		}
		
		var url = "${pageContext.request.contextPath}/buyBooksServlet";
		var param = {
				accId:accId,
				bookNos:bookNos
		};
		$.get(url,param,function(data){
			data = eval(data);
			if(data[0].code == 1001){
				alert(data[0].message);
				getAllBooks();//执行查询
			}else if(data[0].code == 1002){
				alert(data[0].message);
			}
		});
		
	});	
});
</script>
</head>
<body>
	<h2>XXX图书商场欢迎您:${account.accName},<a id="logout" href="${pageContext.request.contextPath}/jsp/logout.jsp">注销</a></h2>
	<form id="queryForm" action="">
		图书名:<input type="text" name = "bookName"> <input type="submit" value="查询">
	</form>
	<table border='1'>
		<caption>图书信息表</caption>
		<thead>
			<tr>
				<th><input type="checkbox" id="selectAll">全选/全不选</th>
				<th>图书编号</th>
				<th>图书名称</th>
				<th>图书单价</th>
				<th>图书库存</th>
				<th>操作</th>
				<th>购买多本</th>
			</tr>
		</thead>
		<tbody id="showBookInfos"></tbody>
	</table>
	<input type="button" value="首页" id="first">
	<input type="button" value="上一页" id="up">
	<input type="button" value="下一页" id="next">
	<input type="button" value="尾页" id="last">
	<span id="pageMessage" style="color:blue"></span>
	<span style="color:blue">,每页显示
		<select id="changeSize">
			<option value="3">3</option>
			<option value="5" selected="selected">5</option>
			<option value="10">10</option>
		</select>
		笔数据
	</span>
</body>
</html>
login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function(){
	$("#loginForm").submit(function(){
		//在这里面做AJAX异步请求
		//设置请求地址
		//取得这个表单的请求地址,通过属性名action获取属性值
		var url = $(this).attr("action");
		//设置请求参数,这里有2个请求参数,请求参数名是name值,name="username",name="password"
		//jQuery提供了val()函数取得或设置组件的值
		var param = { //属性选择器
				username:$("input[name='username']").val(),
				password:$("#password").val()
		};
		//ajax函数,用post提交方式
		$.post(url,param,function(data){//响应完成后的回调函数,data表示接收到的响应内容
			data = eval(data);//将响应数据jsonArray转化为JSON数据格式
			if(data[0].code == 1001){//data就装了一个map,data[0]就表示map
				//登录成功后跳转,window.location.href等页面全部加载完成后跳转
				window.location.href = "${pageContext.request.contextPath}/jsp/books.jsp";
			}else if(data[0].code == 1002){
				alert(data[0].message);
			}
			
		});
		return false;//取消表单默认行为,submit默认提交行为
	});
	
});
</script>
</head>
<body>
<form method="post" id="loginForm" action="${pageContext.request.contextPath}/LoginServlet">
	用户名:<input type="text" name="username">
	密码:<input type="password" name="password" id="password">
		<input type="submit" value="登录">
		<a href="register.jsp">注册</a>
</form>
</body>
</html>
logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		session.invalidate();//让session失效
		response.sendRedirect("login.jsp");//重定向到登录页
	%>
</body>
</html>
register.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script>
<script type="text/javascript">
//验证两次输入密码必须一致 
$(function(){
	var accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
	
	//jQuery对象$("#registerForm")调submit事件,submit提交的组件,点击submit触发函数
	$("#registerForm").submit(function(){ 
		
		if(!accNameCheck){ //accNameCheck响应的信息控制表单能否提交的问题
			alert("用户名不可用"); //true才执行if,false进不来if
			return false;
		}
		
		//取得两次输入的密码
		//var pass = $("#accName").addr("value")
		//取某个标签的值不是用addr取value属性
		var pass= $("#accPass").val();
		//jQuery提供了val()函数取得或设置组件的值
		var passAgain = $("#accPassAgain").val();//取得第二次输入的密码
		var name  = $("#accName").val();
		if(name == "" || null == name ){
			alert("用户名不能为空");
			return false;//取消组件的默认行为
			//取消表单submit提交按钮的提交默认行为
		}
		if(pass == "" || null == pass){
			alert("密码不能为空");
			return false;
		}
		if(pass != passAgain){
			alert("两次输入密码不一致");
			return false;
		}
	});
	
	
	
	
	//给这个用户名一个失去焦点的事件(blur)
	$("#accName").blur(function(){
		var accName = $(this).val();
		var param = {
				accName : accName//js中对象的写法
			};
		
		var url = "${pageContext.request.contextPath}/RegisterCheckServlet";
		$.get(url,param,function(data){//参数3响应完成后的回调函数,data表示接收到的响应内容
			if(data == "true" || data == true){
				$("#checkMessage").html("<font style = 'color:green'>用户名可用</font>");
				accNameCheck = true;//accNameCheck响应的信息控制表单能否提交的问题
			}else{
				$("#checkMessage").html("<font style = 'color:red'>用户名不可用</font>");
				accNameCheck = false;//accNameCheck响应的信息控制表单能否提交的问题
			}
		
		});
		
	});
});  
</script>
</head>
<body>   <!-- 注册jsp提交到注册Servlet -->
<form id="registerForm" action="${pageContext.request.contextPath}/RegisterServlet" 
		enctype="multipart/form-data" method="post">
		用户名:<input type="text" name="accName" id="accName"><span id = "checkMessage"></span>
		<br>
		密码 : <input type="password" name="accPass" id="accPass">
		<br>
		再次输入密码 : <input type="password" name="accPassAgain" id="accPassAgain">
		<br>
		头像 : <input type="file" name="accPic">
		<br>
		<input type="submit" value="注册">
	</form>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值