JAVA WEB从入门到精通day14 JAVA三层架构、登录注册实战演练

MVC模式

MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式

-Model(模型)。是应用程序中用于处理应用程序数据逻辑的部分。
-View(视图)。是应用程序中处理数据显示的部分。
-Controller(控制器)是应用程序中处理用户交互的部分。

例如:
我们在View输入账号密码,点击登陆,然后触发Controller调用Model的方法
Model检查后发现错误,返回出错信息,Controller再把错误信息显示在View上。
用户修改正确以后,Controller再调用登陆方法进行登陆。

下面两张逻辑图帮我们理清思路

这里写图片描述

这里写图片描述

Java Web的三层架构

    -表示层(web层):包含JSP,Servlet等web相关的内容
    -业务逻辑层(Service):处理业务,
    -数据层(DAO Data Access Object):也叫持久层,封装了对数据库的访问细节,一般写DAO类

    我们写项目时一般要分成这三层。
    -Web层,Servlet,jsp等。
    -Service层(业务逻辑层)
    -Dao层(数据层)

案例:使用三层架构完成注册登录的功能

项目分析

1)先创建空项目
2)创建包和类
    -domain包:创建User类,是一个javabean
    -web包:用来存放登录注册的servlet,与web相关的类
    -service包:用来处理业务逻辑
    -dao包:用来负责处理用户数据
3)代码的实现
    我们一般是jsp页面将表单数据传入servlet
    servlet依赖service层来处理具体业务逻辑
    service层依赖dao层来进行数据的处理

项目结构

注册流程

1)首先创建register.jsp页面完成注册页面,也就是表单,我们只需要添加账号密码验证码这三项即可。 

2)表单中的数据提交给RegisterServlet,把数据封装到User对象中,RegisterServlet需要完成表单的检测,例如账号长度等。 

3)具体的实现应该交给业务逻辑层来实现,所以RegisterServlet中应该调用UserService的register方法,并将user对象传入。 

4)UserService的register方法,应该完成用来检测用户名是否被注册
    -如果已经注册,则抛出异常,这个异常是我们的自定义异常,因为我们要自定义异常信息
    -没有注册,就进行注册,当然需要调用数据层 

5)数据层应该实现两个方法
    -通过用户名查找对象
    -添加用户 
    我们还没有学数据库,所以在xml文件中存取数据  

登录流程

1)创建login.jsp完成登陆页面
2)登陆页面中的表单提交给LoginServlet
3)LoginServlet将对象封装,调用service的login方法来处理具体的业务逻辑
4)UserService的login方法
    -检测有没有该用户,没有的话就抛出异常
    -有的话,检测密码是否正确,不正确就抛出异常,正确就返回user对象
//我们首先创建cn.xxx.domain包,在domain包里创建一个javabean User类,用来封装对象
public class User {
    private String username;          //用户名
    private String password;          //密码
    private String vcode;             //验证码
    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 getVcode() {
        return vcode;
    }
    public void setVcode(String vcode) {
        this.vcode = vcode;
    }

    public String toString() {
        return "User [username=" + username + ", password=" + password + ", vcode=" + vcode + "]";
    }

}
 然后创建cn.xxx.dao包,创建数据层的类UserDao,类里应该实现两个方法
 -通过用户名查找对象方法
 -添加用户方法                  
package cn.cad.dao;

import java.io.FileOutputStream;
import java.util.List;

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

import cn.cad.domain.User;

public class UserDao {
    private String path="E://users.xml";   //我们还没有学数据库,所以在xml文件中存放数据
    public User findByUsername(String username)  //通过用户名查找对象的方法
    {
        try{
        SAXReader saxReader=new SAXReader();         //通过dom4j和xpath查找对象
        4  
        Document document=saxReader.read(path);
        Element e=(Element) document.selectSingleNode("//user[@username='"+username+"']"); 

        if(e!=null)                               
        //如果对象不为空,则将属性值username和password封装成user对象返回,否则返回空,就是没找到该用户
        {
            String name=e.attributeValue("username");
            String passwd=e.attributeValue("password");
            User user=new User();
            user.setUsername(name);
            user.setPassword(passwd);
            return user;
        }
        return null;
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }  

    public void addUser(User user)          //添加用户的方法
 {
     //将传进来的user对象添加到xml文件中
        try{
        SAXReader saxReader=new SAXReader();
        Document document=saxReader.read(path);
        Element root=document.getRootElement();
        Element newuser=root.addElement("user");

        newuser.addAttribute("username", user.getUsername());
        newuser.addAttribute("password", user.getPassword());

         OutputFormat format=OutputFormat.createPrettyPrint();
         XMLWriter xmlWriter=new XMLWriter(new FileOutputStream(path),format);
         xmlWriter.write(document);
         xmlWriter.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
我们需要自定义异常,因为当我们出现各种错误时时我们需要来抛出异常。所以我们需要来自定义一个异常类。
我们只需要继承Exception类,然后就不用管其他的。我们把这个类放在cn.xxx.service包里。

package cn.cad.service;

public class UserException extends Exception{

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

    public UserpException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
        super(arg0, arg1, arg2, arg3);
        // TODO Auto-generated constructor stub
    }

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

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

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


}
cn.xxx.service包。我们创建UserService类用来处理业务逻辑,需要实现两个业务逻辑的处理
-注册
-登陆
package cn.cad.service;

import cn.cad.dao.UserDao;
import cn.cad.domain.User;

public class UserService {
    private UserDao userdao=new UserDao();                //依赖数据层 

    public void register(User user) throws UserException  //注册业务逻辑的处理方法
    { 
    //表单中的数据被封装成user对象传入servlet,然后servlet再把对象传进来,让service实现具体的业务逻辑处理,我们先查找用户是否存在,存在就抛出用户名已存在的异常,不存在就调用添加用户的方法
        User  _user=userdao.findByUsername(user.getUsername());
        if(_user!=null)
        {
            throw new UserException("用户名"+user.getUsername()+"已存在");
        }

        userdao.addUser(user);

    } 

    //处理登陆的业务逻辑的方法。先查找用户是否存在,不存在就抛出用户未找到异常。
    //存在再判断密码是否正确,不正确抛出密码错误异常,正确就返回该对象。

    public User login(User user) throws UserException {
        User _user=userdao.findByUsername(user.getUsername());
        if(_user==null)
        {
            throw new UserException("用户未找到");
        }
        if(!user.getPassword().equals(_user.getPassword()))
        {
            throw new UserException("密码错误");
        }
        return _user;
    }
}

//创建cn.xxx.web.servlet包,来处理web层。
//RegisterServlet来进行表单检测和调用service的register方法。
package cn.cad.web.servlet;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.cad.domain.User;
import cn.cad.service.UserException;
import cn.cad.service.UserService;

public class RegiserServlet extends HttpServlet {

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

        String name=(String) request.getParameter("username");  //获取表单数据
        String passwd=(String) request.getParameter("password");
        String vcode=request.getParameter("vcode");

        //进行表单检测,map集合用来存放错误信息,因为可能有很多错误信息,我们使用键值对来存放
        Map <String,String>errmsg=new HashMap<String,String>();  

        //判断用户名的长度和是否为空
        if(name==null||name.trim().isEmpty())         
        {
            errmsg.put("username", "用户名不能为空");
        }else if(name.length()<=3||name.length()>=15)
        {
            errmsg.put("username", "用户名必须在3到15位之间");
        }

         //判断密码的长度和是否为空
        if(passwd==null||passwd.trim().isEmpty()) 
        {
            errmsg.put("password", "密码不能为空");
        }else if(passwd.length()<=3||passwd.length()>=15)
        {
            errmsg.put("password", "密码必须在3到15位之间");
        }

        //判断验证码的长度,是否为空和是否正确 
        if(vcode==null||vcode.trim().isEmpty())
        {
            errmsg.put("vcode", "验证码不能为空");
        }else if(vcode.length()!=4)
        {
            errmsg.put("vcode", "验证码长度错误");
        }else if(!vcode.equalsIgnoreCase((String) request.getSession().getAttribute("text")))
        {
            errmsg.put("vcode", "验证码错误");
        } 

        //判断map集合长度,如果大于0,说明有错误信息,保存到request欲,将用户的信息也保存起来,用来回显 
        if(errmsg.size()>0)
        {
            request.setAttribute("errmsg", errmsg);
            request.setAttribute("name", name);
            request.setAttribute("passwd", passwd);
            request.setAttribute("vcode", vcode);

            request.getRequestDispatcher("/user/register.jsp").forward(request, response);
            return;
        } 

        //封装user对象,调用service的register方法,如果什么都没有,则显示注册成功,不成功就捕获异常信息保存到request域,转发到注册页面
        User user=new User();
        user.setUsername(name);
        user.setPassword(passwd);
        UserService userservice=new UserService();
        try {
            userservice.register(user);
            response.getWriter().print("注册成功<a href='"+request.getContextPath()+"/user/login.jsp'>点击跳转</a>");
        } catch (UserException e) {
            // TODO Auto-generated catch block
            String msg=e.getMessage();
            request.setAttribute("msg", msg);
            request.getRequestDispatcher("/user/register.jsp").forward(request, response);
        }
    }

}
LoginServlet用来处理登陆
package cn.cad.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.cad.domain.User;
import cn.cad.service.UserService;

public class LoginServlet extends HttpServlet {

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

        //将登录的表单信息封装成对象,然后调用业务逻辑层的login方法
        如果成功,则将返回来的user对象保存在session域中,不成功则将异常信息保存在request域中,转发到登陆页面
        String name=request.getParameter("username");
        String passwd=request.getParameter("password");
        User user=new User();
        user.setUsername(name);
        user.setPassword(passwd);
        UserService userservice=new UserService();
        try {
            User sessionuser=userservice.login(user);
            request.getSession().setAttribute("sessionuser", sessionuser);
            response.sendRedirect("/User/user/welcome.jsp");
        } catch (Exception e) {
            request.setAttribute("msg", e.getMessage());
            request.getRequestDispatcher("/user/login.jsp").forward(request, response);
        }

    }

}
生成验证码的servlet,需要用到我们以前编写过的一个验证码生成类。
package cn.cad.web.servlet;

import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class VerifiCodeServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        VerifiCode v=new VerifiCode();   //创建验证码生成类
        BufferedImage bi=v.getImage();  //获取验证码图片
        request.getSession().setAttribute("text", v.getText()); //将验证码的正确字符串保存在session域中,以方便判断
        v.output(bi, response.getOutputStream()); //将验证码写入到页面
    }

}
登陆页面login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>登陆页面</h1>
<form action="/User/LoginServlet" method="post">
    用户名:<input type="text" name="username"><br/>
    密   码:<input type="password" name="password"><br/>
    <input type="submit" value="登录"><br/>
    <a href="/User/user/register.jsp">没有账号?点击注册</a>
    <br/>
    ${msg }  //用来显示错误信息
</form>

</body>
</html>
注册页面register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
    function change()
    {
        var img=document.getElementById("image");
        img.src="/User/VerifiCodeServlet?a="+new Date().getTime();
    }
</script>
</head>
<!--每一个input的后面都有一个用来显示错误信息的el表达式-->
<body>
    <h1>注册页面</h1>
    <form action="/User/RegiserServlet" method="post">  
    用户名:<input type="text" name="username" value="${requestScope.name }">${requestScope.errmsg.username }<br/>
    密   码:<input type="password" name="password" value="${requestScope.passwd }">${requestScope.errmsg.password }<br/>
    验证码:<input type="text" name="vcode" size="3" value="${requestScope.vcode }">
            <img src="/User/VerifiCodeServlet" id="image">  
            <a href="javascript:change()">看不清,换一张</a>

            ${requestScope.errmsg.vcode }
            <br/>
    <input type="submit" value="注册">
    </form>
    ${ requestScope.msg}
</body>
</html>
登陆成功页面welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>   
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<!--判断session域中是否有user对象,没有就不让看-->
<body>
    <c:choose>
        <c:when test="${empty sessionScope.sessionuser }">对不起,请您先登录</c:when>
        <c:otherwise>欢迎登录本系统,${sessionScope.sessionuser }</c:otherwise>
    </c:choose>
</body>
</html>
  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值