实践
2.1 需求及用例
创建一个简单的计算器, 当用户输入整数时, 输出其平方值. 但用户需要登录才能进行操作, 用户的登录信息放在web.xml中, 每次登录用户可以使用该计算器三次, 三次使用结束后, 提示用户推出后重新登录继续使用.
|
User Case 用例 |
登录系统 |
||
|
Brief description |
登录系统 |
||
|
Scope/Level |
AthenaES/User goal |
Primary actor/role |
Root |
|
Minimal & Success Guarantees 保证 |
Minimal: The system logs how far it may get |
||
|
Preconditions 前提 |
无 |
||
|
Triggers 引发条件 |
用户打开登录界面 |
||
|
Main Success Scenario 成功场景 |
1. 系统提示用户输入用户名及密码 |
||
|
Extension 扩展 #1 |
3a: 系统无法核实用户身份, 提示其用户名或密码错误, 并提示用户重新输入 |
||
|
Notes and Issues |
无 |
|
User Case 用例 |
计算平方 |
||
|
Brief description |
计算平方 |
||
|
Scope/Level |
AthenaES/User goal |
Primary actor/role |
Root |
|
Minimal & Success Guarantees 保证 |
Minimal: The system logs how far it may get |
||
|
Preconditions 前提 |
Actor is logged in |
||
|
Triggers 引发条件 |
用户点击”计算” |
||
|
Main Success Scenario 成功场景 |
1. 确认用户使用次数未达到上限 |
||
|
Extension 扩展 #1 |
1a: 用户使用次数达到上限, 系统提示用户重新登陆后继续使用 |
||
|
Extension 扩展 #2 |
4a: 系统检测到用户输入不合法, 系统提示用户重新输入 用户重新进行2~4 |
||
|
Notes and Issues |
无 |
2. 2 数据分析:
1. ServltContext层次的数据: 由于用户名及最大限制次数等信息在整个Servlet进程中都会被使用, 因此使用Context的Listener来实现.
2. Session层次的数据: 用户本次登录已使用次数应记录在Seesion中, 在当前Session中使用
3. Request层次的数据: 用户输入的数值尽在当前Request中使用
2. 3 具体实现
|
Calc主页面实现: |
|
首先检查Session是否存在, 不存在则跳转到登录界面. |
package com.insprise.servletStu;
//省略import
public class Calc extends HttpServlet {
public static final String MAX_CALCULATIONAS_PER_SESSION = “maxNumber”; // 最大使用次数的Key
public static int MAX_CALCULATION_TIMES_PER_SESSION; // 最大使用次数
public static final String CURRENT_USER = “currentUser”; // 当前用户
public static final String URL_MAIN = “./Calc”; // 主页面
public static final String URL_LOGIN = “./Login”; // 登录页面
public static final String URL_LOGOUT = “./Logout”; // 注销页面
private static final String ACCESS_COUNT = “accessCount”; // 使用次数
private static final String INPUT_INT = “inputInt”;
private static Logger log = Logger.getLogger(Calc.class);
private static final int MAX_INT = 46340; // Math.sqrt(Integer.MAX_VALUE)
private HttpSession session;
private Integer accessCount; // 使用次数
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
session = request.getSession(false);
if (validatUser(session)) { // 已登录
accessCount = (Integer) session.getAttribute(ACCESS_COUNT);
if (accessCount == null) { // 如果Session中不存在accessCount, 则表明其为新登录用户,
// 赋值为0;
accessCount = 0;
session.setAttribute(ACCESS_COUNT, accessCount);
}
if (checkUseTimes(accessCount)) { // 已登录, 且使用次数在限制之内, 进行操作.
proccessRequet(request, response);
} else { // 已登录, 但使用次数操过限制,提示用户重新登陆.
accessOverTime(request, response);
}
} else { // 未登录
response.sendRedirect(URL_LOGIN);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
doGet(request, response);
}
// 检查用户是否已登录
private boolean validatUser(HttpSession s) {
if (session != null) {
return true;
}
return false;
}
// 检查用户使用次数是否超过限制
private boolean checkUseTimes(Integer number) {
//省略
}
// 使用次数超过限制之后 提示其登录;
private void accessOverTime(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().invalidate();
response.getWriter().println("本次登录已使用完毕, 请重新登录");
return;
}
// 获得输入数值, 计算结果, 返回信息
private void proccessRequet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Integer i;
String title = "求整数平方";
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
// 不使用缓存 在点击推出后 按后退按钮时 不会出现缓存中的内容.
response.setHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
PrintWriter out = response.getWriter();
out.println(ServletUtilities.headwithTitle(title));
out.println("
" + title + "
");
out.println("
当前用户: " + session.getAttribute(CURRENT_USER) + " [退出]
");
String numberString = request.getParameter(INPUT_INT);
if (numberString != null) {
try {
out.println("
" + i + " 的平方是: " + calculator(i) + "
");
log.info("累计第[" + accessCount + "]次使用, 本次计算的参数为: " + i);
} catch (Exception e) {
out.println("您可能输入的不是整数 或您输入的整数绝对值过大
请输入: 一个绝对值小于" + MAX_INT + " 的整数
");
}
}
out.println("
您总共可以使用 " + MAX_CALCULATION_TIMES_PER_SESSION + "次, 您已累计使用:" + accessCount + "次");
// 最后一次运行时, 停止输出Form;
if (accessCount.equals(MAX_CALCULATION_TIMES_PER_SESSION)) {
out.println("已达到最大使用次数限制, 请退出后重新登陆");
return;
}
printForm(out);
out.println("
");
}
// 计算
private int calculator(int i) {
accessCount = new Integer(accessCount.intValue() + 1); // 使用次数增加一次
session.setAttribute("accessCount", accessCount);
return i * i;
}
// 打印一个Form
private void printForm(PrintWriter out) {
out.print("



