登錄功能
創建Servlet
在名爲servlet的package下創建一個名爲LoginServlet的類。
public class LoginServlet extends HttpServlet{
private static final long serialVersionUID = -5870852067427524781L;
public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException{
doPost(req,res);
}
public void doPost(HttpServletRequest req,HttpServletResponse res) throws IOException{
res.getWriter().write("hello");
}
web.xml配置
建立了Servlet之後,我們需要建立Servlet到訪問路徑上的配置,在web.xml中添加以下代碼。
<servlet>
<description>登錄驗證</description>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.ischoolbar.programmer.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
在doPost方法中我們給請求一個迴應。
運行程序,F12打開調試窗口,點擊xhr,再在窗口中點擊登錄,我們可以看見服務器給的迴應信息hello
,瀏覽器已經接受到了。
在上面的基礎上做修改,loginServlet中的代碼如下所示。
public class LoginServlet extends HttpServlet{
private static final long serialVersionUID = -5870852067427524781L;
public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException{
doPost(req,res);
}
public void doPost(HttpServletRequest req,HttpServletResponse res) throws IOException{
String vcode = req.getParameter("vcode");
String loginCpacha = req.getSession().getAttribute("loginCapcha").toString();
if(StringUtil.isEmpty(vcode)){
res.getWriter().write("vcodeError");
return;
}
if(!vcode.toUpperCase().equals(loginCpacha.toUpperCase())){
res.getWriter().write("vcodeError");
return;
}
}
這裏我們是通過login.jsp的登錄按鈕來實現驗證碼的驗證的。String vcode = req.getParameter("vcode");
是用於獲取form表單中驗證碼輸入框中輸入的數據,從下面的html代碼中可以看見這個input標籤
的name是定義爲vcode
的。
<div class="row cl">
<div class="formControls col-8 col-offset-3">
<input class="input-text size-L" name="vcode" type="text" placeholder="請輸入驗證碼" style="width: 200px;">
<img title="點擊圖片切換驗證碼" id="vcodeImg" src="CpachaServlet?method=loginCapcha">
</div>
</div>
String loginCpacha = req.getSession().getAttribute("loginCapcha").toString();
是一句是用於獲取session中所生成的驗證碼的代碼,是用於與用戶輸入進行匹配。
那麼這個是通過什麼方式來保存到session中的呢?
我們可以看見在CpachaServlet這個Servlet中有這樣一句代碼:req.getSession().setAttribute("loginCapcha", generatorVCode);
request.getSession().setAttribute()
可以通過sessionID得到自己的session,將參數存儲在session中,即使重定向客戶端也沒事,這個值可以在多個頁面上使用。
正是因爲生成驗證碼時,將驗證碼存入到了Session中,所以我們在後面是可以直接獲取到並拿出來用的。
數據庫的連接
數據庫也會在很多的地方使用,所以要建立一個專門管理數據庫的工具包DBUtil,以便於提高代碼的複用率。
public class DBUtil {
private String dbUrl = "jdbc:mysql://localhost:3306/db_student_manager_web?useUnicode=true&characterEncoding=utf8";
private String dbUser = "root";
private String dbPassword = "root";
private String jdbcName = "com.mysql.jdbc.Driver";
private Connection connection = null;
// 獲取數據庫連接
public Connection getConnection(){
try {
Class.forName(jdbcName);
connection = DriverManager.getConnection(dbUrl,dbUser,dbPassword);
System.out.println("數據庫連接成功!");
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("數據庫連接失敗!");
e.printStackTrace();
}
return connection;
}
// 關閉數據庫連接
public void closeCon(){
if(connection != null){
try {
connection.close();
System.out.println("數據庫連接關閉!");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
封裝數據庫基本操作
public class BaseDao {
private DBUtil dbUtil = new DBUtil();
// 關閉數據庫,釋放資源
public void closeCon(){
dbUtil.closeCon();
}
// 基礎查詢,多條查詢
public ResultSet query(String sql){
try {
PreparedStatement prepareStatement = dbUtil.getConnection().prepareStatement(sql);
return prepareStatement.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
做好上面的準備之後,我們就需要對應着數據表來建立model,一張數據表對應着一個model。爲了實現對管理員的登錄,我們先創建Admin.java,對應的數據表中也包含四個字段,分別是id,name,password,status。
public class Admin {
private int id;
private String name;
private String password;
private int status = 1;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
接下來,就可以實現關於管理員數據庫操作的封裝了,我們實現的是登錄功能,就需要讀取數據庫的信息再與前端的數據進行匹配。
在這裏我們做的是先創建了一個Admin的對象,將前端傳來的數據作爲查詢條件拼接在sql語句中,經過查詢就返回了一個結果集對象,我們對結果集中的數據獲取到並且根據Admin的set方法將這些屬性值獲取到,最終返回給Servlet。
public class AdminDao extends BaseDao {
public Admin login(String name,String password){
String sql = "select * from s_admin where name = '"+ name +"'and password = '" + password +"'";
ResultSet resultSet = query(sql);
try {
if(resultSet.next()){
Admin admin = new Admin();
admin.setId(resultSet.getInt("id"));
admin.setName(resultSet.getString("name"));
admin.setPassword(resultSet.getString("password"));
admin.setStatus(resultSet.getInt("status"));
return admin;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
因爲servlet是處理處理業務邏輯的層,所以我們在這一層獲取到了前端的數據以及從數據庫中獲取的數據。
我們先來看看前端關於填寫用戶名等信息的表單是如何定義的,這裏只貼出來了相關的代碼:
<input id="" name="account" type="text" placeholder="賬戶" class="input-text size-L">
<input id="" name="password" type="password" placeholder="密碼" class="input-text size-L">
<input class="input-text size-L" name="vcode" type="text" placeholder="請輸入驗證碼" style="width: 200px;">
<div class="radio-box">
<input type="radio" id="radio-2" name="type" checked value="2" />
<label for="radio-1">學生</label>
</div>
<div class="radio-box">
<input type="radio" id="radio-3" name="type" value="3" />
<label for="radio-2">老師</label>
</div>
<div class="radio-box">
<input type="radio" id="radio-1" name="type" value="1" />
<label for="radio-3">管理員</label>
</div>
上面我們需要的是name屬性,因爲通過name的值我們可以獲取到文本框中輸入的值,將獲得的值傳入到Dao進行查詢,如果沒有查詢到就返回一個信息“LoginError”給瀏覽器,否則就登錄成功。
因爲登錄成功後需要一直用這個用戶的身份進行操作,所以就要將這個用戶的用戶類型,賬戶存在Session中。
public class LoginServlet extends HttpServlet{
private static final long serialVersionUID = -5870852067427524781L;
public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException{
doPost(req,res);
}
public void doPost(HttpServletRequest req,HttpServletResponse res) throws IOException{
String vcode = req.getParameter("vcode");
String name = req.getParameter("account");
String password = req.getParameter("password");
int type = Integer.parseInt(req.getParameter("type"));
String loginCpacha = req.getSession().getAttribute("loginCapcha").toString();
if(StringUtil.isEmpty(vcode)){
res.getWriter().write("vcodeError");
return;
}
if(!vcode.toUpperCase().equals(loginCpacha.toUpperCase())){
res.getWriter().write("vcodeError");
return;
}
// 驗證碼驗證通過,對比用戶名密碼是否爭取
switch(type){
case 1:{
AdminDao adminDao = new AdminDao();
Admin admin = adminDao.login(name, password);
adminDao.closeCon();
if(admin == null){
res.getWriter().write("LoginError");
return;
}
HttpSession session = req.getSession();
session.setAttribute("user", admin);
session.setAttribute("userType", type);
res.getWriter().write("admin");
break;
}
default:
break;
}
// 說明用戶名密碼正確
}
}
res.getWriter().write("admin");
:這句代碼是便於登錄之後,實現將要跳轉到什麼頁面的功能。
我們看一下jsp中的代碼:
success: function(msg){
if("vcodeError" == msg){
....
} else if("loginError" == msg){
....
} else if("admin" == msg){
window.location.href = "SystemServlet?method=toAdminView";
} else if("student" == msg){
window.location.href = "SystemServlet?method=toStudentView";
} else if("teacher" == msg){
window.location.href = "SystemServlet?method=toTeacherView";
}
}
所以當我們匹配登錄信息之後,可以給瀏覽器一條消息,那麼瀏覽器就可以根據這個消息跳轉到管理員登錄成功之後應該去的頁面。