传智播客JavaWeb day07、day08-自定义标签(传统标签和简单标签)、mvc设计模式、用户注册登录注销

第七天的课程主要是讲了自定义标签、简单介绍了mvc设计模式、然后做了案例

1. 自定义标签

  1.1 为什么要有自定义标签

    前面所说的EL、JSTL等技术都是为了提高jsp的可读性、可维护性、方便性而取代在jsp页面中直接嵌入java代码的方式(el和jstl的实质也是一段Java代码,只是可以用他们来代替),但是在实际开发过程中业务非常的复杂,现有的el和jstl根本满足不了需求,所有得根据实际需求开发自己的标签,自定义标签应运而生。

  1.2 自定义标签分类(传统标签和简单标签)

    自定义标签分为两类:传统标签(继承tag接口)和简单标签(继承simpleTagSupport接口),实现的步骤同实现el函数一样。第一步就是写一个类,第二步就是定义一个tld文件对类中的方法和属性进行描述,第三步就是在jsp文件中对定义的tld文件进行引用。

    1.2.1 传统标签

      1.2.1.1 传统标签继承tag接口,里面有些重写方法setPageContext(可以用来初始化pageContext)、setParent(设置父标签)、doStartTag、doEndTag(这两个方法是最重要的两个方法,标签的实际功能就是在两个方法中定义的)

      1.2.1.2 Eval_Body、Skip_Body、Skip_Page、Eval_page 这个是doStartTag、doEndTag这两个方法的返回值,能控制标签的body和剩余page是否计算

      1.2.1.3 案例自定义一个showip的标签

package com.chenlh.prac;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;

public class ShowIP implements Tag {

    private PageContext pc = null;
    
    @Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int doStartTag() throws JspException {        
        try {
            String ip = pc.getRequest().getRemoteAddr();
            pc.getOut().write(ip);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public Tag getParent() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void release() {
        // TODO Auto-generated method stub

    }

    @Override
    public void setPageContext(PageContext arg0) {
        // TODO Auto-generated method stub
      pc = arg0;
    }

    @Override
    public void setParent(Tag arg0) {
        // TODO Auto-generated method stub

    }

}
View Code

    1.2.2 简单标签

         步骤:第一步,写一个类实现simpleTagSupport接口;第二步,写一个tld文件对类进行描述;第三步,在jsp页面中文tld文件进行引用

       案例:自定义一个showip的简单标签      

package com.chenlh.prac;

import java.io.IOException;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class SimpleShowIp implements SimpleTag {

    
    private PageContext pc = null;
    @Override
    public void doTag() throws JspException, IOException {
        // TODO Auto-generated method stub
      String ip = pc.getRequest().getRemoteAddr();
      pc.getOut().write(ip);
    }

    @Override
    public JspTag getParent() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setJspBody(JspFragment arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setJspContext(JspContext arg0) {
        // TODO Auto-generated method stub
        pc = (PageContext)arg0;

    }

    @Override
    public void setParent(JspTag arg0) {
        // TODO Auto-generated method stub

    }

}
View Code

 

2. mvc设计模式

  2.1 Java web的发展史(才有了mvc设计模式)

    2.1.1 servlet

       servlet是sun公司提供的最早的javaweb技术,它有一个缺点就是Java代码中编写html代码很不方便。

    2.1.2 jsp(实质也是一个servlet,第一次访问的时候会被翻译成一个servlet)

       基于servlet在Java代码中编写html代码很不方便的毛病,jsp应运而生,它能很方便的编写html代码同时还能嵌入Java代码

    2.1.3 jsp + javabean(模式一) ps:jsp包含标签技术

       久而久之发现在jsp中嵌入大量的Java代码,可读性不是很好,于是就有标签技术,而且jsp本身就是一个servlet于是就才用jsp+javabean的模式

    

    2.1.4 servlet+jsp +javabean(模式二)

       模式一又发展了一段时间,设计者发现jsp的特长就是向用户展示数据的,而现在又担任了servlet程序流转的工作,没有做到无尽期能,各司所职的目的,于是就有了模式二。

    2.1.5 javaweb经典一层架构(mvc设计模式)

        任何软件都可以看做是由如下三个模块组成的。控制器:用来控制程序流转;view:用来与用户进行交互;model:用来封装数据和处理业务逻辑(一个设计良好的软件都应该尽力将这三部分独立开来)

  2.2 Javabean  

    2.2.1 什么是javabean

       javabean是一个遵循特定写法的类

    2.2.2 javabean特点

         2.2.2.1 它必须有一个无参的构造函数

       2.2.2.2 属性必须私有化

       2.2.2.3 私有属性必须通过一个public类型的方法暴露给其它程序,并且方法名必须遵循一定的命名规范

3.案例

  3.1 用户注册登录注销(模式二实现:servlet+jsp+javabean+dom4J(xpath)+junit)

    用户注册登录注销主要的功能点:用户注册、用户登录、用户注销、记住用户名。知识点:XML的操作(这里用xml模拟数据库所以有dom4J的使用)、session应用(登录成功后保存用户数据)、cookie(记住用户名实质就是向客户端写一个cookie)、自定义标签(记住用户名时用户名可能是中文所以需要Decoder而此时又不想在页面中嵌入大量的Java代码)

    jar包:Junit,dom4J,*jstl,beanutils

    实现过程:

                      

    编程思想总结:各个模块尽量解耦,各司其职。如业务层不要出现SQL语句(因为有可能换成其他的数据库或者多数据库共用),DAO层不要出现页面上的提示信息,因为你不知道将来页面的提示信息要改什么样的。

    Xpath:Xpath的作用是用来检索dom文件的(xml文件加载成dom),它需要jaxen(jar包)的支持,用SaxReader解析xml

    3.1.1 注册   ps:throw new exception 之后的代码段将不再执行,抛走了;session丢失可能是没有存,或者客户端禁用了cookie

      3.1.1.1 判断验证码

          生成验证码并将验证码返回给浏览器的同时,也将它保存到session中,如果验证码不正确则转发到注册页面

      3.1.1.2 封装验证数据(直接放在javabean中验证) ps:这里用一个beanutils工具类,其中的popular方法能自动填充map数据到javabean中

          将数据封装到一个javabean里面,如果不正确就抛出异常,在这里需要一个必须被捕捉和处理的异常(自定义一个MsgException类)  ,如果外层捕捉到异常

          则将抛出的异常信息通过转发打印到注册页面上

                           PS:RunTimeException和Exception的区别就是RunTimeException不需要外层捕捉和处理,而Exception需要被捕捉和处理

      3.1.1.3 判断用户名是否已经注册

          如果用户名已经被注册,同样是抛出一个MsgException自定义的异常不过在抛出这个异常的时候也要通过throws在方法前面声明

      3.1.1.4 注册用户

          当上面的步骤都通过了,那么就可以向数据库中注册用户了。PS:这里是xml中添加一个user节点。首先将xml加载到dom中,然后获取root节点,然后声明                              一个element将注册信息setAttribute上,再将element附加到root根节点上,由于dom是一个引用类型,此时只需要利用xmlWriter将dom写入文件即可

    3.1.2 登录(记住用户名)

       3.1.2.1 校验用户名和密码

           校验成功后,将用户信息存session中,在需要用户登录才能访问的页面判断有没有session信息即可

       3.1.2.2 是否记住用户名

           PS:<input type="checkbox" value="ok">如果勾选上,则会将value值以表单的形式传到服务器,否则不传。(这里可以用chrome F12观察一下)

         3.1.2.2.1 勾选上:如果勾选上了,则要实例化一个cookie对象,并设置path和setMaxAge属性并添加到response中(这里有个问题就是当用户名为中文的时候返回 cookie,当cookie再次发送到服务器时会因为乱码导致服务器错误,而setContentType("text/html;charset=utf-8")只对页面content有效,所以这里必须要用UrlEncoder对用户名进行编码,同时页面上获取的时候需要解码,但是我又不想在jsp中写大量的Java代码,所以此时想到了自定义标签)

                自定义标签三步骤:第一步,继承simpleTagSupport接口,重新dotag方法;第二步,定义描述tld文件;第三步页面引用

                ps:这里还有小细节就是当有cookie那么用户在登录界面的时候记住用户名复选框一定要勾上

        3.1.2.2.2 记住用户名没有勾选:那么只要删除cookie即可

              删除cookie的方法:声明一个同名同path的cookie并将setMaxAge设置成0即可然后添加到response中

    3.1.3 注销

       这个环节就比较简单了,其实就是将session杀死调用request.getSession().invaidate()

       Ps:request.getSession()默认情况下如果有session对象则返回一个,如果没有则创建一个session对象;而request.getSession(false)如果有就返回session对象,如果没有也不会创建了。

源代码下载:http://pan.baidu.com/s/1i306til

原文地址:https://www.cnblogs.com/lihongchen/p/4364767.html