JavaWeb-13 (用户的注册和登录案例)

来源:互联网 发布:苹果mac怎么下载 编辑:程序博客网 时间:2024/06/06 07:20

JavaWeb-13:项目案例

用户注册和登录案例项目

一、用户注册和登录案例

1、技术架构:三层架构(表现层MVC:M:model V:View C:Controller)


2、要求:JSP中不能出现一行java脚本或java表达式。除了指令<%@%>,其余地方不能有<%%>

3、数据库:临时使用xml。解析使用Dom4j

4、必须知道要干什么?

5、开发步骤:

a、建立工程,搭建开发环境(拷贝jar包、建立配置文件)    dom4j.jar    jaxen.jar    commons-beanutils.jar    commons-logging.jar    standard.jar    jstl.jarb、建立类所用的包    cn.itcast.domain:放JavaBean    弄出数据库    cn.itcast.dao:放Dao接口    cn.itcast.dao.impl:放Dao接口的实现    cn.itcast.servcie:业务接口    cn.itcast.service.impl:业务接口实现    cn.itcast.web.controller:Servlet控制器    //WEB-INF/pages:用户无法直接访问(只能靠转发)

工程架构:


知识点:用户输入数据的验证

1、客户端验证:使用js代码。减轻服务器的负担2、服务器端验证:使用java代码。安全3、实际开发中:1+2

二、用户的注册和登录案例攻略


1、搭建环境:

创建好需要用来读取和存储的xml数据库文件--->导入jar包(用来操作xml数据库文件的Dom4J包、封装数据用的BeanUtils包、使用XPath的jaxen-1.1-beta-6.jar包),创建User类(JavaBean),用于关联每一层的数据。

User.java

package com.heima.bean;import java.io.Serializable;import java.util.Date;public class User implements Serializable{    private String username ;    private String password ;    private String email ;    private Date birthday ;    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 getEmail() {        return email;    }    public void setEmail(String email) {        this.email = email;    }    public Date getBirthday() {        return birthday;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }}

2、设计业务逻辑层和数据访问层的接口

新建dao包:

接口类IUserDao:新建用于操作JavaBean数据的方法接口类IUserDao,里面提供添加用户并返回用户对象的方法addUser接口,提供根据用户的名字和密码查找用户,返回用户对象的方法findUserByUserNameAndPassword接口,提供根据用户的姓名查找用户的方法findUserByUserName接口。

IUserDao

package com.heima.dao;import com.heima.bean.User;public interface IUserDao {    /**     * 将用户添加到数据库     * @param user  要添加的用户     * @return  成功返回此用户,失败返回null     */    public User addUser(User user) ;    /**     * 根据用户的名字和密码查找用户     * param username  用户名     * param password  用户的密码     * @return 找到用户返回此用户,否则返回null     */    public User findUserByUserNameAndPassword(String username,String password ) ;    /**     * 根据用户的姓名查找用户     * @param username 用户的姓名     * @return 找到用户返回此用户,否则返回null     */    public User findUserByUserName(String username) ;}

新建Utils包:

DBUtils类:该工具类主要用于获取xml里的数据和把数据写回xml文件的方法:

getDocument()和write2xml()方法。该类里使用了dom4J包里的工具类,例如创建dom4j解析器和写回xml文件的方法。

DBUtils.java

package com.heima.utils;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.io.OutputFormat;import org.dom4j.io.SAXReader;import org.dom4j.io.XMLWriter;//工具类public class DBUtils {    public static String path ;    static{        path = DBUtils.class.getClassLoader().getResource("users.xml").getPath() ;    }    //加载dom树    public static  Document getDocument(){        try {            //创建dom4j解析器            SAXReader reader = new SAXReader() ;            //读取文档            Document document = reader.read(path) ;            return document ;        } catch (DocumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null ;    }    //将内存中的dom树写回到硬盘    public static void write2xml(Document document){        try {            XMLWriter writer = new XMLWriter(new FileOutputStream(path),OutputFormat.createPrettyPrint()) ;            writer.write(document) ;            writer.close() ;        } catch (UnsupportedEncodingException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

新建dao.impl包:

该包用于存储继承接口类IUserDao的实现类UserDaoImpl.java。该类的作用:

addUser()主要是通过调用Utils包里提供的方法getDocument()和write2xml(),把从别处生成的User对象里的属性数据写到xml文件里并返回该User对象,findUserByUserNameAndPassword()主要是通过Utils包工具加载到xml里,然后通过dom4j里的方法使用XPath和相对应的属性定位到要找的user对象,并判断如果存在就封装成user对象并返回,无就返回null。findUserByUserName()主要是通过传进来的属性并加载了xml文档后去使用XPath定位要找的user,如果不存在就返回一个新的User对象,若找到就返回null。

UserDaoImpl.java

package com.heima.dao.impl;import java.text.ParseException;import java.text.SimpleDateFormat;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.Node;import com.heima.bean.User;import com.heima.dao.IUserDao;import com.heima.utils.DBUtils;public class UserDaoImpl implements IUserDao {    public User addUser(User user) {        //获取dom树        Document document = DBUtils.getDocument() ;        //获得根节点        Element root = document.getRootElement() ;        //添加用户        root.addElement("user").addAttribute("username", user.getUsername())            .addAttribute("password", user.getPassword())            .addAttribute("email", user.getEmail())            .addAttribute("birthday", new SimpleDateFormat("yyyy-MM-dd").format(user.getBirthday())) ;        //写回硬盘        DBUtils.write2xml(document) ;        return user;    }    public User findUserByUserNameAndPassword(String username, String password) {        //加载dom树        Document document = DBUtils.getDocument() ;        //查找user节点        Node node = document.selectSingleNode("//user[@username='" + username + "' and @password='" + password+ "']") ;        if(node != null){            //封装数据            User user = new User() ;            Element el = (Element)node ;            user.setUsername(el.valueOf("@username")) ;            user.setPassword(el.valueOf("@password")) ;            user.setEmail(el.valueOf("@email")) ;            try {                user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(el.valueOf("@birthday"))) ;            } catch (ParseException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            return user ;        }        return null;    }    public User findUserByUserName(String username) {        //加载dom树        Document document = DBUtils.getDocument() ;        //查找user节点        Node node = document.selectSingleNode("//user[@username='" + username + "']") ;        if(node != null){            return new User() ;        }        return null;    }}

新建service包:

接口IUserService类:

该类的框架目的主要是让实现类去调用实现类UserDaoImpl.java里的功能。方法接口login():目的为了让实现类根据用户的姓名和密码完成用户的登录,方法接口:register()目的为了让实现类完成注册用户的功能。

IUserService.java

package com.heima.service;import com.heima.bean.User;import com.heima.exception.UserExistException;public interface IUserService {    /**     * 根据用户的姓名和密码完成用户的登录     * @param username  用户的姓名     * @param password  用户的密码     * @return 登录成功返回此用户,失败返回null     */    public User login(String username,String password ) ;    /**     * 完成注册用户的功能     * @param user 要注册的用户     * @return  成功返回TRUE,失败返回FALSE     * @throws UserExistException 如果用户存在抛出用户存在异常     */    public boolean register(User user) throws UserExistException;}

新建exception包:

UserExistException.java:

用于提供给UserServiceImpl类抛出异常。

UserExistException.java

package com.heima.exception;public class UserExistException extends Exception {}

新建service.impl包:

UserServiceImpl类:

在类里创建UserDaoImpl的对象,并使用UserDaoImpl对象里的方法去获得对应的User对象。        login():通过根据用户的姓名和密码来传入到UserDaoImpl对象的方法中去完成用户的登录,并返回User对象。        register():通过根据用户的姓名来传入到UserDaoImpl对象的方法中去完成用户的注册验证,并返回boolean值。还有判断如果用户存在抛出异常。

UserServiceImpl.java

package com.heima.service.impl;import com.heima.bean.User;import com.heima.dao.IUserDao;import com.heima.dao.impl.UserDaoImpl;import com.heima.exception.UserExistException;import com.heima.service.IUserService;public class UserServiceImpl implements IUserService {    IUserDao dao = new UserDaoImpl() ;    public User login(String username, String password) {        return dao.findUserByUserNameAndPassword(username, password);    }    public boolean register(User user) throws UserExistException {        //验证用户是否已经存在了        User u = dao.findUserByUserName(user.getUsername()) ;        if(u != null){            //说明此用户已经存在了,需要抛出异常            throw new UserExistException() ;        }        User u1 = dao.addUser(user) ;        return u1!=null ;    }}

设计业务逻辑层和数据访问层的接口并实现步骤完成。

3、搭建表现层并连接各层间的关系

首先实现页面:新建index.jsp,写用于注册的register.jsp的超链和用于登录的login.jsp的超链

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">    <title>My JSP 'index.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">    -->  </head>  <body>      <a href="http://blog.163.com/faith_yee/blog/register.jsp">注册</a> &nbsp;&nbsp;<a href="http://blog.163.com/faith_yee/blog/login.jsp">登陆</a>  </body></html>

新建web.formbean包:

创建UserBean.java类:

该javabean类用于封装页面的数据和验证数据用的。类里除了各种属性和设置属性的方法之外,还有一个用来验证数据的方法validate(),就是从别处传来的各种属性都需要符合该方法里的规格,付过不符合,方法会为属性里的Map集合存储用于传达给页面的验证信息,并该方法最后返回boolean值反映存储的属性数据是否正确。

UserBean.java

package com.heima.web.formbean;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.HashMap;import java.util.Map;import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;//主要用来封装页面的数据,验证数据public class UserBean {    private String username ;    private String password ;    private String repassword ;    private String email ;    private String birthday ;    private Map<String,String> errors = new HashMap<String,String>() ;    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 getRepassword() {        return repassword;    }    public void setRepassword(String repassword) {        this.repassword = repassword;    }    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;    }    public Map<String, String> getErrors() {        return errors;    }    //检测数据    public boolean validate(){        //检测用户名        if(username == null || "".equals(username)){            errors.put("username", "用户名不能为空") ;        }else{            if(username.length() < 3 || username.length() > 8){                errors.put("username", "用户名长度不符合要求") ;            }        }        //检测密码        if(password == null || "".equals(password)){            errors.put("password", "密码不能为空") ;        }else{            if(password.length() < 3 || password.length() > 8){                errors.put("password", "密码长度不符合要求") ;            }        }        //检测重复密码        if(!repassword.equals(password)){            errors.put("password", "两次密码不一致") ;        }        //检测邮箱        String reg = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$" ;        if(email == null || "".equals(email)){            errors.put("email", "邮箱不能为空") ;        }else{            if(!email.matches(reg)){                errors.put("email", "邮箱格式不正确") ;            }        }        //检测出生日期        if(birthday == null || "".equals(birthday)){            errors.put("birthday", "出生日期不能为空") ;        }else{//          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;//          try {//              sdf.parse(birthday) ;//          } catch (ParseException e) {//              errors.put("birthday", "日期格式不正确") ;//          }            DateLocaleConverter dlc = new DateLocaleConverter() ;            try {                dlc.convert(birthday) ;            } catch (Exception e) {                errors.put("birthday", "日期格式不正确") ;            }        }        return  errors.isEmpty() ;    } }

在原来的Utils包:

新建WebUtils类:

该工具类用于给页面传进来的UserBean类中的属性数据还有页面发来的request请求进行使用反射技术生产对象:因为传来的类对象本来不存在,所以使用反射机制来处理生成对象,并使用BeanUtils包里的超级方法populate()把UserBean对象和页面中的属性和属性值包装起来,并返回。

WebUtils.java

package com.heima.utils;import javax.servlet.http.HttpServletRequest;import org.apache.commons.beanutils.BeanUtils;//为页面服务的工具类public class WebUtils {    public static <T> T  fillFormBean(Class<T> clazz,HttpServletRequest reqeust){        T t = null ;        //创建对象        try {            t = clazz.newInstance() ;            BeanUtils.populate(t, reqeust.getParameterMap()) ;        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return t ;      }}

新建web.controls包:

新建RegisterServlet.java类:

用于处理页面register.jsp传进来的UserBean数据,并通过调用UserBean里的验证数据方法validate()验证页面传进来的数据是否有效,无效会跳转回register.jsp页面,然后BeanUtils.copyProperties()用于将数据从userBean中拷贝到user对象中,为存储到xml文档中的必然步骤。最后调用UserServiceImpl类中的register()方法注册用户,成功跳转到login.jsp页面,失败跳转回register.jsp页面。另外一种可能,如果register()抛出了异常,那么RegisterServlet.java就给异常处理。

RegisterServlet.java

package com.heima.web.controls;import java.io.IOException;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 com.heima.bean.User;import com.heima.exception.UserExistException;import com.heima.service.IUserService;import com.heima.service.impl.UserServiceImpl;import com.heima.utils.WebUtils;import com.heima.web.formbean.UserBean;//注册处理器public class RegisterServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        request.setCharacterEncoding("UTF-8");        response.setContentType("text/html;charset=UTF-8");//      UserBean formuser = new UserBean() ;//      try {//          BeanUtils.populate(formuser, request.getParameterMap()) ;//      } catch (IllegalAccessException e) {//          // TODO Auto-generated catch block//          e.printStackTrace();//      } catch (InvocationTargetException e) {//          // TODO Auto-generated catch block//          e.printStackTrace();//      }        //接收页面数据,封装数据         UserBean userform = WebUtils.fillFormBean(UserBean.class, request) ;         //验证数据是否有效         if(!userform.validate()){             //没有通过             request.setAttribute("userform", userform) ;             request.getRequestDispatcher("/register.jsp").forward(request, response) ;             return ;         }         //验证通过         //将数据从userBean中拷贝到user对象中         User user = new User() ;         try {             //注册时间转换器            ConvertUtils.register(new DateLocaleConverter(), Date.class) ;             //拷贝数据            BeanUtils.copyProperties(user, userform) ;        } catch (Exception e) {            e.printStackTrace();        }         //注册用户         IUserService us = new UserServiceImpl() ;         try {            boolean flag = us.register(user) ;            if(flag){                //注册成功                response.getWriter().write("恭喜,注册成功,2秒后转向登陆页面") ;                response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.jsp") ;            }else{                response.getWriter().write("注册失败,2秒后转注册页面") ;                response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/register.jsp") ;            }        } catch (UserExistException e) {            //此用户已经注册过了            userform.getErrors().put("username", "此用户名已经注册了,请更换一个") ;            request.setAttribute("userform", userform) ;            request.getRequestDispatcher("/register.jsp").forward(request, response) ;              }    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

最后创建register.jsp:

    利用el表达式把存到UserBean里的属性值通过submit按钮发送到指定的RegisterServlet里,register.jsp也会通过el表达式返回UserBean里Map类型的errors信息。

register.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">    <title>My JSP 'register.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">    -->  </head>    <script type="text/javascript">        function formsubmit(form){            var username = form.username.value ;            if(username == ""){                //alert("用户名不能为空") ;                //return false ;            }            return true ;        }    </script>  <body>        <form action = "${pageContext.request.contextPath }/servlet/RegisterServlet" method="post" onsubmit="return formsubmit(this)">            <table border =1 >                <tr>                    <td>${"用户名" }</td>                    <td><input type="text" name = "username"  value = "${userform.username}">${userform.errors.username }</td>                </tr>                <tr>                    <td>${"密码" }</td>                    <td><input type="password" name = "password" value = "${userform.password }">${userform.errors.password }</td>                </tr>                <tr>                    <td>${"确认密码" }</td>                    <td><input type="password" name = "repassword" ></td>                </tr>                <tr>                    <td>${"邮箱" }</td>                    <td><input type="text" name = "email"  value = "${userform.email }">${userform.errors.email }</td>                </tr>                <tr>                    <td>${"出生日期" }</td>                    <td><input type="text" name = "birthday"  value = "${userform.birthday }">${userform.errors.birthday }</td>                </tr>                <tr>                    <td colspan = "2"><input type="submit"  value = "注册"></td>                </tr>            </table>        </form>  </body></html>

还有其他类和jsp文件:如下:

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">    <title>My JSP 'register.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">    -->  </head>    <script type="text/javascript">        function formsubmit(form){            var username = form.username.value ;            if(username == ""){                //alert("用户名不能为空") ;                //return false ;            }            return true ;        }    </script>  <body>        ${errorinfo }        <form action = "${pageContext.request.contextPath }/servlet/LoginServlet" method="post" onsubmit="return formsubmit(this)">            <table border =1 >                <tr>                    <td>${"用户名" }</td>                    <td><input type="text" name = "username"  value = "${userform.username}">${userform.errors.username }</td>                </tr>                <tr>                    <td>${"密码" }</td>                    <td><input type="password" name = "password" value = "${userform.password }">${userform.errors.password }</td>                </tr>                <tr>                    <td colspan = "2"><input type="submit"  value = "登陆"></td>                </tr>            </table>        </form>  </body></html>

LoginServlet.java

package com.heima.web.controls;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.heima.bean.User;import com.heima.service.IUserService;import com.heima.service.impl.UserServiceImpl;//实现登陆功能public class LoginServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        request.setCharacterEncoding("UTF-8");        response.setContentType("text/html;charset=UTF-8");        //拿取页面传递的数据        String username = request.getParameter("username") ;        String password = request.getParameter("password") ;        //查找用户        //创建service层对象        IUserService us = new UserServiceImpl() ;        User user = us.login(username, password) ;        if(user != null){            //登陆成功            request.getSession().setAttribute("loginuser", user) ;            response.getWriter().write("登陆成功,2秒后转向主页") ;            response.setHeader("Refresh", "2;url="+ request.getContextPath() + "/main.jsp") ;        }else{            //登陆失败            request.setAttribute("errorinfo", "用户名或者密码错误") ;            request.getRequestDispatcher("/login.jsp").forward(request, response) ;        }    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

main.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">    <title>My JSP 'register.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">    -->  </head>  <body>        ${loginuser.username },欢迎你  </body></html>

表现层完成。

三、总结

用户--->register.jsp--->输入信息------>提交到RegisterServlet里,RegisterServlet结合UserBean类、UserServiceImpl类给用户注册----->注册成功后:数据会转到User类里,并通过业务逻辑层和数据访问层的类和方法把User类里的数据存储到xml数据库中。可以发现,我们搭建这个项目是和用户的思维完全相反的。


资料下载

0 0