JavaWeb笔记-14-验证登陆注册案例。学习感想、遗留问题(未解决)

1、各个包在框架下的理解:

    User作用:
        //存放用户实体。提供属性,get/set方法

    UserDao
        //实现对文件数据的操作。是service的底层
        //发送反馈给service

    service
        //提供可实现的功能
        //service不具体实现,调度UserDao。接收UserDao实现的反馈。
        //发送反馈给servlet

    servlet
        //调度。
        //接收service功能的反馈。
        //完成相关信息、异常消息的存放。返回给jsp用以显示

2、注册流程:

用户提交表单  jsp
    如果异常,使用EL表达式输出异常信息。
    传递验证码图片

servlet封装表单,传递(调用)给service#regist     servlet
    封装:toBean    ***导包。
    service.regist()

    接收service结果。


service#regist。用于接收注结果。根据注册功能对应的文件操作。转发给userdao完成。自身用于接收反馈信息。
    先调用userdao#findByName中查询
        返回null正常:调用userdao#add添加
                添加完成。跳转登陆界面。
        返回异常:获取异常信息,保存到request域。转发回注册界面

userdao查询与添加。是否存在。存在则不添加。不存在则添加  完成后反馈给上层。
    知识点,dom4j对xpath的操作。 ***需要导包jaxen-1.1-beta-6.jar 

    findByName      
        得到doc
        使用xpath查找
            没找到:返回null
            找到了,返回注册异常。

    add
        得到doc
        得到根节点
        创建新元素
        设值。
        回写。


user数据的底层设置和获取方法。

底层文件:xml
    xml格式:每个用户一个<user>属性为username和password

3、练习感想:

//xml文件配置
    考虑根元素
    考虑属性

//表单提交
    考虑提交地址:项目名  +  web.xml中对应的Url-pattern属性值
    提交方式:EL表达式、JSTL-core库标签
        EL表达式:${pageContext.request.contextPath}/RegistServlet
        JSTL-core库标签:<c:url value='/RegistServlet'/>

//创建方法时:
    考虑是否需要返回值,返回值类型
    考虑参数

//requst应用理解:
    多用于servlet与jsp页面的数据请求共享
    eg:1)保存错误信息到request中,(设置属性及信息)可以在jsp界面用EL表达式输出。
                EL表达式的优势:有值回输出,无值不输出
        2)用于用户名回显。

//EL表达式应用理解:
    在jsp页面中输出域中内容,输出集合中内容。

//session感想
    保存一次对话的信息
    可用于数据回显等操作。

//xpath感想
    用于查找xml文件节点。极其方便。

//输入验证时 考虑输入为空情况

//jsp插入图片:
    需设置src !
    设置id

//jsp调用JavaScript代码
    jsp页面需要动态效果时,需编写JavaScript代码用数据呈现动态效果。 eg:图片切换。

//超链接调用JavaScript代码
        点击元素时启动 JavaScript。
         <a href="javascript:_change()">


遗留问题:
    异常处理的交互流程。

    封装表单数据的过程。

代码:

package Domain

//实体类
//存放用户实体。提供属性,get/set方法

public class User {
    private String username;
    private String password;
    private String verifyCode;
    public String getVerifyCode() {
        return verifyCode;
    }
    public void setVerifyCode(String verifyCode) {
        this.verifyCode = verifyCode;
    }
    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 User() {
        super();
        // TODO Auto-generated constructor stub
    }
    public User(String username, String password, String verifyCode) {
        super();
        this.username = username;
        this.password = password;
        this.verifyCode = verifyCode;
    }
}

package Dao

//实现对文件数据的操作。是service的底层
        //发送反馈给service
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import Domain.User;

public class UserDao {
    private String path = "E:/users.xml";

    /**
     * 按用户名查询
     * 
     * @param username
     * @return
     * @author 一万年行不行
     */
/*   
 * 步骤:
 *  1.得到doc
 *  2.使用xpath查找
 *      没找到:返回null
 *      找到了,返回注册异常。
*/
    public User findByUsername(String username) {

        // 创建解析器
        SAXReader reader = new SAXReader();
        try {
            //通过解析器得到document
            Document doc = reader.read(path);

            //通过xpath查询元素,返回给ele
            Element ele = (Element) doc.selectSingleNode("//user[@username='"+ username + "']");

            //校验ele是否为null,如果为null,返回null 
            if (ele == null)
                return null;  

            //找到了,则需要返回一个user对象,
            //表示(user.username)用户找到了,在登陆功能中,也可直接调用user对象比对密码
            //此时ele为元素,不能作为对象返回。
            //需要创建出一个user  提取出ele元素的属性值,  赋给user 
            //返回
            User user = new User();
            String attrUsername = ele.attributeValue("username");// 获取该元素的名为username属性值
            String attrPassword = ele.attributeValue("password");// 获取该元素的名为password属性值
            user.setUsername(attrUsername);
            user.setPassword(attrPassword);

            return user;
        } catch (DocumentException e) {
            throw new RuntimeException(e);   //?有什么用
        }
    }

    /**
     * 添加用户
     * 
     * @param user
     * @author 一万年行不行
     */
    public void add(User user) {
        /*
         1.得到doc
         2.得到根节点
         3.创建新元素
         4.设值。
         5.回写。
         */

        SAXReader reader = new SAXReader();
        try {
            // 得到Document
            Document doc = reader.read(path);
            // 得到根元素
            Element root = doc.getRootElement();
            // 通过根元素创建新元素
            Element userEle = root.addElement("user");
            // 为userEle设置属性
            userEle.addAttribute("username", user.getUsername());
            userEle.addAttribute("password", user.getPassword());

             //保存文档  
                // 创建格式化器
            OutputFormat format = OutputFormat.createPrettyPrint();

            // 创建XmlWriter
            XMLWriter writer;
            try {  
                 //将回写对象放进流中,保证该流对象为"UTF-8"。
                writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8"), format);
                writer.write(doc);
                writer.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }
}

package service

/**
 * @author 一万年行不行
 * 自定义异常,只需要给出父类中的构造器。方便用来创建对象
 */
public class UserException extends Exception {

    public UserException() {
        super();
        // TODO Auto-generated constructor stub
    }

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

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

    public UserException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }
}
public class UserService {
    private UserDao userDao = new UserDao();
    /**
     * 注册功能
     * @param user
     * @throws UserException
     * @author 一万年行不行
     */
    public void regist(User user) throws UserException {

        //查询是否存在
        User _user = userDao.findByUsername(user.getUsername());

        //存在,抛异常
        if(_user != null) throw new UserException("用户名" + user.getUsername() + ", 已被注册过了!");

        //不存在,添加
        userDao.add(user);
    }
    /**
     * 登录功能
     * @param form
     * @return
     * @throws UserException
     * @author 一万年行不行 
     */
    public User login(User form) throws UserException {

         // 1. 使用form中的username进行查询,得到User user
        User user = userDao.findByUsername(form.getUsername());

        // 2. 如果返回null,说明用户名不存在,抛出异常,异常信息为“用户名不存在”
        if(user == null) throw new UserException("用户名不存在!");

        //找到用户名了
        //3. 比较user的password和form的password,如果不同,抛出异常,异常信息为“密码错误!”
        if(!form.getPassword().equals(user.getPassword())) {
            throw new UserException("密码错误!");
        }

        //返回数据库中查询出来的user,而不是form,因为form中只有用户名和密码,而user是所有用户信息!
        return user;
    }
}

package web.servlet

/** 
 * @author 一万年行不行
 */
public class LoginServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //依赖userservice
        UserService userService = new UserService();
        //封装表单数据(form)为User对象。
        User form = CommonUtils.toBean(request.getParameterMap(), User.class);
        try {
            //调用登陆
            User user = userService.login(form);

            //登陆成功,返回user,保存用户信息到session
            request.getSession().setAttribute("sessionUser",user);
            //登陆成功,重定向到新的页面。 .sendRedirect();重定向方法。
            response.sendRedirect(request.getContextPath() +"/user/welcome.jsp");
        } catch(UserException e) {
            //登陆异常
            //设置异常信息到request请求域中,
            request.setAttribute("msg", e.getMessage());
            //保存form表单数据   用于回显
            request.setAttribute("user", form);
            //转发回登陆界面。显示request域中错误信息。
            request.getRequestDispatcher("/user/login.jsp").forward(request, response);
        }   
    }
}
/**
 * @author 一万年行不行
 */
public class RegistServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        // 依赖userservice
        UserService userService = new UserService();

        // 封装表单数据
        User form = CommonUtils.toBean(request.getParameterMap(), User.class);

    /*  
         表单校验
         * 1. 创建一个Map,装载所有的表单错误信息
         * 2.校验。
         *      失败,向map添加错误信息,其中key为表单字段名称 
         * 3.查看map长度是否大于0,
         *      a.大于0。有错误! 
         *          处理错误:保存map到request中,保存form到request中,转发到regist.jsp
         *      b.等于0。没有错误,向下执行!
    */

    // 1. 创建一个Map,装载所有的表单错误信息
        Map<String, String> errors = new HashMap<String, String>();

    // 2.校验。
        // 对用户名进行校验,获取表单的username
        String username = form.getUsername();

        //用户名不为空,trim();表示去掉空格。
        if (username == null || username.trim().isEmpty()) {
            //为空,向map中存放错误信息。
            errors.put("username", "用户名不能为空!");
        } else if (username.length() < 3 || username.length() > 15) {
            errors.put("username", "用户名长度必须在3~15之间!");
        }

        // 对密码进行校验
        String password = form.getPassword();
        if (password == null || password.trim().isEmpty()) {
            errors.put("password", "密码不能为空!");
        } else if (password.length() < 3 || password.length() > 15) {
            errors.put("password", "密码长度必须在3~15之间!");
        }

        // 对验证码进行校验   获取保存到session中的验证码
        String sessionVerifyCode = (String) request.getSession().getAttribute(
                "session_vcode");
        // 获取表单中验证码字节
        String verifyCode = form.getVerifyCode();
        if (verifyCode == null || verifyCode.trim().isEmpty()) {
            errors.put("verifyCode", "验证码不能为空!");
        } else if (verifyCode.length() != 4) {
            errors.put("verifyCode", "验证码长度必须为4!");
        } else if (!verifyCode.equalsIgnoreCase(sessionVerifyCode)) {
            errors.put("verifyCode", "验证码错误!");
        }


         // 处理错误: 判断map是否为空,不为空,说明存在错误
        if (errors != null && errors.size() > 0) {

            // 1. 保存errors到request域      
            request.setAttribute("errors", errors);
            //2. 保存form到request域,为了回显 
            request.setAttribute("user", form);
            //3. 转发到regist.jsp
            request.getRequestDispatcher("/user/regist.jsp").forward(request,
                    response);
            return;
        }

        //验证格式正确后,开始注册
        try {
            //调用userService的regist()方法,传递form过去 
            userService.regist(form);
            //没有异常:输出注册成功!
            response.getWriter().print(
                    "<h1>注册成功!</h1><a href='" + request.getContextPath()
                            + "/user/login.jsp" + "'>点击这里去登录</a>");
        } catch (UserException e) {
        //得到异常:获取异常信息,保存到request域,转发到regist.jsp中显示 
            // 获取异常信息,保存到request域
            request.setAttribute("msg", e.getMessage());
            // 还要保存表单数据,到request域
            request.setAttribute("user", form);// 用来在表单中回显!
            // 转发到regist.jsp
            request.getRequestDispatcher("/user/regist.jsp").forward(request,
                    response);
        }
    }
}
public class VerifyCodeServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //1. 创建验证码类
        VerifyCode vc = new VerifyCode();

        //2. 得到验证码图片
        BufferedImage image = vc.getImage();

        //3. 把图片上的文本保存到session中
        request.getSession().setAttribute("session_vcode", vc.getText());

        //4. 把图片响应给客户端
        VerifyCode.output(image, response.getOutputStream());
    }
}

注册界面

<head>
<script type="text/javascript">
    /*
    如果一个表单项的name和<img>的id相同,那么可能会出问题!一般只有IE出问题!
    */
    function _change() {
        /*
        1. 获取<img>元素
        */
        var ele = document.getElementById("vCode");
        ele.src = "<c:url value='/VerifyCodeServlet'/>?xxx=" + new Date().getTime();

    }
</script>
  </head>  
<body>
<h1>注册</h1>
<p style="color: red;font-weight: 900"> ${msg} </p>
<form action="<c:url value='/RegistServlet'/>" method="post">
用户名:<input type="text" name="username" value="${user.username}"/>${errors.username}<br/>
密&nbsp;&nbsp;&nbsp;码:<input type="password" name="password" value="${user.password}"/>${errors.password}<br/>
验证码:<input type="text" name="verifyCode" value="${user.verifyCode }" size="3"/>
        <img id="vCode" src="<c:url value='/VerifyCodeServlet'/>" border="2"/>
        <a href="javascript:_change()">换一张</a>${errors.verifyCode }<br/>
<input type="submit" value="注册"/>

</form>
</body>

登陆界面

  <body>
<h1>登录</h1>
<p style="color: red; font-weight: 900">${msg }</p>
<%--${pageContext.request.contextPath }/RegistServlet --%>
<form action="<c:url value='/LoginServlet'/>" method="post">
  用户名:<input type="text" name="username" value="${user.username }"/><br/>
  密 码:<input type="password" name="password" value="${user.password }"/><br/>
  <input type="submit" value="登录"/>
</form>
  </body>

欢迎界面

<body>
<h1>欢迎登录本系统</h1>
<c:choose>
    <c:when test="${empty sessionScope.sessionUser }">滚!</c:when>  //防止未登陆用户直接访问此页面。
    <c:otherwise>
        ${sessionScope.sessionUser }
    </c:otherwise>
</c:choose>
  </body>

猜你喜欢

转载自blog.csdn.net/qq_41307491/article/details/81395686