手记

JSP+Servlet培训班作业管理系统[1]

按照猫哥的一般习惯,做一个项目的顺序如下:

1,先搞定数据库
2,搞定Java Web项目基本结构,包括数据库相关操作类
3,开发Java Web各项功能
4,优化、改进

这个顺序呢,不直观,而且容易使人厌倦,非常无聊,是故,抛弃之。这次猫哥从看的见摸得着的网页出发,然后网页需要后台提供啥功能,就搞啥。最后后台需要数据库啥样,就弄啥样,用这样一个顺序实现培训班管理系统。为了方便记忆和理解,猫哥将内容分节,节名统一用从task:X-Y开始,X表示任务名称,Y表示任务步骤

task:1-1,作为一个系统,首先就得提供登录功能。设计一个最简单的登录页面如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>   
    <title>login.jsp</title>
  </head>
  <body>
    <form id="mainForm" method="post" action="/HomeworkSystem/LoginServlet">
        请输入用户名:<input type="text" name="userName" />
        <br/>
        请输入密码:<input type="password" name="userPassword"/>  
        <br/>
        <input type="submit" value="登录"/>
    </form>
  </body>
</html>
task:1-1注意点
1,文件为:WebRoot/login.jsp
2,注意编码保持utf-8
3,点击【登录】按钮后,表单内容被提交给/LoginServlet

task:1-2,我们来编辑LoginServlet处理登录页面提交的登录请求吧。(猫哥使用的MyEclipse菜单新建的LoginServlet,自动生成了web.xml文件代码和LoginServlet类及方法,猫哥为了演示更加清晰,将演示必要代码)。

<?xml version="1.0" encoding="UTF-8"?><!-- web.xml文件内容 -->
<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">
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/LoginServlet</url-pattern>
  </servlet-mapping>
</web-app>
package servlet;//在servlet包下
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class LoginServlet extends HttpServlet {//用于处理登录请求的LoginServlet
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doPost(request, response);//直接调用doPost方法处理get请求
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {//处理post请求
        //设置输入输出格式、编码
        response.setContentType("text/html");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //获取用户在网页输入的用户名和密码
        String userName=request.getParameter("userName");
        String userPassword=request.getParameter("userPassword");
    }
}

task:1-3,现在,用户的登录请求抛给了我们的Servlet处理,此时的逻辑应该如下设计:

1,如果用户名或密码为空,提示用户输入。
2,如果用户名或密码错误,提示用户重新输入(注意此处用户名不存在也认为是输入错了即可)。
3,如果用户名和密码都正确,跳转到相应用户页面。
4,因为存在校长、教师、学生三种不同的角色,不同角色登录后页面显示内容不同(校长可以新增教师、学生,教师可以新增课程,学生可以提交作业,功能不同)。

根据以上讨论,我们至少知道我们需要用户的信息有:用户名,密码,角色,另外为了避免用户名重复,我们需要一个唯一标识id(就像QQ上网名可以重复,但是QQ号是唯一的)。此处我们先不管数据库(差不多什么样心里也有数了吧),先把用户这个实体类设计出来。

package entity;//在entity包下,注意了
public class User {
    private int userId;
    private String userName;
    private String userPassword;
    private String userRole;
        //以后省略无聊的get set方法,自行补足
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserPassword() {
        return userPassword;
    }
    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }
    public String getUserRole() {
        return userRole;
    }
    public void setUserRole(String userRole) {
        this.userRole = userRole;
    }
}

此处有一点需要注意,就是userRole这个玩意,也就是角色。如果角色确定了就三种(校长、教师、学生),且每种角色对应的功能固定,那么就直接private String userRole;对应数据库中的user_role列搞定(列值为校长、教师、学生三者之一)。如果要想系统拓展性更好,比如角色可能增加(副校长、教师又分班主任、助教..),那么可以将角色单独设计为一张表,而用户中的user_role指向角色表一条记录即可。此处我们采取这种先进理念(哈哈自吹自擂),所以实体类改为:

package entity;
public class User {
    private int userId;
    private String userName;
    private String userPassword;
    private Role userRole;  
    //自行补足get set
}
//邪恶的分界线
package entity;
public class Role {
    private int roleId;
    private String roleName;
    //自行补足get set
}

task:1-4,然后我们现在需要操作数据库了,但是猫哥想把数据库留到最后再实现(实在是大同小异没啥意思),那咋办那。好办,我们就像个八路军指挥官一样,三团上去干鬼子,至于三团怎么干鬼子,让三团长自己想办法,先把命令下去再说。我们建一个包command,用于向数据库下令,首先我们把登录相关的命令保存在LoginCommand类里面,代码如下:

package command;
public class LoginCommand {//从此处向数据库类下操作指令
}

结合task:1-3中的需求分析,我们需要向LoginCommand 这个小团长(确实官职小,在程序设计的世界里,程序员就是最牛X的大官),下达检查登录指令。这个指令描述如下:

指令:检查登录
动作:检查userName和userPassword是否正确
行动结果:失败:执行失败原因(无此人?信息错误?..)
行动结果:成功:把此人带来见我!我要根据他的能力(校长、教师、学生)给他安排工作。

这样一看,就简单了,这样设计就行:

package command;
import entity.User;
public class LoginCommand {//从此处向数据库类下操作指令
    public User checkLogin(String userName,String userPassword) throws Exception{
        if(userName.equals("")||userPassword.equals("")){
            //抛出输入信息异常
        }
        User user=null;
        try{
            //从数据库中执行查询
        }catch(Exception e){
            //抛出数据库异常
        }
        return user;
    }
}

好的,这样一看,我们后续只需要把执行用户查询的语句放在//从数据库中执行查询处,就可以了。此处还有几个异常,需要处理,我们希望能把所有的异常信息统计起来,所以定义个自定义异常类如下:

package exception;
import java.util.Date;
public class MyException extends Exception{
    private Date time;//记录异常发生时间
    private String message;//原始异常信息,给程序员看,记录日志
    private String info;//自定义信息,给用户看
    public MyException(){
        super();
    }
    public MyException(Date time,String msg,String info){
        super();
        this.time=time;
        this.message=msg;
        this.info=info;
    }
    public Date getTime() {
        return time;
    }
    public void setTime(Date time) {
        this.time = time;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

好的,有了这个自定义异常类,我们的指令类可以修改为:

package command;
import java.util.Date;
import entity.User;
import exception.MyException;
public class LoginCommand {//从此处向数据库类下操作指令
    public User checkLogin(String userName,String userPassword) throws MyException{
        if(userName.equals("")||userPassword.equals("")){
            //抛出输入信息异常
            throw new MyException(new Date(),"用户名或者密码为空","用户名或者密码为空");
        }
        User user=null;
        try{
            //从数据库中执行查询
        }catch(Exception e){
            throw new MyException(new Date(),e.getMessage(),"数据库访问异常");
        }
        return user;
    }
}

task:1-5,好的,此时,我们就可以在Servlet中调用LoginCommand 完成数据库操作了,代码如下:

package servlet;
import java.io.*;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import command.LoginCommand;
import entity.User;
import exception.MyException;
public class LoginServlet extends HttpServlet {//用于处理登录请求的LoginServlet
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doPost(request, response);//直接调用doPost方法处理get请求
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {//处理post请求
        //设置输入输出格式、编码
        response.setContentType("text/html");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //获取用户在网页输入的用户名和密码
        String userName=request.getParameter("userName");
        String userPassword=request.getParameter("userPassword");
        //数据库操作
        LoginCommand lc=new LoginCommand(); 
        User user=null;
        try {
            user=lc.checkLogin(userName, userPassword);
            if(user==null)
                throw new MyException(new Date(),"用户名或者密码错误","用户名或者密码错误");
            //根据user.getUserRole();用户角色显示不同内容
        } catch (Exception e) {
            //跳转到错误提示页面,并提示用户错误信息
        }

    }
}

task:1-6,根据用户不同角色显示不同内容,是一个比较复杂的事情,这个猫哥下一篇博客再论,我们来先来实现比较简单的跳转到错误提示页面,并提示用户错误信息

修改LoginServlet 为:

package servlet;
import java.io.*;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import command.LoginCommand;
import entity.User;
import exception.MyException;
public class LoginServlet extends HttpServlet {//用于处理登录请求的LoginServlet
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doPost(request, response);//直接调用doPost方法处理get请求
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {//处理post请求
        //设置输入输出格式、编码
        response.setContentType("text/html");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //获取用户在网页输入的用户名和密码
        String userName=request.getParameter("userName");
        String userPassword=request.getParameter("userPassword");
        //数据库操作
        LoginCommand lc=new LoginCommand(); 
        User user=null;
        try {
            user=lc.checkLogin(userName, userPassword);
            if(user==null)
                throw new MyException(new Date(),"用户名或者密码错误","用户名或者密码错误");
            //根据user.getUserRole();用户角色显示不同内容
        } catch (MyException e) {
            //跳转到错误提示页面,并提示用户错误信息
            request.setAttribute("errorInfo", e.getInfo());//设置错误信息
            request.getRequestDispatcher("/error.jsp").forward(request,response);//跳转到error.jsp
        }
    }
}

好的,最后,设计error.jsp为:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>  
    <title>error.jsp</title>
  </head>
  <body>
    错误信息:${errorInfo}<br/>
  <a href="login.jsp">点此返回登录页</a>
  </body>
</html>

重新部署、运行后,测试输入空的内容,提交后发现:错误信息:用户名或者密码为空,如果随便输如用户名密码,提交后发现:错误信息:用户名或者密码错误

最后,还有个问题,错误信息:用户名或者密码为空,这个也太生硬了把,最好改为友情提示:用户名或者密码不能为空。但是猫哥就是不改了,网站要个性!

19人推荐
随时随地看视频
慕课网APP

热门评论

条理非常清晰,像楼主这样用心写文章的人太少

在吗在吗 用eclipse可以吗  第一页代码怎么写啊

哥,有个问题啊,这里request.setAttribute("errorInfo", e.getInfo());//设置错误信息的e.getInfo()报错,咋回事啊

查看全部评论