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代码了。

posted @ 2018-08-24 16:43  逆風〠飛翔  Views(1214)  Comments(0Edit  收藏  举报