17.1一个MVC小demo_1(我的JavaEE笔记)

说明:这是一个实现用户注册和登录的web应用,只是一个很小的demo,同时最初我们只是使用xml来代替数据库,之后才会加入数据库,主要是用来说明MVC开发模式。
(工程day09_user

一、搭建开发环境

1.1 导入相关的jar包

操作xml文档: dom4j-1.6.1.jar
操作xpath: jaxen-1.1-beta-6.jar
将数据封装到javabean中: commons-beanutils-1.9.2.jar
包含log4j日志包: commons-logging-1.2.jar
标签包:javax.servlet.jsp.jstl.jar、jstl-impl-1.2.2.jar 如果使用MyEclipse开发那么这两个包MyEclipse已经帮我加入了,无需自己加了。

1.2 创建程序开发用要的包

实体类存放包:cn.itcast.domain
dao层接口:cn.itcast.dao
dao层实现:cn.itcast.dao.impl
业务(service)层接口:cn.itcast.service
业务实现:cn.itcast.service.impl
web层业务控制:cn.itcast.web.controller
web层UI控制:cn.itcast.web.UI
工具包:cn.itcast.utils
测试包:junit.test
自定义异常包:cn.itcast.exception
表单数据包:cn.itcast.web.formbean
jsp包:WEB-INF/jsp

说明:

  • 1.包比较多,刚开始可能建的不全,我们可以在后面进行添加。
  • 2.对于web层,我们要知道,其实servlet有两种,一种是实际处理业务类的servlet,另一种是为用户提供相关的界面jsp的,因为jsp我们需要保护起来,不能让用户随便访问。所以放在了WEB-INF目录下。
  • 3.对于异常处理包,我们知道在应用中我们有时候可能需要通过异常来传递相关的异常消息,所以需要一个异常处理包。
  • 4.由于数据表单一般来说和实体类是不太一致的,所以需要专门建包存放。

二、开发实体

User.java

public class User {
    private String id;
    private String username ;
    private String password ;
    private String email ;
    private Date birthday ;
    
    ...
}

三、开发dao层工具类

XmlUtils.java

package cn.itcast.utils;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
//注意:使用dom4j操作xml文档我们可以直接去查文档,在quick start就可以查到
public class XmlUtils {
    private static String filename = "users.xml";
    
    public static Document getDocument() throws DocumentException{
        //得到资源文件的URL地址
        URL url = XmlUtils.class.getClassLoader().getResource(filename);
        //得到资源文件的真实路径
        String realpath = url.getPath();
        //操作xml文档
        SAXReader reader = new SAXReader();
        return reader.read(realpath);//工具类的异常一般抛给其调用者

    }
    
    public static void write2Xml(Document document) throws IOException{
        URL url = XmlUtils.class.getClassLoader().getResource(filename);
        String realpath = url.getPath();
        //使用格式化输出器进行输出
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter writer = new XMLWriter(new FileOutputStream(realpath), format );
        writer.write( document );
        writer.close();
    }
}

说明:这里我们由于使用的是xml存放数据,所以需要新建一个操作xml文档的工具类,在后面我们换成MySQL或其他数据库之后同样也需要这样一个工具类来获取数据库的链接等。

四、开发dao层

UserDaoXmlImpl.java

package cn.itcast.dao.impl;
import java.text.SimpleDateFormat;
import org.dom4j.Document;
import org.dom4j.Element;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.utils.XmlUtils;

public class UserDaoXmlImpl implements UserDao {
    
    //使用用户名和密码去查找,用于用户登录
    @Override
    public User find(String username , String password) {
        try {
            //这里的异常可能是资源文件读取不到,所以抛出去是没有意义的,而且不能
            //直接打印,因为我们需要让上一层知道这里出现了异常,这里最好的方式是自己定义一个异常,后面再说
            Document document = XmlUtils.getDocument();
            
            //下面使用了xpath
            Element e = (Element) document.selectSingleNode("//user[@username='"+username+"'and @password='"+password+"']");
            if(e == null){
                return null;
            }
            User user = new User();
            user.setId(e.attributeValue("id"));
            user.setUsername(e.attributeValue("username"));
            user.setPassword(e.attributeValue("password"));
            user.setEmail(e.attributeValue("email"));
            
            String birth = e.attributeValue("birthday");//这里取到的是一个日期字符串,需要转换成日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthday(sdf.parse(birth));
            
            return user;
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    
    //使用用户名去查找,用于用户注册,查看系统中此用户名是否被使用
    @Override
    public User find(String username){
        
        try {
            Document document = XmlUtils.getDocument();
            
            //下面使用了xpath
            Element e = (Element) document.selectSingleNode("//user[@username='"+username+"']");
            if(e == null){
                return null;
            }
            User user = new User();
            user.setId(e.attributeValue("id"));
            user.setUsername(e.attributeValue("username"));
            user.setPassword(e.attributeValue("password"));
            user.setEmail(e.attributeValue("email"));
            
            String birth = e.attributeValue("birthday");//这里取到的是一个日期字符串,需要转换成日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthday(sdf.parse(birth));
            
            return user;
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    //添加用户
    @Override
    public void add(User user){
        
        try {
            Document document = XmlUtils.getDocument();
            Element root = document.getRootElement();
            
            Element user_node = root.addElement("user");//创建user节点,并挂到root节点上
            //向新节点中赋值
            user_node.setAttributeValue("id", user.getId());
            user_node.setAttributeValue("username", user.getUsername());
            user_node.setAttributeValue("password", user.getPassword());
            user_node.setAttributeValue("email", user.getEmail());
            user_node.setAttributeValue("birthday", user.getBirthday().toLocaleString());
            
            XmlUtils.write2Xml(document);
            
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

说明:

  • 1.这里我们只是提供用户注册和登录,所以只有查找和添加方法。如果以后的项目中业务比较复杂可能还需要删除和修改等操作。
  • 2.时间属性一定要进行处理,这里需要将字符串转换成一个日期对象。
  • 3.在登录的时候我们需要用户的用户名和密码,而在注册的时候我们首先要查看数据库中此用户名是否已经存在,所以这里我们需要提供两个查找的方法。

测试
开发一层之后我们需要立即进行测试。
UserDaoTest.java

package junit.test;
import java.util.Date;
import org.junit.Test;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.impl.UserDaoXmlImpl;
import cn.itcast.domain.User;

public class UserDaoTest {
    
    @Test
    public void testAdd(){
        User user = new User();
        
        user.setId("2222");
        user.setUsername("bbb");
        user.setPassword("2222");
        user.setEmail("bb@sina.com");
        user.setBirthday(new Date());
        
        UserDao dao = new UserDaoXmlImpl();
        dao.add(user);
        //注意:测试通过后我们发现工程下的users.xml没有改变,其实这里改变的是classes中的那个users.xml,而不是
        //工程src下的这个文件,因为我们编译之后src下的users.xml是发布到classes目录下的,我们可以看到工程最下面
        //多了一个users.xml文件
    }
    
    @Test
    public void testFind(){
        
        UserDao dao = new UserDaoXmlImpl();
        //User user = dao.find("aaa", "123");
        User user = dao.find("aaa");
    }
}

说明:测试add方法时我们直接new一个User对象,然后设置好相关的属性值,直接调用add方法进行测试。而查找方法我们直接调用测试即可。

五、开发service层

BusinessServiceImpl.java

package cn.itcast.service.impl;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.impl.UserDaoXmlImpl;
import cn.itcast.domain.User;
import cn.itcast.exception.UserExistException;
import cn.itcast.service.BusinessService;
public class BusinessServiceImpl implements BusinessService {
    //有两个需求,一个是注册一个是登录
    
    UserDao dao = new UserDaoXmlImpl();
    
    //提供注册服务
    @Override
    public void registerUser(User user) throws UserExistException{
        if(dao.find(user.getUsername()) != null){
            //在应用开发中一般都是抛运行时异常,但是如果我们想将异常当成一个返回值来让上一层处理的话
            //那么需要抛编译时异常,比如这里的给用户一个友好提示(注册的用户已存在)。最好的做法就是自定义
            //异常,而编译时异常需要在方法上申明
            throw new UserExistException("注册的用户名已存在"); 
        }
        dao.add(user);
    }
    
    //提供登录服务
    @Override
    public User loginUser(String username , String password){
        return dao.find(username, password);
    }
    
}

说明:很明显我们可以看到在用户注册的时候如果此用户已经存在,那么我们需要向上一层提供一个信息,而在开发中一般我们使用异常向上一层提供这类信息。于是我们需要开发一个专门的异常包用来存放各类异常。最后注意抽取接口。
cn.itcast.exception/UserExistException.java

package cn.itcast.exception;

//当用户已经存在的时候抛此异常,继承Exception表示是编译时异常,如果是运行时异常则继承RuntimeException
public class UserExistException extends Exception {
    //自定义异常肯定是用来封装信息,那一般使用构造函数来封装信息,从父类继承
    public UserExistException() {
        super();
        // TODO Auto-generated constructor stub
    }

    public UserExistException(String message, Throwable cause,
            boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
        // TODO Auto-generated constructor stub
    }

    public UserExistException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

    public UserExistException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

    public UserExistException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }
    
}

说明:一定要注意程序中对异常的一些说明。异常类中的方法都是直接从父类中继承的,我们一般通过构造方法来设置异常信息。

六、web层

6.1注册

  • web层的开发中我们需要知道,为了网站的安全性,其实工程中的相关jsp文件是不能随便让用户直接访问的,于是我们将相关的jsp放在WEB-INF目录中。那如何为用户提供相关的页面呢?这里我们使用servlet为用户提供相关的jsp页面,而这类servlet不是真正处理用户业务请求的servlet,于是还有另一类servlet专门处理用户的业务请求。这里我们将前者放在cn.itcast.web.UI包中,后者放在cn.itcast.web.controller包中。

  • 而当用户注册等请求的时候需要将表单数据提交给后台进行处理,而表单数据我们是需要进行校验的,同时表单数据往往和真实实体类的属性是不太一致的,所以我们需要一个专门的包存放表单数据类。这里是cn.itcast.web.formbean

RegisterFormBean.java

package cn.itcast.web.formbean;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//表单中的数据一般都是String类型
public class RegisterFormBean {
    private String username ;//用户名不能为空,并且要是3-8为的字符
    private String password ;//密码不能为空,并且要是3-8位的数字
    private String password2 ;//两次的密码必须一致
    private String email ;//可以为空,不为空的时候必须是一个合法的邮箱
    //这里的生日必须是字符串类型,而后面我们需要校验此字符串是否是一个合法的日期
    private String birthday ;//可以为空,不为空时要是一个合法的日期
    private Map<String , String> errors = new HashMap<String, String>();//用来保存校验失败信息
    
    public boolean validate(){
        
        boolean isOk = true;
        
        if(this.username==null || this.username.trim().equals("") ){
            isOk = false;
            errors.put("username", "用户名不能为空!!");
        }else{
            if(!this.username.matches("[a-zA-Z]{3,8}")){
                isOk = false;
                errors.put("username", "用户名必须是3-8位的字母!!");
            }
        }
        
        
        if(this.password==null || this.password.trim().equals("")){
            isOk = false;
            errors.put("password", "密码不能为空!!");
        }else{
            if(!this.password.matches("\\d{3,8}")){
                isOk = false;
                errors.put("password", "密码必须是3-8位的数字!!");
            }
        }
        
        //private String password2; 两次密码要一致
        if(this.password2!=null){
            if(!this.password2.equals(this.password)){
                isOk = false;
                errors.put("password2", "两次密码不一致!!");
            }
        }
        
        //private String email;     可以为空,不为空要是一个合法的邮箱
        // flx_itcast@sina.com.cn
        if(this.email!=null){
            if(!this.email.matches("\\w+@\\w+(\\.\\w+)+")){
                isOk = false;
                errors.put("email", "邮箱不是一个合法邮箱!!");
            }
        }
        
        
        //private String birthday;  可以为空,不为空时,要是一个合法的日期
        //校验日期比较简单,如果字符串能被转换成日期就表示是合法,如果抛出
        //异常则表示非法,但是不能使用SimpleDateFormat转,这个类不太严
        //格,我们使用beanuitls中的转换器
        if(this.birthday!=null){
            try{
                DateLocaleConverter conver = new DateLocaleConverter();
                conver.convert(this.birthday);
            }catch (Exception e) {
                isOk = false;
                errors.put("birthday", "生日必须要是一个日期!!");
            }
        }
        
        return isOk;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword2() {
        return password2;
    }

    public void setPassword2(String password2) {
        this.password2 = password2;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }
    
}

说明:这里需要注意的是表单数据类中的属性一般都是字符串,不管是数字还是日期,在表单数据类中都是String类型。而表单数据类中还提供了对数据的校验工作,于是需要一个属性来封装校验信息。

注册页面(WEB-INF/JSP/register.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="${pageContext.request.contextPath }/">
    <title>register page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
      <form action="servlet/RegisterServlet" method="post">
        <table width="60%" border="1px">
            <tr>
                <td>用户名</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td>确认密码</td>
                <td><input type="password" name="password2"></td>
            </tr>
            <tr>
                <td>邮箱</td>
                <td><input type="text" name="email"></td>
            </tr>
            <tr>
                <td>生日</td>
                <td><input type="text" name="birthday"></td>
            </tr>
            <tr>
                <td><input type="reset" value="清空"></td>
                <td><input type="submit" value="注册"></td>
            </tr>
        </table>
    </form>
  </body>
</html>

提供注册页面的servlet(RegisterUIServlet.java

package cn.itcast.web.UI;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//为用户提供注册界面的servlet
public class RegisterUIServlet  extends HttpServlet{

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
    
}

处理用户业务请求的servlet(RegisterServlet.java

package cn.itcast.web.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import cn.itcast.domain.User;
import cn.itcast.exception.UserExistException;
import cn.itcast.service.BusinessService;
import cn.itcast.service.impl.BusinessServiceImpl;
import cn.itcast.utils.WebUtils;
import cn.itcast.web.formbean.RegisterFormBean;
//处理用户注册请求
public class RegisterServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //RegisterFormBean formbean = new RegisterFormBean();
        //formbean.setBirthday(request.getParameter("birthday"));
        //....太多,使用工具类
        
        RegisterFormBean formbean = WebUtils.request2Bean(request, RegisterFormBean.class);
        if(!formbean.validate()){
            //formbean中带有了校验等信息,需要设置到request中
            request.setAttribute("formbean", formbean);
            //校验失败回到首页,同时显示错误信息,需要修改注册页面
            request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(request, response);
            
        }
        //把表单数据填充到javabean中
        User user = new User();
        try {
            //注册字符串到日期的转换器
            ConvertUtils.register(new DateLocaleConverter(), Date.class);
            BeanUtils.copyProperties(user, formbean);//复制formbean数据到javabean中
            user.setId(WebUtils.makeId());
            BusinessService service = new BusinessServiceImpl();
            service.registerUser(user);
            
            request.setAttribute("message", "注册成功");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            
        } catch (UserExistException e) {
            formbean.getErrors().put("username", "注册用户已存在");
            request.setAttribute("formbean", formbean);
            request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(request, response);
            
        }catch (Exception e) {
            e.printStackTrace();//后台也需要记录
            request.setAttribute("message", "对不起,注册失败");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

说明:

  • 1.首先我们需要将formbean中的数据存放到request中去,但是一个一个设置显然太麻烦,而之后我们可能还有其他的formbean,于是这里我们需要一个工具类WebUtils
  • 2.然后我们需要需要校验数据,校验如果失败我们返回到注册界面,但是返回之后我们需要在表单中显示错误信息,同时还需要回显数据,所以需要对注册界面进行修改。
  • 3.如果校验成功,那么此时我们需要将数据复制到javabean中去,同时存到数据库中,不管成功还是失败我们都需要向用户发送一条提示信息,这里我们需要一个全局消息显示页面message.jsp
  • 4.如果用户已经存在则我们跳转到注册界面,同时在表单中显示相关信息。
  • 5.对于日期我们不能直接复制到javabean中,因为两个对象的日期类型不一致,我们要使用一个转换器,这里可能会出现异常 ,需要导入包commons-collections-3.2.1.jar,我导入高版本的不行,这个版本可以通过,同时用户id我们需要一个工具来产生,这里我们使用uuid。

工具类:WebUtils.java

package cn.itcast.utils;
import java.util.Enumeration;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.BeanUtils;
public class WebUtils {
    //将request中的数据封装到bean中,那以后我们可能不知道封装到哪个bean中,这里使用泛型
    public static <T> T request2Bean(HttpServletRequest request, Class<T> clazz ){
        try{
            T bean = clazz.newInstance();
            Enumeration e = request.getParameterNames();//拿到所有请求参数的名称
            while(e.hasMoreElements()){
                String name = (String) e.nextElement();
                String value = request.getParameter(name);
                BeanUtils.setProperty(bean, name, value);//将属性值封装到bean中
            }
            return bean;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
    public static  String makeId(){
        //id使用uuid,唯一的id号
        return UUID.randomUUID().toString();
        
    }
}

修改后的注册页面:(register.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>register page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
      <form action="${pageContext.request.contextPath }/servlet/RegisterServlet" method="post">
        <table width="60%" border="1px">
            <tr>
                <td>用户名</td>
                <td><input type="text" name="username" value="${formbean.username }">${formbean.errors.username }
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password" value="${formbean.password }">${formbean.errors.password }</td>
            </tr>
            <tr>
                <td>确认密码</td>
                <td><input type="password" name="password2" value="${formbean.password2 }">${formbean.errors.password2 }</td>
            </tr>
            <tr>
                <td>邮箱</td>
                <td><input type="text" name="email" value="${formbean.email }">${formbean.errors.email }</td>
            </tr>
            <tr>
                <td>生日</td>
                <td><input type="text" name="birthday" value="${formbean.birthday }">${formbean.errors.birthday }</td>
            </tr>
            <tr>
                <td><input type="reset" value="清空"></td>
                <td><input type="submit" value="注册"></td>
            </tr>
        </table>
    </form>
  </body>
</html>

全局消息显示页面:(webRoot/message.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>全局消息显示页面</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
    ${message }
  </body>
</html>

6.2登录

首先当然还是需要一个servlet为用户提供一个登录界面
LoginUIServlet.java

package cn.itcast.web.UI;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//为用户提供登录界面
public class LoginUIServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

注册界面(login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>用户登录</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  
  <body>
    <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
  </body>
</html>

处理用户登录业务请求的servlet
LoginServlet.java

package cn.itcast.web.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.domain.User;
import cn.itcast.service.BusinessService;
import cn.itcast.service.impl.BusinessServiceImpl;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        BusinessService service = new BusinessServiceImpl();
        User user = service.loginUser(username, password);
        if(user == null){
            request.setAttribute("message", "用户名或密码有误");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return ;
        }
        request.getSession().setAttribute("user", user);
        request.setAttribute("message", "恭喜您:" + user.getUsername() + "登录成功,本页面将在5秒钟后跳到首页"
                + "<meta http-equiv='refresh' content='5;url=/day09_user/index.jsp'");
        request.getRequestDispatcher("/message.jsp").forward(request, response);
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

说明:当用户登录成功了我们先跳到全局消息显示页面,同时我们还向用户发送了一个头,让用户登录成功之后在全局消息显示页面上停留5秒钟之后跳转到首页上,这里本来不应该将地址写死的。用户登录成功之后一定记得在session中存入用户数据。

首页(index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>首页</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <script type="text/javascript">
        function doLogout(){
            window.location.href="${pageContext.request.contextPath}/servlet/LogoutServlet";
        }
    </script>
  </head>
  
  <body>
    <h1>xx网站</h1><br>
    <c:if test="${user==null }">
        <a href="${pageContext.request.contextPath }/servlet/RegisterUIServlet">注册</a>
        <a href="${pageContext.request.contextPath }/servlet/LoginUIServlet">登录</a>
    </c:if>
    <c:if test="${user != null }">
        ${user.username }登录成功
        <input type="button" value="推出" onclick="doLogout()">
    </c:if>
  </body>
</html>

说明:当用户登录成功之后我们就不要再显示注册和登录按钮了,这里使用了标签对其进行控制。当用户成功之后我们还需要在后面加上一个推出按钮,用于推出业务请求。

用户推出请求业务(LogoutServlet.java

package cn.itcast.web.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LogoutServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        request.getSession().removeAttribute("user");
        request.setAttribute("message", "注销成功,本页面将在5秒钟后跳到首页"
                + "<meta http-equiv='refresh' content='5;url=/day09_user/index.jsp'");
        request.getRequestDispatcher("/message.jsp").forward(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

最后:

到此我们就完成了一个简单的用户注册和登录的web小demo,我们主要要学会这种MVC的开发模式。在后面我们会正真使用数据库进行开发,同时我们是在此工程的基础上进行修改即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容