Servlet學習筆記 :網頁應用Blog的迭代
阿新 • • 發佈:2018-12-10
簡介:跟隨林信良老師的《JSP&Servlet學習筆記》,迭代自己的網頁應用Blog。
一、概括
1 - 功能類
- 登入 :已有賬戶,登入成功顯示歷史動態。
- 註冊 :沒有賬戶,組冊成功顯示歡迎介面。
- 釋出 :登入成功,新增動態資訊。
- 刪除 :登入成功,刪除動態資訊。
- 登出 :離開應用,取消會話狀態。
2-輔助類
- 服務中心 :所有功能的抽象模型,在整個應用週期提供服務。
- 監聽器 :應用初始化時,例項化‘服務中心’至應用上下文(ServletContext)。
- 過濾器 :攔截未登入使用者的登入性功能操作。
3 - 頁面
- 登入頁面 :使用者的登入視窗。
- 註冊頁面 :使用者的註冊視窗。
- 顯示頁面 :進行動態資訊的展示。
- 錯誤頁面 :當輸入錯誤的賬號資訊。
二、Blog-Sheep(初次迭代)
1 - 登陸頁面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>BeerForm</title>
<meta http-equiv="Content-Type" content="text/html;chartset=UTF-8">
</head>
<body >
<form method="post" action="login.do">
<table>
<tr>
<td>Username : </td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password : </td >
<td><input type="text" name="password"></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Login">
</td>
</tr>
</table>
<a href="view/register.html"><h6>Register</h6></a>
</form>
</body>
</html>
2 - 註冊頁面
<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=UTF-8'>
<title>Register</title>
</head>
<body>
<form method="post" action="/Blog/register.do">
<table>
<tr>
<td>Username : </td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password : </td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td>Email : </td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Register">
</td>
</tr>
</table>
<a href="/Blog/index.html"><h6>Login</h6></a>
</form>
</body>
</html>
3、DD
<?xml version="1.0" encoding="UTF-8"?>
<web-app version ="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>USERS</param-name>
<param-value>/Users/apple/Documents/RayDB/users</param-value>
</context-param>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
<default-content-type>text/html</default-content-type>
</jsp-property-group>
</jsp-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
4 - 登陸類
package com.ray.notebook.init;
import com.ray.notebook.utils.UserService;
import java.io.IOException;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
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;
@SuppressWarnings("serial")
@WebServlet("/login.do")
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
UserService service = (UserService)getServletContext().getAttribute("service");
List<String> errors = new ArrayList<String>();
//Check user input
if(username.length() == 0)
errors.add("Please make sure Username no empty!");
if(password.length() == 0)
errors.add("Please make sure Password no empty!");
//Check whether user existed
if(errors.isEmpty()){
try{
if(!service.isInvalidUsername(username))
errors.add("Username does not exist.");
if(!service.checkLogin(username, password))
errors.add("Password is not right.");
}catch(IOException e){
errors.add("Server is busy, try it again." + e);
}
}
//Dispatch the result
if(errors.isEmpty()){
Map<Date, String> messages = new TreeMap<>();
try{
messages = service.readMessage(username);
}catch(IOException e){
messages.put(new Date(), "Server is busy, refesh to try again." + e);
}
//Create session for user who registered success
HttpSession session = request.getSession();
session.setAttribute("login", username);
session.setAttribute("messages", messages);
request.getRequestDispatcher("/view/Success.jsp").forward(request, response);
}else{
request.setAttribute("errors", errors);
request.getRequestDispatcher("/view/Error.jsp").forward(request, response);
}
}
}
5 - 註冊類
/*
* Servlet
* 1.Handle register.do
* 2.Create userhome to store user,s data
*/
package com.ray.notebook.init;
import com.ray.notebook.utils.UserService;
import java.io.IOException;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
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;
@SuppressWarnings("serial")
@WebServlet("/register.do")
public class Register extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
UserService service = (UserService)getServletContext().getAttribute("service");
List<String> errors = new ArrayList<String>();
//Check user input
if(username.length() == 0)
errors.add("Please make sure Username no empty!");
if(password.length() == 0)
errors.add("Please make sure Password no empty!");
if(email.length() == 0)
errors.add("Please make sure Email no empty!");
if(service.isInvalidUsername(username))
errors.add("Username has existed, try another one.");
//Try to create user data
if(errors.isEmpty()){
try{
service.createUserData(username, password, email);
service.addMessage(username, "Welcome to Blog.com !");
}catch(IOException e){
errors.add("Server is busy, try it again." + e);
}
}
//Dispatch the result
if(errors.isEmpty()){
Map<Date, String> messages = new TreeMap<>();
try{
messages = service.readMessage(username);
}catch(IOException e){
messages.put(new Date(), "Server is busy, refesh to try again." + e);
}
//Create session for user who registered success
HttpSession session = request.getSession();
session.setAttribute("login", username);
session.setAttribute("messages", messages);
request.getRequestDispatcher("/view/Success.jsp").forward(request, response);
}else{
request.setAttribute("errors", errors);
request.getRequestDispatcher("/view/Error.jsp").forward(request, response);
}
}
}
6 - 使用者服務中心
package com.ray.notebook.utils;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.lang.NullPointerException;
public class UserService{
/* Directory name where stores users' date */
private String USERS;
/* Constructing with a designated directory name */
public UserService(String USERS){
this.USERS = USERS;
}
/* Constructing with default directory name */
public UserService(){}
{
if(USERS == null)
USERS = "/Users/apple/Documents/RayDB/users";
}
/* Whether the user,s data has been created */
public boolean isInvalidUsername(String username){
try{
for(String file : new File(USERS).list())
if(file.equals(username))
return true;
}catch(NullPointerException e){
return true;
}
return false;
}
/* Creating userhome(a directory) to store data */
public void createUserData(String username, String password, String email) throws IOException{
File userhome = new File(USERS + "/" + username);
userhome.mkdir();
BufferedWriter writer = new BufferedWriter(new FileWriter(userhome + "/profile"));
writer.write(email + "\t" + password);
writer.close();
}
/* Checking whether the user is valid */
public boolean checkLogin(String username, String password) throws IOException{
if(username != null && password != null){
for(String userhome : new File(USERS).list()){
if(userhome.equals(username)){
BufferedReader reader = new BufferedReader(
new FileReader(USERS + "/" + userhome + "/profile"));
String pw = reader.readLine().split("\t")[1];
reader.close();
if(pw.equals(password))
return true;
}
}
}
return false;
}
/* Add message into userhome */
public void addMessage(String username, String data) throws IOException{
String file = USERS + "/" + username + "/" + new Date().getTime() + ".txt";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file), "UTF-8"));
writer.write(data);
writer.close();
}
/* Filter : .txt file only */
private class TxtFileFilter implements FilenameFilter{
public boolean accept(File file, String name){
return name.endsWith(".txt");
}
}
/* Comparator : sort java.util.Date by ascending order */
private class DateComparaor implements Comparator<Date>{
public int compare(Date a, Date b){
return -a.compareTo(b);
}
}
/* Return a map which includes all data uder fixed userhome
*
* Using : file filter which passes .txt only
*
* Using : date comparator which sorts dates by ascending order
*
*/
private TxtFileFilter filter = new TxtFileFilter();
private DateComparaor comparator = new DateComparaor();
public Map<Date, String> readMessage(String username) throws IOException
{
File border = new File(USERS + "/" + username);
String[] txts = border.list(filter);
Map<Date, String> messages = new TreeMap<Date, String>(comparator);
for(String txt : txts){
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(USERS + "/" + username + "/" + txt), "UTF-8"));
String text = null;
StringBuilder builder = new StringBuilder();
while((text = reader.readLine()) != null){
builder.append(text);
}
Date date = new Date(
Long.parseLong(txt.substring(0, txt.indexOf(".txt"))));
messages.put(date, builder.toString());
reader.close();
}
return messages;
}
/* Deleting message in the userhome */
public void deleteMessage(String username, String message){
File file = new File(USERS + "/" + username + "/" + message + ".txt");
if(file.exists())
file.delete();
}
}
7 - 監聽器
/*
* When servlet context was initailized :
* 1.Accessing param USERS(database) from web.xml;
* 2.Instantiation class UserService;
* 3.Setting this instance as an attribute into servlet context.
*/
package com.ray.notebook.listeners;
import com.ray.notebook.utils.UserService;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class DataBaseSCL implements ServletContextListener{
public void contextInitialized(ServletContextEvent event){
ServletContext context = event.getServletContext();
String dataBase = context.getInitParameter("USERS");
context.setAttribute("service", new UserService(dataBase));
}
public void contextDestroyed(ServletContextEvent event){}
}
8 - 過濾器
package com.ray.notebook.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
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;
@WebFilter("/secure/*")
public class UserFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException{
HttpServletRequest req = (HttpServletRequest) request;
if(req.getSession().getAttribute("login") != null){
chain.doFilter(request, response);
}else{
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendRedirect("/Blog/index.html");
}
}
public void destroy(){}
}
9 - 新增動態
package com.ray.notebook.secure;
import com.ray.notebook.utils.UserService;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
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;
@WebServlet("/secure/add.do")
public class AddBlog extends HttpServlet{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{
request.setCharacterEncoding("UTF-8");
HttpSession session = request.getSession();
String username = (String)session.getAttribute("login");
//Try to add blog into userhome
UserService service = (UserService) getServletContext().getAttribute("service");
String blog = request.getParameter("blog");
if(blog.length() != 0)
service.addMessage(username, blog);
//Return messages to user
Map<Date, String> messages = new TreeMap<>();
messages = service.readMessage(username);
session.setAttribute("messages", messages);
request.getRequestDispatcher("/view/Success.jsp").forward(request, response);
}
}
10 - 刪除動態
11 - 登出
package com.ray.notebook.secure;
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;
@WebServlet("/secure/logout.do")
public class LogOut extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{
HttpSession session = request.getSession();
session.invalidate();
response.sendRedirect("/Blog/index.html");
}
}
12 - 動態頁面
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=UTF-8'>
<title>Success</title>
</head>
<body>
Hello,${sessionScope.login}:<br>
<form method="post" action="/Blog/secure/add.do">
<textarea clos="60" rows="4" name="blog"></textarea>
<br><button type="submit">Submit</button>
</form>
<br><h3>History Message:</h3>
<c:forEach var="entry" items="${sessionScope.messages}">
<br>${entry.value}
<br><fmt:formatDate value="${entry.key}" type="both" dateStyle="full" timeStyle="full"/>
<br><a href="/Blog/secure/delete.do?blog=${entry.key.time}">Delete</a>
</c:forEach>
<br><a href="/Blog/secure/logout.do">Logout</a>
</body>
</html>
13 - 錯誤頁面
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=UTF-8'>
<title>Error</title>
</head>
<body>
<c:forEach var="error" items="${errors}">
<li>${error}</li>
</c:forEach>
<a href="view/register.html"><h6>Register</h6></a>
</body>
</html>
14 - JAR包支援
三、Blog-Snake(二次迭代)
- 初次迭代時,所有的資訊以單獨的字串形式出現。
- 二次迭代時,對使用者的資訊進行封裝。
- 使用者的註冊資訊封裝成使用者類(使用者名稱、密碼、郵箱)。
- 動態資訊封裝成動態類(使用者名稱、日期、內容)。
- 利用資訊封裝類對UserService類進行重構。
- 優點是資訊的傳遞更清晰,方法引數更簡單。
- 缺點是原來有些方法只需要傳遞單個字串,現在卻必須傳遞整個物件。
- 可以採用方法過載,避免原來使用UserService類的程式碼修改。
- 筆者是初學者,重寫了所有類。
1 - 將每個使用者的註冊資訊封裝成類
package com.ray.notebook.utils;
public class User{
private String username;
private String password;
private String email;
public User(){}
public User(String username, String password, String email){
this.username = username;
this.password = password;
this.email = email;
}
public void setUsername(String username){
this.username = username;
}
public String getUsername(){
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword(){
return password;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return email;
}
}
2 - 將每條動態封裝成類
package com.ray.notebook.utils;
import java.util.Date;
public class Blog{
private String username;
private Date date;
private String text;
public Blog(){}
public Blog(String username, Date date, String text){
this.username = username;
this.date = date;
this.text = text;
}
public void setUsername(String username){
this. username = username;
}
public String getUsername(){
return username;
}
public void setDate(Date date){
this. date = date;
}
public Date getDate(){
return date;
}
public void setText(String text){
this. text = text;
}
public String getText(){
return text;
}
}
3 - 重構使用者中心
package com.ray.notebook.utils;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
//import java.util.Map;
//import java.util.TreeMap;
import java.util.List;
import java.util.ArrayList;
import java.lang.NullPointerException;
public class UserService{
/* Directory name where stores users' date */
private String USERS;
/* Constructing with a designated directory name */
public UserService(String USERS){
this.USERS = USERS;
}
/* Constructing with default directory name */
public UserService(){}
{
if(USERS == null)
USERS = "/Users/apple/Documents/RayDB";
}
/* Whether the user,s data has been created */
// public boolean isInvalidUsername(String username){
// try{
// for(String file : new File(USERS).list())
// if(file.equals(username))
// return true;
// }catch(NullPointerException e){
// return true;
// }
// return false;
// }
/* Refractoring : Using user class as a whole */
public boolean isInvalidUsername(User user){
try{
for(String file : new File(USERS).list()){
if(file.equals(user.getUsername()))
return true;
}
}catch(NullPointerException e){
return true;
}
return false;
}
/* Creating userhome(a directory) to store data */
// public void createUserData(String username, String password, String email) throws IOException{
// File userhome = new File(USERS + "/" + username);
// userhome.mkdir();
// BufferedWriter writer = new BufferedWriter(new FileWriter(userhome + "/profile"));
// writer.write(email + "\t" + password);
// writer.close();
// }
/* Refractoring : Using user class as a whole */
public void createUserData(User user) throws IOException{
File userhome = new File(USERS + "/" + user.getUsername());
userhome.mkdir();
BufferedWriter writer = new BufferedWriter(new FileWriter(userhome + "/profile"));
writer.write(user.getEmail() + "\t" + user.getPassword());
writer.close();
}
/* Checking whether the user is valid */
// public boolean checkLogin(String username, String password) throws IOException{
// if(username != null && password != null){
// for(String userhome : new File(USERS).list()){
// if(userhome.equals(username)){
// BufferedReader reader = new BufferedReader(
// new FileReader(USERS + "/" + userhome + "/profile"));
// String pw = reader.readLine().split("\t")[1];
// reader.close();
// if(pw.equals(password))
// return true;
// }
// }
// }