web 学习笔记13_1-典型MVC Web工程演示

1、用户注册和登陆的案例:

主要是学习一个软件的架构
a.技术架构:三层架构(表现层MVC:M:model   V:View C:Controller)
b.要求:JSP中不能出现一行java脚本或java表达式。除了指令<%@%>,其余地方不能有<%%>
c.数据库:临时使用xml。解析使用Dom4j

2、基本的开发步骤:

a.建立工程,搭建开发环境(拷贝jar包、建立配置文件).
b.建立类所用的包(根据3层架构模型)
    M:model         ---javabean
    V:View          ---JSP显示,交互
    C:Controller    ---Servlet控制业务逻辑

    com.example.bean:放JavaBean    弄出数据库
    com.example.dao:放Dao接口
    com.example.dao.impl:放Dao接口的实现
    com.example.servcie:业务接口
    com.example.service.impl:业务接口实现
    com.example.web.controller:Servlet控制器
    com.example.utils ; 工具类的包

c.我们先写bean包里面的类,因为它在各个层之间穿越.
    建一个User.java类,最好实现Serializable接口
    定义你需要的变量
    使用get set 方法生成,最好生成下toString方法,便于直接输出调试。


d.再编写service包里面的类:
        这个包是给页面服务的,我们写的时候面向接口,便于扩展。
        你页面只有登录和注册,所以我们服务层就提供2个方法,分别是登陆和注册。
        例如:
        public interface UserService {

                /**
                 * 根据用户名和密码登录
                 * @return 登录成功返回此用户,否则返回null
                 */
                public User login(String username,String password ) ;

                /**
                 * 注册用户
                 * @param user 要注册的用户
                 * @throws UserExistsException 当用户名已经存在的时候,抛出一个用户已存在异常
                 */
                public void register(User user) throws UserExistsException ;
            }

        上面方法抛出了个UserExistsException异常,我们再新建一个exception,编写下UserExistsException类
            com.example.exception
            UserExistsException.java:
            public class UserExistsException extends Exception {

            }
            //自己的异常定义,就是这么简单。
                    现在服务层接口定义好了,等会再编写impl实现类。
e.编写dao层接口
        例如:
            com.example.dao
            UserDao.java:
            public interface UserDao {

                /**
                 * 根据用户名和密码查询用户
                 * @return 查询到用户返回此用户,否则返回null
                 */
                public User findUserByUserNameAndPassword(String username,String password) ;

                /**
                 * 注册用户
                 * @param user 要注册的用户
                 */
                public void add(User user) ;

                /**
                 * 根据用户的名字查找用户,看看是否已经注册
                 * @param name 用户的名字
                 * @return 查询到了返回此用户,否则返回null
                 */
                public User findUserByUserName(String name) ;
            }
        dao层的接口就定义好了,具体的impl的实现类,等会再编写。
f.编写dao接口的实现类:
        现在用xml文件,以后我们可以修改这个地方来使用数据库存储。

        我们使用xml解析,所以我们在utils包里面建一个工具类
        com.example.utils
        JaxpUtils.java:
        例如:
            //操作XML文件的方法
            public class JaxpUtils {
                static String path ;
                static{
                    path = JaxpUtils.class.getClassLoader().getResource("users.xml").getPath() ;
                }
                public static Document getDocument(){
                    try {//创建一个dom4j解析器
                        SAXReader reader = new SAXReader() ;
                        Document document = reader.read(path) ;
                        return document ;
                    } catch (DocumentException e) {
                        e.printStackTrace();
                    }
                    return null ;
                }

                public static void write2xml(Document document){
                    try {
                        XMLWriter writer = new XMLWriter(new FileOutputStream(path), OutputFormat.createPrettyPrint()) ;
                        writer.write(document) ;
                        writer.close() ;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        再调用工具类,编写dao的实现类
        com.example.dao.impl
        UserDaoImpl.java:
        例如:
            public class UserDaoImpl implements UserDao {
                public User findUserByUserNameAndPassword(String username, String password) {
                    Document document = JaxpUtils.getDocument() ;//加载Dom树
                    //查询需要的node节点
                    Node node = document.selectSingleNode("//user[@username='" + username+ "' and @password='" + password + "']") ;
                    if(node != null){
                        User user = new User() ;//找到了用户,封装数据
                        user.setUsername(username) ;
                        user.setPassword(password) ;
                        user.setEmail(node.valueOf("@email")) ;
                        String bithday = node.valueOf("@birthday") ;
                        try {
                            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(bithday)) ;
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return user;
                    }
                    return null;
                }

                public void add(User user) {
                    Document document = JaxpUtils.getDocument() ;//加载dom树
                    Element root = document.getRootElement() ;//拿到根节点
                    //添加一个user节点
                    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())) ;
                    JaxpUtils.write2xml(document) ;//将dom树保存到硬盘上
                }

                public User findUserByUserName(String name) {
                    Document document = JaxpUtils.getDocument() ;//加载Dom树
                    //查询需要的node节点
                    Node node = document.selectSingleNode("//user[@username='" + name +"']") ;
                    if(node != null){
                        User user = new User() ;//找到了用户,封装数据
                        user.setUsername(name) ;
                        user.setPassword("@password") ;
                        user.setEmail(node.valueOf("@email")) ;
                        String bithday = node.valueOf("@birthday") ;
                        try {
                            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(bithday)) ;
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return user;
                    }
                    return null;
                }
            }
g.  编写service接口的实现类:
        com.example.service.impl
        UserServiceImpl.java
        例如:
            public class UserServiceImpl implements UserService {
                UserDao dao = new UserDaoImpl() ;

                public User login(String username, String password) {
                    return dao.findUserByUserNameAndPassword(username, password);
                }

                public void register(User user) throws UserExistsException {//抛一个用户存在的异常
                    User u = dao.findUserByUserName(user.getUsername()) ;//查找用户
                    if(u == null)
                        dao.add(user) ;//说明用户没有注册过
                    else
                        throw new UserExistsException() ;
                }
            }
        很简单。后面我们在用户访问servlet的时候,servlet只需要调用这个服务的方法来注册和登陆了。
h.现在需要写和页面相关的内容了。
        index.jsp:
            <body>
                <a href = "register.jsp">注册</a>
                <a href = "login.jsp">登陆</a>
            </body>
        regiest.jsp:
            <body>
               <h1>注册用户</h1>
               <hr>
               <center>
               <form action="${pageContext.request.contextPath }/servlet/RegisterServlet" method="post">
                    <table>
                       <tr>
                           <td align  ="right">姓名:</td>
                           <td align = "left"><input type = "text" name = "username" value = "${user.username }"></td>
                           <td><span>${user.errors.username }</span></td>
                       </tr>
                       <tr>
                           <td align  ="right">密码:</td>
                           <td align = "left"><input type = "password" name = "password" ></td>
                           <td><span>${user.errors.password }</span></td>
                       </tr>
                       <tr>
                           <td align  ="right">确认密码:</td>
                           <td align = "left"><input type = "password" name = "repassword" ></td>
                           <td></td>
                       </tr>
                       <tr>
                           <td align  ="right">邮箱:</td>
                           <td align = "left"><input type = "text" name = "email" value = "${user.email }"></td>
                           <td><span>${user.errors.email }</span></td>
                       </tr>
                       <tr>
                           <td align  ="right">生日:</td>
                           <td align = "left"><input type = "text" name = "birthday" value = "${user.birthday }"></td>
                           <td><span>${user.errors.birthday }</span></td>
                       </tr>
                       <tr>
                           <td colspan = "3" align = "center"><input type = "submit" value = "注册"></td>
                       </tr>
                   </table>
               </form>
               </center>
            </body>
i.我们需要给页面传递过来的数据写个bean类,封装数据
        新建一个包com.example.web.formbean
        UserFormBean.java  //此bean专门用来封装页面的数据,因传递过来的数据都是字符串,和User里面定义的不一样
        里面的成员变量
            private String username;
            private String password;
            private String repassword;
            private String email;
            private String birthday;
            //提供一个错误信息
            private Map<String,String> errors = new HashMap<String,String>() ;
        生成get set方法
        我们在添加一个服务端验证的方法,防止客户端绕过JavaScript验证,直接达到服务器
        例如:
        //服务端验证
        public boolean validate(){
            //验证用户名
            if(username == "" || username == null){
                errors.put("username", "用户名不能为空") ;
            }else{
                if(username.length() > 8 || username.length() < 3){
                    errors.put("username", "用户名长度必须在3~8位之间") ;
                }
            }
            //验证密码
            if(password == "" || password == null){
                errors.put("password", "密码不能为空") ;
            }else{
                if(password.length() > 8 || password.length() < 3){
                    errors.put("password", "密码长度必须在3~8位之间") ;
                }
            }
            if(!repassword.equals(password)){
                errors.put("password", "两次密码输入不一致") ;
            }
            //验证邮箱
            if(email == "" || email == null){
                errors.put("email", "邮箱不能为空") ;
            }else{
                if(!email.matches("^([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})(\\]?)$")) 
                    errors.put("email", "邮箱格式不正确") ;
            }
            //验证生日
            if(birthday == "" || birthday == null){
                errors.put("birthday", "生日不能为空") ;
            }else{              
                DateLocaleConverter dlc = new DateLocaleConverter() ;
                try {
                    dlc.convert(birthday) ;
                } catch (Exception e) {
                    errors.put("birthday", "日期格式错误") ;
                }
            }
            return errors.isEmpty() ;//如果是空的就说明验证通过
        }
j、接下来我们可以写Servlet。
        先编写一个工具类
        com.example.utils
        WebUtils.java
        //专门为页面服务: 封装了页面的信息
        public class WebUtils {
            public static <T> T fillFormBean(Class<T> clazz,HttpServletRequest request){
                T t = null ;
                try {
                    t = clazz.newInstance() ;//使用了个反射
                    BeanUtils.populate(t, request.getParameterMap()) ;
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return t ;
            }
        }

        再编写servlet
        com.example.web.servlet
        RegisterServlet.java
        /完成注册的功能
        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");
                PrintWriter out = response.getWriter();

                //第一步,先封装数据到userbean中
                UserFormBean ufb = WebUtils.fillFormBean(UserFormBean.class, request) ;

                //第二步,验证数据
                if(ufb.validate()){
                    //说明验证通过
                    //第三步,将formbean中的数据拷贝到user对象
                    User user = new User() ;
                    //由于formbean中的生日是String类型,userbaen中的生日是Date类型,beanUtils类不能自动转换,因此必须注册一个日期类型转换器
                    try {
                        ConvertUtils.register(new DateLocaleConverter(), Date.class) ;
                        BeanUtils.copyProperties(user, ufb) ;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    //第四步,注册用户
                    //调用业务逻辑层完成注册
                    UserService us = new UserServiceImpl() ;
                    try {
                        us.register(user) ;
                        //注册成功
                        //返回登陆页面
                        response.getWriter().write("恭喜你,注册成功,2秒后转向登陆页面") ;
                        response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.jsp") ;
                        //response.sendRedirect(request.getContextPath() + "/login.jsp") ;

                    } catch (UserExistsException e) {
                        //说明用户已经注册过了
                        ufb.getErrors().put("username", "此用户名已经被注册过了,请换一个") ;
                        //将ufb存入request对象
                        request.setAttribute("user", ufb) ;
                        request.getRequestDispatcher("/register.jsp").forward(request, response) ;
                    }
                }else{
                    //验证不通过
                    //完成数据的回显操作,把ufb对象存放到request
                    request.setAttribute("user", ufb) ;
                    request.getRequestDispatcher("/register.jsp").forward(request, response) ;
                }
            }

            public void doPost(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
                doGet(request, response);
            }
        }
k、编写登陆页面jsp
        <body>
          <center>
           <h1>登陆页面</h1>
           <hr>
           <font color =red>${error }</font>
           <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post">
                <table>
                   <tr>
                       <td align  ="right">姓名:</td>
                       <td align = "left"><input type = "text" name = "username" ></td>
                       <td><span></span></td>
                   </tr>
                   <tr>
                       <td align  ="right">密码:</td>
                       <td align = "left"><input type = "password" name = "password" ></td>
                       <td><span></span></td>
                   </tr>
                   <tr>
                       <td colspan = "3"><input type = "submit" value = "登陆"></td>
                   </tr>
               </table>
           </form>
           </center>
        </body>
l、编写登陆的Servlet
        com.example.web.servlet
        LoginServlet.java
        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");
                PrintWriter out = response.getWriter();

                //获取页面的数据
                String name = request.getParameter("username") ;
                String pass = request.getParameter("password") ;

                //验证数据(略)
                //调用service层完成业务逻辑
                UserService us = new UserServiceImpl() ;
                User user = us.login(name, pass) ;
                if(user != null){
                    //合法用户
                    request.getSession().setAttribute("loginuser", user) ;
                    request.getRequestDispatcher("/main.jsp").forward(request, response) ;
                }else{
                    //非法用户
                    request.getSession().setAttribute("error", "用户名或者密码错误") ;
                    response.sendRedirect(request.getContextPath() + "/login.jsp") ;
                }
            }
            public void doPost(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
                doGet(request, response);
            }
        }

        编写一个登陆成功之后的页面 main.jsp
          <body>
              ${loginuser.username },欢迎你
          </body>

到这里整个流程都结束了,对整个的3层架构有了更加深入的了解了。

总结下:
3层架构,我们写dao的时候是面向接口的,有什么好处呢?
如果以后我们存储的数据方式改变了,例如想用数据库存储,不用改变其他的类,我们只要加类,重新实现下
扩展性更好了。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值