• JSP/Servlet开发——第二章 JSP数据交互(二)


    1、 JSP 内置对象 application:

    ●application 对象类似于系统的 "全局变量", 用于同一个应用内的所有用户之问的数据共享;

    ●application对象的常用方法:

    方法名称

    说  明

    void setAttribute(String key,Object value)

    以key/value的形式将对象储存到application中;

    Object getAttribute(String key)

    通过key获取application中存储的对象

    String getRealPath(String path)

    返回相对路径的真实路径

    eg:在网站系统中统计并显示已访问的在线人数:

    eg:登陆页面的JSP代码:

     <html>

      <head> 

        <title>My JSP 'login.jsp' starting page</title>

      </head>

      <%

         Integer count = (Integer) application.getAttribute("count");

         if(count !=  null){

                count = 1 + count;

         }else{

                count = 1;     

         }

         application.setAttribute("count", count);

    %>

      <body>

        <form name="loginForm" method="post" action="showCount.jsp">

                     用户名:<input type="text" name="userName" />

                     密码:<input type="password" name="pwd" />

                     <input type="submit" value="登录">

              </form>

      </body>

    </html>

    eg:统计页面的JSP代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <%

             Integer i = (Integer) application.getAttribute("count");

             out.println("统计访问量:目前有 " + i + " 个人访问过本网站" );

    %>

    运行结果:

     

    分析:这里使用 count 存储统计的访问人数,由干无法控制是第几个用户访问本网站,所以先通过 getAttribtue 方法取值进行判断,如果count 为 null ,说明是第一个访问本网站的用户,赋值为1,否则在原来的计数上进行累加;

    ●JSP常用内置对象:

    内置对象名称

    说明

    out

    用于向客户端输出数据

    request

    主要用于处理客户端请求的数据信息

    response

    用于响应客户端请求并向客户端输出信息

    session

    用于记录会话状态的相关信息

    application

    类似于系统的全局变量,用于实现Web应用中的资源共享

    ●JSP的其他内置对象:

      ◆pageContext : 提供了在 JSP 运行时访问和其相关的环境信息的能力,通过 pageContcx对象可以访问和当前 JSP 页面相关联的所有作用域,以及一些页面属性;

      ◆pageContext 对象的常用方法:

        ☉ ServletRequest getRequest( ): 获得 request 对象

        ☉ ServletResponse getResponse () : 获得 response 对象

        ☉HttpSession getScssion(): 获得 session 对象

        ☉JspWriter getOut ): 获得 out 对象

        ☉void setAtMbute( ): 保存属性

        ☉Object getAttrubute (): 获得属性

        ☉void include( ): 请求指定的资源,并将目标资源的响应结果包含在调用页面的响应中。

      ◆page: 表示当前页面,类似于 Java 中的 this。在 JSP 页面中 ,很少使用 page 对象;

      ◆config: 用于存放 JSP 编译后的初始数据。 与 page 对象-样 , 在 JSP 页面中很少使用;

      ◆exception: 表示 JSP 页面运行时产生的异常和错误信息,该对象只有在错误页面(pag指令中设定 isErrorPage 为true的页面 ) 中才能够使用;

    2、 对象的作用域:

    分别是 page 作用域、request 作用域 、session 作用域和 application作用域;

      ▲page作用域:对应的作用域访问对象为pageContext 对象,在一个页面范围内有效,通过pageContext对象访问;

      ▲request作用域:对应的作用域访问对象为request 对象,在一个服务器请求范围内有效;

      ▲session作用域:对应的作用域访问对象为session 对象,在一次会话范围内容有效;

      ▲application作用域:对应的作用域访问对象为application 对象,在一个应用服务器范围内有效;

         

    ●page作用域:page 作用域指单一JSP页面的范围,page 作用域内的对象只能在创建该对象的页面中访问,page作用域可以使用 pageContext 对象的 setAttribute()和 getAttribute()方法访问,page 作用域在客户每次请求 JSP 页面时创建,在服务器发送响应或请求转发到其他的页面或资源后失效;

    eg:testOne.jsp代码:

    <html>

      <head> 

        <title>My JSP 'login.jsp' starting page</title>

      </head>

      <body>

        <%

          String name = "page";

          pageContext.setAttribute("name", name);

        %>

        <strong>

          testOne:<%=pageContext.getAttribute("name") %>

        </strong>

        <br/>

        <%

          pageContext.include("testTwo.jsp");

        %>

      </body>

    </html>

    eg:testTwo.jsp代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <strong>

        testTwo:<%=pageContext.getAttribute("name") %>

    </strong>

    运行结果:

     

    分析:在testOne .jsp 页面中,调用 pageContext 对象的 setAttribute ()方法将一个 String对象保存到 page 作用域,然后在本页面中调用 pageContext 对象的 getAttribute ( )方法可以访问到这个 String 对象,而在 testTwo.jsp页面中,也就是在另一个 page 作用域中,则无法访问到该 String对象,显示 "testTwo:null”, 当然 , 这个结果是通过 pageContext 对象的 include() 方法将 testTwo.jsp的响应结果包含到 testOne .jsp 页面中的;

    ● request作用域:page 作用域与当前页面绑定在一起 . 而 request 作用域则是与客户端的请求绑定在一起的 , 其用范围要比 page 作用域大 , request作用域可以通过调用 request 对象的 setAttribute ( ) 与 getAttribute()方法进行访问。request 作用域在页面转发或包含中同样有效,即在调用 RequestDlspatcher 的 forward ()方法转向的页面或者调用include() 方法包含的页面中,都可以共享同一个 request 作用域,访问其中的数据,需要注意的是,request 作用域对于每次客户端的请求都是不同的,对于任何一个新的请求都会重新创建与本次请求相对应的 request作用域。而当请求结束后,与之相关的 request 作用域也随之失效;

        ★RequestDlspatcher对象的include()方法与pageContext对象的include()方法与pageContext对象的include()方法实现相同的效果;

    eg:testOne.jsp代码:

    <html>

      <head> 

        <title>My JSP 'login.jsp' starting page</title>

      </head>

      <body>

        <%

           String name = "request";

           request.setAttribute("name", name);

           request.getRequestDispatcher("testTwo.jsp").forward(request, response);

        %>

      </body>

    </html>

    eg:testTwo.jsp代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <strong> testTwo:<%=request.getAttribute("name") %></strong>

    运行结果:  

     

    分析:在 testOne .jsp 页面中,通过 RaquestDispitcher 对象forward ( ) 方法转发至 testTwo.jsp, 属于一次请求,在同一个 request 作用域内,所以在 testTwo .jsp 页面中可以访问到这个 String 对象;

    ●session作用域:JSP 容器为每一次会话创建一个 session 作用域。在会话有效期内,只要将数据绑定到 session作用域中,则该数据可以被本次会话中的其他页面所访问。session 作用域可以通过 session 对象setAttribute ()和 getAttributet ()方法进行访问;

    eg:testOne.jsp代码:

    <html>

      <head> 

        <title>My JSP 'login.jsp' starting page</title>

      </head>

      <body>

    <%

        String req = "request";

        String ses = "session";

        request.setAttribute("reqName", req);

        session.setAttribute("sessionName", ses);

        response.sendRedirect("testTwo.jsp");

    %>

      </body>

    </html>

    eg:testTwo.jsp代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <strong>

        request:<%=request.getAttribute("reqName") %><br/>

        session:<%=session.getAttribute("sessionName") %>

    </strong>

    运行结果:  

     

    分析:分析:使用response对象将页面定向至testTwo.jsp,在testTwo.jsp中能够读取到sessionName变量,由此可见session作用域内的数据在会话有效期内都可以访问,使用response.sendRedirect()重定向到零一个界面,相当于重新发起了一次请求,所以在上一次请求中的reqName变量随之失效;

    ●application作用域:相对于 session 作用域针对一个会话,application作用域则针对整个 Web 应用,被该应用下所用户所共享。在 Web 应用运行期间,所有页面都可以访问application作用域内的变量,其作用域最大,application 作用域通过 application对象的 setAttribute ()和 getAttribute()方法访问;

    eg:testOne.jsp代码:

    <html>

      <head> 

        <title>My JSP 'login.jsp' starting page</title>

      </head>

      <body>

    <%

        String app = "application";

        String ses = "session";

        session.setAttribute("sesName", ses);

        application.setAttribute("appName", app);

        response.sendRedirect("testTwo.jsp");

    %>

      </body>

    </html>

    eg:testTwo.jsp代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <strong>

        session:<%=session.getAttribute("sesName") %><br/>

        application:<%=application.getAttribute("appName") %>

    </strong>

    运行结果:运行testOne.jsp页面的效果如下:

     

    此时会以一个新的会话开启另一个浏览器窗口,直接访问testTwo.jsp页面,

    页面显示如下信息:session:null

                      application:application

    分析: 由于session作用域针对当前会话,,多个会话之间不能共享,所以无法获取setName变量,而application作用域针对整个应用,因而appName变量可以被再次被读取到(注:若重启Web应用,现有的application作用域会消失);

    3、 cookie:是Web服务器保存在客户端的一系列文本信息;

    ●简介:cookie由Netscapt公司发明,是最常用的跟踪用户会话的方式,它是由服务器端生成并发送客户端浏览器的,浏览器会将其保存为某个目录下的文本文件;

    说明:

      ★当用户在浏览网站时,Web 服务器会将一些资料存放在客户端,这些资料包括用户在浏览网期间输入的文字或是一些选择记录。当用户下一次访问该网站时,服务器会先从客户端查看是否保留下来的 emkie 信息,然后依据 cookie 的内容,呈现特定的页面内容给用户。

          cookie 最典型的用是判定注册用户是否已经登录网站,用户可能会得到提示,是否保存状态以便在下一次进入系时可以简化登录。另外 cookie 还会应用到 '最近浏览过的商品’ 之类的业务处理中, 用户在购网站中浏览过不同的商品信息,都可以使用cookie在客户端进行存储,方便用户快速定位到已浏过的商品;

    ●cookie的作用表现:

       对特定对象的追踪,如访问者的访问次数、最后访问时间、路径等;

       统计网页浏览次数;

       在cookie有效期内,记录用户登陆信息;

       实现各种个性化服务,如针对不同用户喜好以不同的风格展示不同的内容等;

    ●注:由于cookie会将用户的个人信息保存在客户端,如用户名、计算机名、浏览记录等,这些信息中会包含一些比较敏感的内容,尤其是用户私人的信息。所以从安全角度上,使用cookie存在着一定的风险 , 因此不建议在cookie中保存比较重要或敏感的内容;

    在JSP中使用cookie:

      1、创建cookie对象:

           Cookie newCookie = new Cookie(String key, String value);

        注:Cookie 类在 javax.servlet.http包下,当 JSP 翻译成.java 文件时,会自动导入 java.servlet.http 的类。在JSP中,通过调用构造方法 Cookie(String name , String value)创建新的cookie 对象。// name: 用于代表 cookie 的名称,value: 用于表示该名称所对应的值

      2、写入cookie:

           在学习 JSP 内置对象 response 的常用方法时,有一个 addCookie ) 方法。在创建 cookie对象使用response 对象的 addCookie() 方法实现写入cookie;

            其代码:response.addCookie(newCookie);

            ★cookie对象的常用方法:

        方法名称

    说  明

    void setMaxAge(int expiry)

    设置cookie的有效期,以秒为单位

    void setValue(String value)

    在cookie创建后,为cookie赋予新的值

    String getName()

    获取cookie的名称

    String getValue()

    获取cookie的值

    int getMaxAge()

    获取cookie的有效时间,以秒为单位

                  eg:添加cookie信息:

    <html>

      <head>  

        <title>添加cookie</title>

      </head>

     

      <body>

        <%

              response.addCookie(new Cookie("username","Jack"));

              response.addCookie(new Cookie("password","123456"));

              response.sendRedirect("getCookies.jsp");

       %>

      </body>

    </html>

      3、读取cookie:Cookie[] cookies = request.getCookies();

           JSP 通过 response 对象的 addCookie()方法写cookie后,读取时需要调用 JSP 中 request 对象getCookies )方法 ,该方法将返回 HTTP请求中的cookie 对象数组 , 因此必须通过遍历的方式进访问;

             cookie 是通过 name/value 方式进行保存的 , 因而在遍历数组时,需要通过调用 cookie 对象getNarne ( ) 方法对每个数组成员的名称进行检查,直至找到我们需要的cookie,然后调用cookie对象 getValue方法取得与名称对应的值;

              eg:读取上面的(第二步)数据信息:

    <html>

      <head>

        <title>读取cookie</title>

      </head>

     

      <body>

        <%

              Cookie[] cookies = request.getCookies();

              String user="";

              String pwd = "";

              if(cookies!=null){

                     for(int i=0;i<cookies.length;i++){

                            if(cookies[i].getName().equals("username"))

                                   user = cookies[i].getValue();

                            else if(cookies[i].getName().equals("password"))

                                   pwd = cookies[i].getValue();

                     }

              }

              out.print("用户名:"+user+" ,密码: "+pwd);

       %>

      </body>

    </html>

      

    eg:验证 sessionid是否以 cookie 的形式存储在客户端,首先通过访问JSP页面创建会话 , 然后从 cookie 中读取 sessionid. 比较与通过 session 对象的 getld()方法取得的sessionid是否相同;

    eg:创建信息(create.jsp):

    <html>

      <head>  

        <title>添加cookie</title>

      </head>

     

      <body>

    <%

        session.setAttribute("test", "hello");

        response.sendRedirect("getCookie.jsp");

    %>

     

      </body>

    </html>

    eg:读取信息:

    <html>

      <head>

        <title>读取cookie</title>

      </head>

     

      <body>

    <%

        out.print("sessionid:" + session.getId());

        out.print("<br/>");

        Cookie[] cookies = request.getCookies();

        if (cookies != null) {

            for (int i=0; i<cookies.length; i++) {

                out.print("cookie name:" + cookies[i].getName());

                out.print("<br/>");

                out.print("cookie value:" + cookies[i].getValue());

                out.print("<br/>");

            }

        }

    %>

      </body>

    </html>

    分析:程序未向 cookie 对象中存储其他数据,如果此 cookie 对象不为null , 则只存储了 sessionid这条数据, 所以不需要判断, 调用 cookie 对象的 getName ()方法和 getValue ()方法就可将 sessionid 的名称和值取出来;

    结论:从上面输出结果中可以看出 , cookie 的值与 sesslonid 的值是一致的,这也说明了 sessionid被保存在 cookie 中;

    问题:在上面 create.jsp 页面中如果不使用 response进行重定向,而是使getRequestDispatcher() .forward(request,response) 为何看不到 cookie中的JSESSIONID?

    解答 : 因为使用 response对象的 sendRedirect()方法是将页面重定向到一个新的地址,在请求 getCookie.jsp 之前,服务器已经对上一个请求做出了响应,在客户端写入cookie。如果使用转发的形式,到达 getCookie.jsp前并没有返回响应,因而在客户端有没写入cookie。这时, 只要通过浏览器再次访问 getCookie.jsp 页面 (直接输入 URL地址访问) , 即可看到上次响应写入的 cookie;

    cookie 的有效期:

      ★当用户访问网页时,cookie 能够在客户端创建一个文件,用于记录用户的有关数据。但是一个cookie 在客户端存在的时间并不是无限期的,也有其生命周期,可以指定cookie的有效期 ,在由效期内cookie始终存在并能够被读取,当达到cookie 有效期后,cookie 会被从客户端清除;

      ★设置cookie有效期的方法是调用 cookie 对象的 setMaxAge (int expiry) 方法,其中参数 expiry代表cookie的有效时间 , 以秒为单位;

    eg:设置cookie的有效期为60秒:

    eg:info.jsp代码:

    <html>

      <head>  

        <title>添加cookie</title>

      </head>

     

      <body>

    <%

        Cookie nc=new Cookie("info", "ok");

        nc.setMaxAge(60); //设置Cookie失效前时间为60秒

        response.addCookie(nc);

        response.sendRedirect("showCookie.jsp");

    %>

     

      </body>

    </html>

    eg:showCookie.jsp代码:

    <html>

      <head>

        <title>读取cookie</title>

      </head>

     

      <body>

    <%

        Cookie[] cookies = request.getCookies();

        boolean sign = false; //标识

        if (cookies != null) {

            for (int i=0; i<cookies.length; i++) {

                if (cookies[i].getName().equals("info")) {

                    sign = true;

                    out.print("读取Cookie的值:" + cookies[i].getValue());

                }

            }

        }

        if (!sign) {

            out.print("超过Cookie有效期,无法读取Cookie");

        }

    %>

      </body>

    </html>

    分析:上面的示例,执行结果是为一个 cookie 变量设置了60 秒的有效期,在此期间内可以对该 cookie进行读取,一旦超过60 秒,将无法读取该ccokie 信息;

    注:使用setMaxAge(int expire)时,有下面的几种情况:

        通常情况下 expire参数应为大于0的整数,表示 cookie 的有效存活时间;

      ★如果设置 expire参数等于0 ,表示从客户端删除该 cookie;

      ★设置 expire参数为负数或者不设置 ,表示 cookie 会在当前窗口关闭后失效;

    4、  cookie与 session 作用域的对比:

    session 作用域

    cookie作用域

    在服务器端保存用户信息

    在客户端保存用户信息

    保存的值是 Object 类型

    保存的值是 String类型

    随会话的结束而将其存储的数据销毁

    可以长期保存在客户端

    保存重要的信息

    通常用于保存不重要的用户信息

    5、JDBC中访问数据库:

    ●使用JDBC访问数据库的步骤:

      1加载 JDBC 驱动,使用 Class.forName() 方法将给定的 JDBC 驱动类加载到Java虚拟机中,如果系统中不存在给定的类,则会引发 ClassNotFoundException异常;

      2、与数据库建立连接。DriverManager类是JDBC的管理层,作用于用户和驱动程序之间。DriverManager类跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立连接,当调getConnection ( ) 方法时,DriverManager 类首先从已加载的驱动程序列表中找到一个可以接受该库 URL 的驱动程序,然后请求该驱动程序,使用相关的URL、用户名和密码连接到数据库中,于是建立了与数据库的连接,创建连接对象并返回引用;

      3、发送 SQL 语句, 并得到返回结果。一旦建立连接, 就使用该连接创建 Statement接口的实例,并将 SQL 语句传递给它所连接的数据库,如杲是查询操作 , 将返回类型为 ResultSet 的结果集,其包含执行 SQL 查询的结果。如果是其他操作 , 将根据调用方法的不同返回布尔值或操作影晌的记录数目;

      4、处理返回结果,主要是针对查询操作的结果集,通过循环取出结果集中每条记录并做相的处理;

      5、数据库访问结束后,进行资源释放;

    JSP访问数据库:

      ◆分层实现:数据访问层(DAO):对数据库的增、删、改、查操作是数据访问层,

            表示层(JSP):JSP 是用户直接访问的,主耍是用获取客户的数据和显示数据,作为表示层;

      ◆DAO 模式的主要组成:

           DAO 接口:把对数据库的所有操作定义成抽象方法;

        ★DAO 实现类,给出 DAO 接口中定义方法的具体实现;

        ★实体类:用于存放. 传输对象数据;

        ★数据库连接和关闭工具类:对数据库连接和关闭代码进行集中管理,减少冗余;

    eg:下面通过完成新闻发布系统中的一个开发任务来具体了解在 JSP 中如何实现数据库访问,本务主要包括以下几个步骤:

      ◆新闻发布系统的数据库中包含一个和用户表,NEWS_USERS,表中包含用户编号(uid)、用户名称(uname)、用户密码(upwd)三个字段;

           

         ★1、了解需求:实现用户注册功能,在注册页面中输入用户名、密码,如上图(左), 单击 ’注册’ 按钮.数据保存至数据库中. 如果注册成功,跳转至登录页面,如图上图(右),如果注册失败,跳转至注册页面;

         ★2、准备环境:使用MySOL数据库实现数椐存储,因而需耍将 MySQL 的驱动包添加到项目的/WEB-INF/lib目录下;

         ★3、数据访问层:代码如下:

    在数据连接和关闭工具类BaseDao中封装对用户的增加、删除、修改i操作的关键代码如下:

    /**

     * 数据库连接与关闭工具类。

    */

    public class BaseDao {

        private static String driver = ConfigManager.getProperty("driver");// 数据库驱动字符串

        private static String url = ConfigManager.getProperty("url");// 连接URL字符串

        private static String user = ConfigManager.getProperty("user"); // 数据库用户名

        private static String password = ConfigManager.getProperty("password"); // 用户密码

     

        protected Connection conn;

     

        static {

            try {

                Class.forName(driver);

            } catch (ClassNotFoundException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

     

        /**

         * 获取数据库连接对象。

         */

        public Connection getConnection() {

            // 获取连接并捕获异常

            try {

                if (conn == null || conn.isClosed())

                    conn = DriverManager.getConnection(url, user, password);

            } catch (SQLException e) {

                e.printStackTrace();

            }

            return conn;// 返回连接对象

        }

     

     

        /**

         * 关闭数据库连接。

         * @param conn  数据库连接

         * @param stmt    Statement对象

         * @param rs 结果集

         */

        public void closeAll(Connection conn, Statement stmt, ResultSet rs) {

            // 若结果集对象不为空,则关闭

            try {

                if (rs != null && !rs.isClosed())

                    rs.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

            // 若Statement对象不为空,则关闭

            try {

                if (stmt != null && !stmt.isClosed())

                    stmt.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

            // 若数据库连接对象不为空,则关闭

            try {

                if (conn != null && !conn.isClosed())

                    conn.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

     

     

        /**

         * 增、删、改操作

         * @param sql sql语句

         * @param prams 参数数组

         * @return 执行结果

         */

        protected int executeUpdate(String sql, Object... params) {

            int result = 0;

            conn = this.getConnection();

            PreparedStatement pstmt = null;

            try {

                pstmt = conn.prepareStatement(sql);

                for (int i = 0; i < params.length; i++) {

                    pstmt.setObject(i + 1, params[i]);

                }

                result = pstmt.executeUpdate();

            } catch (SQLException e) {

                e.printStackTrace();

            } finally {

                closeAll(null, pstmt, null);

            }

            return result;

    }

     

     

        /**

         * 查询操作

         * @param sql   sql语句

         * @param params   参数数组

         * @return 查询结果集

         */

        protected ResultSet executeQuery(String sql, Object... params) {

            conn = this.getConnection();

            PreparedStatement pstmt = null;

            ResultSet rs = null;

            try {

                pstmt = conn.prepareStatement(sql);

                for (int i = 0; i < params.length; i++) {

                    pstmt.setObject(i + 1, params[i]);

                }

                rs = pstmt.executeQuery();

            } catch (SQLException e) {

                e.printStackTrace();

            }

            return rs;

        }

    }

    注意:executeUpdate()方法和executeQuery()方法中使用了形参“Object…params“,表示可变长参数,在调用此方法时,此形参位置可以传入若干个实参。在此方法中params 当数组使用。需要注意的是,一个方法中只能由一个这样的参数(可变长参數), 且只能放在参数列表的最后;

    用户实现类NewsUserImpl代码如下:

    public class NewsUserImpl extends BaseDao implements NewsUserDao {

        @Override

        public int findUser(NewsUser newsUser) {

            return 0;

        }

     

        @Override

        public int insert(NewsUser newsUser) {

            int result = 0;

            try {

                String sql = "INSERT INTO `NEWS_USERS`(`uname`, `upwd`) VALUES(?, ?)";

                result = this.executeUpdate(sql, newsUser.getUname(),

                        newsUser.getUpwd());

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                this.closeAll(conn, null, null);

            }

            return result;

        }

    }

        ★4、表示层:JSP代码:

    用户注册页面register.jsp代码:

      <html>

    <head>

    <title>用户注册</title>

    </head>

    <body>

           <form name="form1" method="post" action="control.jsp">

                  <table>

                         <tr>

                                <td>用户名:</td>

                                <td><input type="text" name="userName">

                                </td>

                         </tr>

                         <tr>

                                <td>输入登录密码:</td>

                                <td><input type="password" name="pwd"></td>

                         </tr>

                         <tr>

                                <td>再次输入密码:</td>

                                <td><input type="password" name="validatepwd"></td>

                         </tr>

                         <tr>

                                <td></td>

                                <td><input type="submit" value="注册"></td>

                         </tr>

                  </table>

           </form>

    <body>

    </html>

    登陆页面login.jsp代码:

    <html>

    <head>

    <title>用户登录</title>

    </head>

    <body>

           <form name="form1" method="post" action="">

                  用户名: <input type="text" name="userName">

                            密码: <input type="password" name="pwd">

            <input type="submit" value="登录">

           </form>

    </body>

    </html>

    控制页面control.jsp用于获取用户的输入,向数据库添加数据,并根据处理结果返回不同的页面,代码:

    <html>

        <head>

            <title>注册处理页面</title>

        </head>

        <body>

          <%

              request.setCharacterEncoding("UTF-8");

              String name = request.getParameter("userName");

              String pwd = request.getParameter("pwd");

              NewsUser newsUser = new NewsUser(name, pwd);

              int result = new NewsUserImpl().insert(newsUser);

              if (result > 0) {

                  response.sendRedirect("login.jsp");

              } else {

                   request.getRequestDispatcher("register.jsp")

                            .forward(request, response);

              }

          %>

        </body>

    </html>

    至此实现用户注册功能的编码任务就完成了,下面进一步完善此功能,增加两个要求:

      ▲第一,如果用户的注册信息未填写完整便提交,则需要给出验证提示,并且为了方便用户操作.要保留户已填写过的数据;

      ▲第二, 如果注册成功, 弹出 ’注册成功! 马上登录.' 的提示框;单击 ’确定’ 按钮后跳转至登录页面, 如果注册失败. 则给出相应的提示信息;

    分析:在实现第一个要求.即表单的信息验证时.不仅需要在客户端表单提交时进行数据验证,达用户体验好. 减轻服务器端压力的目的 . 同时也需要在服务器端进行验证. 因为如果用户设置浏览器禁止运行脚本代码,则客户端的验证会失效. 再如,此示例中,用户通过浏览器直接访问 control .jsp页面. 也能绕过客户端验证.鉴于安全性考虑.服务器端也要进行数据的验证.为了实现新增的功能,这里需要修改用户注册页面 register isp 和控制页面 control .jsp,修改后的代码如下:

    控制页面control.jsp用于获取用户的输入,向数据库添加数据,并根据处理结果返回不同的页面,代码:

    <html>

        <head>

            <title>注册处理页面</title>

        </head>

        <body>

          <%

              request.setCharacterEncoding("UTF-8");

              String name = request.getParameter("userName");

              String pwd = request.getParameter("pwd");

              String validatepwd = request.getParameter("validatepwd");

              if (name == null || name.equals("")) {

                  request.setAttribute("message", "用户名不能为空");

                  request.getRequestDispatcher("register.jsp").forward(request, response);

              } else if (pwd == null || pwd.equals("")) {

                  request.setAttribute("message", "密码不能为空");

                  request.getRequestDispatcher("register.jsp").forward(request, response);

              } else if (!validatepwd.equals(pwd)) {

                  request.setAttribute("message", "两次输入的密码不一致");

                  request.getRequestDispatcher("register.jsp").forward(request, response);

              } else {

                  NewsUser newsUser = new NewsUser(name, pwd);

                  int result = new NewsUserImpl().insert(newsUser);

                  if (result > 0) {

                      out.println("<script type='text/javascript'>"+"alert('注册成功!马上登录。');location.href='login.jsp';"+"</script>");

                  } else {

                      request.setAttribute("message", "注册失败,请重新注册。");

                      request.getRequestDispatcher("register.jsp") .forward(request, response);

                  }

              }

          %>

        </body>

    </html>

    用户注册页面register.jsp代码:

    <html>

        <head>

            <title>用户注册</title>

            <script type="text/javascript" src="js/news.js"></script>

        </head>

        <%

            //获取验证消息

            request.setCharacterEncoding("UTF-8");

            String message = (String) request.getAttribute("message");

        %>

        <body>

          <div id="mess" style="color:red;">

            <%=message != null && !message.equals("") ? message : "" %>

          </div>

          <form name="form1" method="post" action="control.jsp"

                onsubmit="return checkAll()">

          <table>

          <tr>

            <td>用户名:</td>

            <td><input type="text" name="userName" id="userName"

                    value='<%=request.getParameter("userName") == null ? ""

                            : request.getParameter("userName") %>'>

            </td>

          </tr>

          <tr>   

            <td>输入登录密码:</td>

            <td><input type="password" name="pwd" id="pwd"

                    value='<%=request.getParameter("pwd") == null ? ""

                            : request.getParameter("pwd") %>'>

            </td>

          </tr>

          <tr>

            <td>再次输入密码:</td>

            <td><input type="password" name="validatepwd" id="validatepwd"

                    value='<%=request.getParameter("validatepwd") == null ? ""

                            : request.getParameter("validatepwd") %>'>

            </td>

          </tr>

          <tr>

            <td></td>

            <td><input type="submit" value="注册"></td>

          </tr>

          </table>

          </form>

        <body>

    </html>

    说明:在控制页面 control.jsp 验证用户输入的信息时 , 使用 request.setAttribute()方法将验证信息存储到请求对象 request 中,并转发至用户注册页面 register.jsp。在 register.jsp 中,通过 request.getAttribute()方法获取验证信息并显示在div层中。在显示验证信息前,需考虑的是,如果用户第一次访问 reglster.jsp 页面,通过 request.getAttribute()方法获取的message为null,直接显示则会在页面出现 “null',所以要进行判断,便于代码简洁,这里使用三元运算符实现,其代码如下:

         <div id="mess" style="color:red;">

            <%=message != null && !message.equals("") ? message : "" %>

          </div>

    同时,将用户填写过的信息保留在注册页面中,实现思路与显示验证信息类似,显示数据前同样需要判断。例如,实现保留用户名的代码如下:

    <td><input type="text" name="userName" id="userName"

                    value='<%=request.getParameter("userName") == null ? "": request.getParameter("userName") %>'>

            </td>

    至此, 使用 JSP 连接数据库,实现用户注册功能已经完善. 运行程序观看结果;

    6、在JSP中使用 JavaBean:

    ●JavaBean的优势:

      ☉解决代码重复编写,减少代码冗余

      ☉功能区分明确

      ☉提高了代码的维护性

    JavaBean 是 Java 中开发的可以跨平台的重用组件.

    JavaBean 在服务器端的应用中表现出了强的生命力,在 JSP 程序中常用于封装业务逻辑、数据库操作等;

    JavaBean 组件本质上就是一个类,只是这个类需要遵循一些编码的约定;

    JavaBean 实际上是一个 Java 类 , 这个类可以重用。

        ★从 JavaBean 的功能上可以分为以下两类:封装数据、封装业务;

    JavaBean般情况下要满足以下要求:

      ★JavaBean 是一个公有类,并提供无参的公有的构造方法;

      ★属性私有;

      ★具有公有的访问属性的 getter 和 setter 方法;

        ☉符合上述条件的类,都可以把它看成 JavaBean 组件;

        ☉在程序中,开发人员所要处理的无非是业务逻辑和数据,而这两种操作都可以封装成 JavaBe组件. 一个应用程序中会使用很多 JavaBean,由此可见 , JavaBean 组件是应用程序的重要组成部分:

    eg:下面这段代码实际上就是实现用户登录时用于封装用户的实体类,这也是一个很典型的封装数据JavaBean。这个 JavaBean封装了用户所用的数据,uid、uname 等是用户的属性,外部通过 getter /setter方法可以对这些属性进行操作;

         

      ★使用工具自动生成getter/setter方法: Alt+Shift+S -> Generate Getters and Setters

    规范:Sun 推荐的属性命名规则为xxx的属性对应setXxx ()方法;

      ◆一般情况下,Java的属性变量都以小写字母开始,eg:name、userName 等;

      ◆但也存在殊的情况,如一些特定意义的大写英文缩略词(如 XML、URL 等).

      ◆JavaBean 也允许使大写字母开头的属性变量名,但是必须满足“变量的前两个字母要么全部大写,要么全部小写“的要求,

          eg:IDCode、ID、ICCard 等属性变量名是合法的,而 iDCode、 iD 、 iCCard等属性变量名则是非法的,

      ◆有些情况下非法的变量名再以属性名第一个字母大写的方式命名getter/setter方法,会导致找不到属性错误;

      ◆解决方法如下:

           如果属性名的第二个字母大写,那么该属性名直接用作 getter/setter 方法中 get/set后部分,就是说大小写不变。

            eg:属性名为 uName , 方法是 getuName/setuName

             如果前两个字母大写( 一般的专有名词和缩略词都会大写 ) 则属性名直接用作getter/setter方法,eg:属性名为URL, 方法是 getURL/ setURL;

             如果首宇母大写,则属性名直接用作 getter/setter方法中 get/set的后部分。例如:属性名为 Name,方法是 getName/setName,这是最不符合规范的情况,很容易发错误,因为通过 getter/setter方法得到的 默认属性名是name;

    在编写程序时一个封装数据的,JavaBean一般情况下对应着数据库内的一张表(或视图),JavaBean的属性与表(或视图)内字段的属性一一对应。同样 , 相对于一个封装数据的 JavaBean一般都会有一个封装该类的业务逻辑和业务操作的 JavaBean 相对应;

    7、JSP与JavaBean:

      ●在JSP页面中导入JavaBean:

        ★在 JSP 页面中,可以像使用普通类一样实例化一个 JavaBean 对象,调用它的方法。

        ★在 JSP 中引入并使用 JavaBdan 的语法如下:

    //引入JavaBean

    <%@ page import="org.news.bean.*" %>

    //使用JavaBean

    <%

        Comment c = new Comment();

        c.setCid(1014);

        c.getCauthor();

    %>

            ★代码提示:Alt+/

       ●访问JavaBean:

    访问JavaBean

    <jsp:useBean> 标签可以在JSP中声明一个JavaBean,然后使用。声明后,JavaBean对象就成了脚本变量,可以通过脚本元素或其他自定义标签来访问。<jsp:useBean>标签的语法格式如下:

    <jsp:useBean id="bean 的名字" scope="bean 的作用域" typeSpec/>

    其中,根据具体情况,scope的值可以是page,request,session或application。id值可任意只要不和同一JSP文件中其它<jsp:useBean>中id值一样就行了。

    接下来给出的是 <jsp:useBean> 标签的一个简单的用法:

    <%@ page language="java" contentType="text/html; charset=UTF-8"

        pageEncoding="UTF-8"%>

    <html>

    <head>

    <title>useBean 实例</title>

    </head>

    <body>

     

    <jsp:useBean id="date" class="java.util.Date" />

    <p>日期为:<%= date %>

     

    </body>

    </html>

    它将会产生如下结果:

    日期为:Tue Jun 28 15:22:24 CST 2016


    访问 JavaBean 对象的属性

    在 <jsp:useBean> 标签主体中使用 <jsp:getProperty/> 标签来调用 getter 方法,使用 <jsp:setProperty/> 标签来调用 setter 方法,语法格式如下:

    <jsp:useBean id="id" class="bean 编译的类" scope="bean 作用域">

       <jsp:setProperty name="bean 的 id" property="属性名" 

                        value="value"/>

       <jsp:getProperty name="bean 的 id" property="属性名"/>

       ...........

    </jsp:useBean>

    name属性指的是Bean的id属性。property属性指的是想要调用的getter或setter方法。

    8、Jsp中EL(Expression Language)基础详解:

    为了使JSP写起来更加简单。表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法。

    JSP EL语言定义

    E L(Expression Language)目的:为了使JSP写起来更加简单。

    表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法。它是一种简单的语言,基于可用的命名空间(PageContext 属性)、嵌套属性和对集合、操作符(算术型、关系型和逻辑型)的访问符、映射到 Java 类中静态方法的可扩展函数以及一组隐式对象。

    EL 提供了在 JSP 脚本编制元素范围外使用运行时表达式的功能。脚本编制元素是指页面中能够用于在 JSP 文件中嵌入 Java 代码的元素。它们通常用于对象操作以及执行那些影响所生成内容的计算。JSP 2.0 将 EL 表达式添加为一种脚本编制元素。

    一、JSP EL简介

    1、语法结构

    ${expression}

    2、[ ]与.运算符

    EL 提供"."和"[ ]"两种运算符来存取数据。

    当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用"[ ]"。例如:

    ${user.My-Name} 应当改为${user["My-Name"]}

    如果要动态取值时,就可以用"[ ]"来做,而"."无法做到动态取值。例如:

    ${sessionScope.user[data]}中data 是一个变量

    3、变量

    EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为username的变量。

    因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、Application范围查找。

    假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,就回传null。

    属性范围

    EL中的名称

    Page 

    PageScope

    Request   

    RequestScope

    Session

    SessionScope

    Application

    ApplicationScope

    二、JSP EL 中的有效表达式

    有效表达式可以包含文字、操作符、变量(对象引用)和函数调用。我们将分别了解这些有效表达式中的每一种:

    1、文字

    JSP 表达式语言定义可在表达式中使用的以下文字:

    文字

    文字的值

    Boolean

    true 和 false

    Integer

    与 Java 类似。可以包含任何正数或负数,例如 24、-45、567

    Floating Point

    与 Java 类似。可以包含任何正的或负的浮点数,例如 -1.8E-45、4.567

    String

    任何由单引号或双引号限定的字符串。对于单引号、双引号和反斜杠,使用反斜杠字符作为转义序列。

    必须注意,如果在字符串两端使用双引号,则单引号不需要转义。

    Null

    null

    2、操作符

    JSP 表达式语言提供以下操作符,其中大部分是 Java 中常用的操作符:

    术语

    定义

    算术型

    +、-(二元)、*、/、div、%、mod、-(一元)

    逻辑型

    and、&&、or、||、!、not

    关系型

    ==、eq、!=、ne、、gt、<=、le、>=、ge。

    可以与其他值进行比较,或与布尔型、字符串型、整型或浮点型文字进行比较。

    空操作符是前缀操作,可用于确定值是否为空。

    条件型

    A ?B :C。根据 A 赋值的结果来赋值 B 或 C。

    3、隐式对象

    JSP 表达式语言定义了一组隐式对象,其中许多对象在 JSP scriplet 和表达式中可用:

    pageContext

    JSP 页的上下文。它可以用于访问 JSP 隐式对象,如请求、响应、会话、输出、servletContext 等。

    例如,${pageContext.response} 为页面的响应对象赋值。

    此外,还提供几个隐式对象,允许对以下对象进行简易访问:

    术语

    定义

    param

    将请求参数名称映射到单个字符串参数值(通过调用 ServletRequest.getParameter (String name) 获得)。

    getParameter (String) 方法返回带有特定名称的参数。表达式 $(param.name) 相当于 request.getParameter (name)。

    paramValues

    将请求参数名称映射到一个数值数组(通过调用 ServletRequest.getParameter (String name) 获得)。

    它与 param 隐式对象非常类似,但它检索一个字符串数组而不是单个值。表达式 ${paramvalues.name) 相当于 request.getParamterValues(name)。

    header

    将请求头名称映射到单个字符串头值(通过调用 ServletRequest.getHeader(String name) 获得)。

    表达式 ${header.name} 相当于 request.getHeader(name)。

    headerValues

    将请求头名称映射到一个数值数组(通过调用 ServletRequest.getHeaders(String) 获得)。

    它与头隐式对象非常类似。表达式 ${headerValues.name} 相当于 request.getHeaderValues(name)。

    cookie

    将 cookie 名称映射到单个 cookie 对象。向服务器发出的客户端请求可以获得一个或多个 cookie。

    表达式 ${cookie.name.value} 返回带有特定名称的第一个 cookie 值。如果请求包含多个同名的 cookie,则应该使用 ${headerValues.name} 表达式。

    initParam

    将上下文初始化参数名称映射到单个值(通过调用 ServletContext.getInitparameter(String name) 获得)。

    除了上述两种类型的隐式对象之外,还有些对象允许访问多种范围的变量,如 Web 上下文、会话、请求、页面:

    术语

    定义

    pageScope

    将页面范围的变量名称映射到其值。

    例如,EL 表达式可以使用 ${pageScope.objectName} 访问一个 JSP 中页面范围的对象,

    还可以使用 ${pageScope.objectName.attributeName} 访问对象的属性。

    requestScope

    将请求范围的变量名称映射到其值。该对象允许访问请求对象的属性。

    例如,EL 表达式可以使用 ${requestScope.objectName} 访问一个 JSP 请求范围的对象,

    还可以使用 ${requestScope.objectName.attributeName} 访问对象的属性。

    sessionScope

    将会话范围的变量名称映射到其值。该对象允许访问会话对象的属性。

    例如:${sessionScope.name} 

    applicationScope

    将应用程序范围的变量名称映射到其值。该隐式对象允许访问应用程序范围的对象。

    三、特别强调:

    1、注意当表达式根据名称引用这些对象之一时,返回的是相应的对象而不是相应的属性。例如:即使现有的 pageContext 属性包含某些其他值,${pageContext}也返回 PageContext 对象。

    2、 注意 <%@ page isELIgnored="true" %> 表示是否禁用EL语言,TRUE表示禁止.FALSE表示不禁止.JSP2.0中默认的启用EL语言。

    四、举例说明

    1、例如,

    <%=request.getParameter("username")%>      等价于       ${param.username}

    2、例如,但是下面的那句EL语言可以完成如果得到一个username为空,则不显示null,而是不显示值。

     

    <%=user.getAddr()%>      等价于     ${user.addr}。

    3、例如:

    <%=request.getAttribute("userlist")%>     等价于    ${ requestScope.userlist }

    4、例如,原理如上例3。

    ${sessionScope.userlist}             1

    ${requestScope.userlist}             2

    ${applicationScope.userlist}         3 

    ${pageScope.userlist}             4

    ${uselist}:执行顺序为4 1 2 3。

    "."后面的只是一个字符串,并不是真正的内置对象,不能调用对象。

    5、例如,

    <%=user.getAddr()%>     等价于     ${user.addr}

    第一句前面的user,为一个变量。

    第二句后面user,必须为在某一个范围里的属性。

     

    EL即Expression Language(表达式语言)
    EL的语法:${ EL exprission }
    ${ bean.name } 或 ${ bean['name'] }
    说白了,EL是用来显示数据的,功能跟<%=表达式%> 一样,EL是不需要引入什么东西的
    JSTL(JavaServerPages Standard Tag Library)JSP标准标签库
    JSTL标准标签库包括核心标签库和SQL标签库,核心标签库常用的是if和forEach
    说白了JSTL常实现网页逻辑判断和迭代显示的,需要引入<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>只要JSTL和EL结合,就基本可以让页面再无<% %> jsp代码了。

  • 相关阅读:
    菜鸡的Java笔记 第十六
    菜鸡的Java笔记 第十五 this 关键字
    php 数组(2)
    菜鸡的Java笔记 第十四 String 类常用方法
    菜鸡的Java笔记 第十三 String 类的两种实例化方法
    菜鸡的Java笔记 第十二
    php 递推 递归
    bzoj2306 [Ctsc2011]幸福路径
    bzoj3712 [PA2014]Fiolki
    bzoj2958 序列染色
  • 原文地址:https://www.cnblogs.com/HQING/p/9530751.html
Copyright © 2020-2023  润新知