随笔-159  评论-114  文章-7  trackbacks-0



public   class  ValidatorPlugIn
    
implements  PlugIn
{
.

    
public  String getPathnames()
    
{
        
return  pathnames;
    }


    
public   void  setPathnames(String pathnames)
    
{
        
this .pathnames  =  pathnames;
    }



    
public   void  init(ActionServlet servlet, ModuleConfig config)
        
throws  ServletException
    
{
        
this .config  =  config;
        
this .servlet  =  servlet;
        
try
        
{
            initResources();
        
catch (Exception e)
        
{
            log.error(e.getMessage(), e);
            
throw   new  UnavailableException( " Cannot load a validator resource from ' "   +  pathnames  +   " ' " );
        }

    }


    
protected   void  initResources()
        
throws  IOException, ServletException
    
{
        
if (pathnames  ==   null   ||  pathnames.length()  <=   0 )
            
return ;
        StringTokenizer st 
=   new  StringTokenizer(pathnames,  " , " );
        List streamList 
=   new  ArrayList();
        
try
        
{
            
while (st.hasMoreTokens()) 
            
{
                String validatorRules 
=  st.nextToken().trim();
                
if (log.isInfoEnabled())

.

}

学习Java Web 技术,首先必须先把Servlet搞明白。没有Servlet基础,别的都是扯淡!

主要就是掌握Servlet的生命周期,所关联到的类,以及他们的方法。

我简要回顾一下

打开Servlet-API

Servlet接口,三个关乎生命周期的重要方法签名

                  ServletConfig,是一个较重要的对象。

                                          功能:1,获得初始化参数
                                                   2,获得Servlet上下文对象。public ServletContextgetServletContext()

GeneralServlet抽象类,等待你去重写service方法。

                  功能主要就是,为程序员编写Servlet提供一些方便
                                          方便:1,直接覆盖public void init() throws ServletException 
                                                   2,直接调用getInitParameter(java.lang.String name) 
                                                         直接调用public ServletContextgetServletContext()
                                                         直接调用public void log(java.lang.String msg)

                                                         因为GeneralServlet是个懒家伙,都委托给相应ServletConfig/ServletContext完成功能


HttpServlet没什么,自己看API吧

ServletRequest能做什么,几件事

                                             事情1: public java.lang.Object getAttribute(java.lang.String name)/////还有set
                                             事情2: public java.lang.String getParameter(java.lang.String name)
                                                                                        两方面参数,
                                                                                                      方面1:html表单中,有name属性的值.
                                                                                                                  eg. <input type="text" name="userid" size="20" maxlength="20" />
                                                                                                                         request.getParameter("userid");
                                                                                                      方面2:地址栏参数,eg. http://www.infogo.com.cn/action.do?name=admin
                                                                                                                          request.getParameter("name");
                                                           
                                                          由于参数的值有时会是一组,那么就要用public java.lang.String[] getParameterValues(java.lang.String name)
 eg.
   ====================================================
   <c:forEach items="${cart.cartItem}" var="item">
  <TR align=middle>
    <TD height=30><INPUT type=checkbox value="${item.value.product.id}" name=item></TD>
    <TD height=30>${item.value.product.name}&nbsp;</TD>
    <TD height=30>${item.value.product.price}&nbsp;</TD>
    <TD height=30><INPUT maxLength=10 size=10 value="${item.value.number}" name=itemnum></TD>
    <TD height=30>${item.value.cost}&nbsp;</TD>
  </TR>
  </c:forEach>
    ====================================================

//获得页面,checkbox组的信息,可以知道用户选择的商品
  String[] itemkeystr = request.getParameterValues("item");
  System.out.println(itemkeystr);
                Integer[] itemkeyigr = new Integer[itemkeystr.length];
                for(int i = 0; i < itemkeystr.length; i++)
                {
                        itemkeyigr[i] = Integer.valueOf(itemkeystr[i]);
                }
================================================

                                                                                  事情3:public RequestDispatchergetRequestDispatcher(java.lang.String path)
                                                                                  事情4:public void setCharacterEncoding(java.lang.String env)
                          throws java.io.UnsupportedEncodingException
eg.主要防止用户在表单中输入了中文。

过滤器实例:

public   final   class  CharacterEncodingFilter  implements  Filter
{
    
private  String  encoding  =   " gb2312 " ;

    
private   boolean  ignore    =   false ;

    
public   void  init(FilterConfig config)
    
{
        
if  (config.getInitParameter( " encoding " !=   null )
        
{
            encoding 
=  config.getInitParameter( " encoding " );
        }


        
if  (config.getInitParameter( " ignore " !=   null )
        
{
            ignore 
=   new  Boolean(config.getInitParameter( " ignore " )).booleanValue();
        }


    }


    
public   void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  throws  IOException,
            ServletException
    
{
        HttpServletRequest req 
=  (HttpServletRequest) request;
        HttpServletResponse res 
=  (HttpServletResponse) response;

        
if  ( ! ignore)
        
{
            req.setCharacterEncoding(encoding);
            res.setCharacterEncoding(encoding);
        }


        chain.doFilter(request, response);
    }


    
public   void  destroy()
    
{

    }

}


ServletResponse,就是负责输出呗。

                                                                              负责1:  public void setContentType(java.lang.String type) 
                                                                                            eg. response.setContentType(text/html;charse=gbk)
                                                                              负责2:  public java.io.PrintWriter getWriter() throws java.io.IOException
                                                                              这里注意
                                                                            1必须先设置setContextType或者setCharacterEncoding,再获得输出。否则设置编码无效!
                                                                            2不得在ResquestDispatcher.forward()调用前,进行向客户端的输出。有风险。
                                                                              


ServletContext整个应用只有一个实例,可以为应用放置一些只读的共享数据。

责任1:public java.lang.String getInitParameter(java.lang.String name)
责任2:public RequestDispatchergetRequestDispatcher(java.lang.String path)绝对路径
责任3:public void log(java.lang.String msg)


Filter接口,实现对于某一个url匹配的过滤。是一个责任链模式的应用

package  ljl.shop.common;

import  java.io.IOException;
                                                                                                               
import  javax.servlet.Filter;
import  javax.servlet.FilterChain;
import  javax.servlet.FilterConfig;
import  javax.servlet.ServletException;
import  javax.servlet.ServletRequest;
import  javax.servlet.ServletResponse;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;


/**
 * 权限过滤器 通过配置web.xml中的filter初始化参数,实现动态判别
 * 
 *  <filter-mapping>
 *       <filter-name>CharacterEncodingFilter</filter-name>
 *       <url-pattern>/*</url-pattern>
 *   </filter-mapping>                                                                            
 *
 *   <filter>
 *       <filter-name>PermissionFilter</filter-name>
 *       <filter-class>ljl.shop.common.PermissionFilter</filter-class>
 *       <init-param>
 *               <param-name>checkpage</param-name>
 *               <param-value>checkout.jsp#order_created.jsp#postLogin.jsp</param-value>
 *       </init-param>
 *   </filter>
 * 
 * 
@author  lujl
 
*/

public   class  PermissionFilter  implements  Filter
{
    
private  String checkpage  =   null ;

    
private  FilterConfig config  =   null ;

    
public   void  init(FilterConfig config)
    
{
        System.out.println(config.getInitParameter(
" checkpage " ));
        
if (config.getInitParameter( " checkpage " !=   null )
        
{
            System.out.println(config.getInitParameter(
" checkpage " ));
            
// vip.jsp#checkout.jsp#
            checkpage  =  config.getInitParameter( " checkpage " );            
        }

        
this .config  =  config;
    }


    
public   void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  throws  IOException,ServletException
    
{
        HttpServletRequest hrequest 
=  (HttpServletRequest)request;
        String path 
=  hrequest.getServletPath();
        String[] pages 
=  checkpage.split( " # " );
        System.out.println(pages.length);
        
for ( int  i  =   0 ; i  <  pages.length; i ++ )
        
{
            
if (path.indexOf(pages[i])  !=   - 1 ) // 解析的path包含这些页面,那么就检查是否登录
             {
                
if (hrequest.getSession().getAttribute( " user " !=   null )
                
{
                    chain.doFilter(request, response);
                    
return ;
                }

                
else
                
{
                    
this .config.getServletContext().getRequestDispatcher( " /login.jsp " ).forward(request,response);
                    
return ;
                }

            }

            
        }

        chain.doFilter(request,response);    
    }


    
public   void  destroy()
        
{
                                                                                                               
        }

}


===========================================================================     

HttpServletRequest

还有一些Http协议的特征方法

public Cookie[] getCookies()

public java.lang.String getPathInfo()                 http://www.infogo.com.cn/webapp/servlet/aaa
                                                                                 如果url-pattern是/servlet/*         那么request.getPathInfo() 返回 /aaa

public java.lang.String getContextPath()         
                                                                                 /webapp
                                                                                 jsp el  也可以取到此值    ${pageContext.request.contextPath}
                                                                                 也就是<%=request.getContextPath()%>
public java.lang.String getQueryString()
                                                                                 只拿到地址栏参数字符串,自己解析吧:)

public java.lang.String getServletPath()
                                                                                 /servlet

public HttpSessiongetSession(boolean create)

                                                                                 传入true,如果有,直接返回,没有创建        等同于getSession()无参
                                                                                 传入false,没有则返回null
request.getRequestURI()                     /WebTest/servlet/MethodServlet
request.getRequestURL()                    http://localhost:8080/WebTest/servlet/MethodServlet 

URI是一个相对的位置,或者说就是一个标识,URL是资源定位,所以很精确。

HttpServletResponse

public void addCookie(Cookie cookie)

public java.lang.String encodeURL(java.lang.String url)         URL回写机制,说白了就是把jsessionid放在连接里,下回请求时就能穿回来了,不在需要Cookie了。注意,如果浏览器支持Cookie,无效果!!!

public java.lang.String encodeRedirectURL(java.lang.String url)      用于response.sendRedirect()函数中。


最后一招:
public void sendError(int sc)  throws java.io.IOException  

把API上面的静态常量往里放!

+++++++++++++++++++++++

public boolean isRequestedSessionIdValid()   待使用

+++++++++++++++++++++++
--------------------------------------------------------------

HttpSessionListener

public void sessionCreated(HttpSessionEvent se)

做JSP开发时,由于Session是在用户访问jsp时,自动创建的。如果能在用户一访问就往Session中放入一个容器对象呢,而不是在用户发出某一个特定Action请求时,再判断,再setAttribute();

那么就用Listener吧,这时使用是一个完全充分的理由。[还有ServletContextListener]

public void sessionDestroyed(HttpSessionEvent se)   基本可以统计用户在线时间。

或者做考试系统时,会使用到。

====================================

HttpSessionAttributeListener监听Session

HttpSessionBindingListener监听被session的setAttribute方法加入的对象。

实现接口的类型不同!!注意区分。

====================================

HttpServletResponseWrapper

是个适配器。

在制作一个filter的时候,如果想在原有的输出,某部分,添加一部分内容,必须对HttpServletResponse进行适配。

MyResponse myRes = new MyResponse(response);
chain.doFilter(request,myRes);
String contents = myRes.toString();
//解析字符串,比如寻找</body>

myRes.getResponse().getWriter();//取回原来的response          ServletResponseWrapper有个有参的构造方法。
//真正输出


public class MyResponse extends HttpServletResponseWrapper
{
      
      MyResponse(ServletResponse res)
      {
            super(res);
      }

      public PrintWriter getWriter()
      {
            return new PrintWriter(caw);
      }
      
      private CharArrayWriter caw = new CharArrayWriter();//IO 我就不废话了,也就是一个内存中的字符输出流。

      public String toString()
      {
            return caw.toString();
      }
}


================================================================================

 HttpSession接口

public void setMaxInactiveInterval(int interval)

<session-config>
<session-timeout>30</session-timeout>
</session-config>

public void invalidate()

public boolean isNew(),就是创建后,还没让客户端知道呢!


-----------------------------


JSP

就是一个Servlet

<%
      !
%>  

定义那个Servlet的成员

 <%!class ABC{}%>定一个类都没有问题!

表达式

<%=request.getParameter("user")%>                     

代码段

<%

%>

指令

<% @page errorPage="relativeURL"%>
<% @page isErrorPage="true"%>
<% @page contextType="text/html;charset=gb2312" %>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

动作

http://java.sun.com/products/jsp/syntax/2.0/syntaxref20.html

<jsp:include page="scripts/login.jsp">
   <jsp:param name="username" value="jsmith" />
</jsp:include>


<jsp:forward page="/servlet/login">
   <jsp:param name="username" value="jsmith" />
</jsp:forward>

================

<tt:screen id="/bookcatalog">
   <tt:parameter name="title" direct="true">
      <jsp:attribute name="value" >
         <fmt:message key="TitleBookCatalog"/>
      </jsp:attribute>
   </tt:parameter>
...
</tt:screen>

注意,也就是<tt:parameter这个标签,还有一个属性就是value,那么它的值是通过变化取得。

jsp先回把html,翻译成为xml的标准试图,再使用一个引擎翻译成为java代码。

<jsp:element name="h1">
   <jsp:attribute name="align">
      center
   </jsp:attribute>
   <jsp:body>
      This is the header!
   </jsp:body>
</jsp:element>

您把这段代码放入jsp,可以通过的。

<h1 align="center">
       This is the header!
</h1>                    






<%
Person p = null;
synchronized(application){
   p = (Person)application.getAttribute("person");
   if(p==null)
   {
         p = new Person();
         application.setAttribute("person",p);   
   }
}
%>

通用一些

Class.forName("com.infogo.bean.Person").newInstance();

<jsp:useBean id="p" class="com.infogo.bean.Person" scope="application" />  scope默认为page

这就是useBean指令做的事情。



<jsp:useBean id="persons" type="java.util.Collection" scope="request" />

注意type就是只说明它是什么类型的,不做实例化的步骤

MVC中的视图,就是使用集合bean的。如果不存在,会抛异常。bean persons not found within scope


<jsp:getProperty name="p" property="name" />


Stores all of the values of request parameters in bean properties. The names of the bean properties must match the names of the request parameters. A bean property is usually defined by a variable declaration with matching getter and setter methods (for more information, see http://java.sun.com/products/javabeans/docs/).

<jsp:setProperty name="mybean" property="*" />	
<jsp:setProperty name="mybean" property="username" />	
<jsp:setProperty name="mybean" property="username" value="Steve" />


====================================

先来说说,JSTL和EL的东西

Sun专门定制了一组标签库来完成页面的程序流程控制,避免了代码片断的出现。而EL则避免了页面出现表达式,而且对于attribute中的数据的非空验证是自动完成。如果为空,只会出现没有输出内容。

EL还是比较简单的。

http://java.sun.com/products/jsp/syntax/2.0/syntaxref207.html#1010522

上面是sun的教程。

=====================================

在说标签和EL原理之前,必须把JSP的原理搞清楚。

客户端请求jsp,由一个翻译引擎对jsp进行java代码的翻译,然后由容器进行编译,加载到容器,invoke Servlet。

一个jsp

<% @ page language = " java "  import = " java.util.* "  pageEncoding = " UTF-8 " %>
<% @ page info = " view jsp translate " %>
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
< html >
  
< head >
    
    
< title > View Jsp Translation </ title >
    
    
< meta  http-equiv ="pragma"  content ="no-cache" >
    
< meta  http-equiv ="cache-control"  content ="no-cache" >
    
< meta  http-equiv ="expires"  content ="0" >
    
< meta  http-equiv ="keywords"  content ="keyword1,keyword2,keyword3" >
    
< meta  http-equiv ="description"  content ="This is my page" >
    
  
</ head >
  
  
< body >
    This is my JSP page. 
< br >
  
</ body >
</ html >

对应代码

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class ViewJspTranslate_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

//这就是page指令生成的
  public String getServletInfo() {
    return "view jsp translate";
  }

  private static java.util.Vector _jspx_dependants;

  public java.util.List getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

//内置对象
    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
//使用page 指令中 Session=false,就不会出现session变量了,提高一些效率,注意只是不出现该引用。一访问jsp/Session就创建了。只能通过SessionListener进行创建时的截获,放置一些初始对象。
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;

//关键的JSP上下文对象
    PageContext _jspx_page_context = null;


    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");
      out.write("
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("
<html>\r\n");
      out.write("  
<head>\r\n");
      out.write("    \r\n");
      out.write("    
<title>View Jsp Translation</title>\r\n");
      out.write("    \r\n");
      out.write("    
<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
      out.write("    
<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
      out.write("    
<meta http-equiv=\"expires\" content=\"0\">\r\n");
      out.write("    
<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
      out.write("    
<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
      out.write("    \r\n");
      out.write("  
</head>\r\n");
      out.write("  \r\n");
      out.write("  
<body>\r\n");
      out.write("    This is my JSP page. 
<br>\r\n");
      out.write("  
</body>\r\n");
      out.write("
</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

所以如果发生编译不过,就到tomcat的work目录里看看java代码,比较容易看到错误。jsp的提示对于严重的语法错误是不太友好的。


对于隐含对象,就可以直接使用了。
<%=request.getContextPath()%>

<%=request.getInitParameter("user")%>

对于JSP也可以配置初始化参数。

web.xml对于JSP进行部署
<servlet>
   <servlet-name>some name</servlet-name>
   <jsp-file>/internal/config.jsp</jsp-file>
</servlet>

<servlet-mapping>
   <servlet-name>some name</servlet-name>
   <url-pattern>/internal/config.jsp</url-pattern>
</servlet-mapping>

url-pattern如果配置与jsp路径不一样,那么只有从这个pattern访问的jsp才能获得初始化参数。直接访问jsp的没有。
=========================


继续使用PageContext,可以得到很多信息。

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page info="view jsp translate"%>
<jsp:useBean id="client" class="com.bean.SthBizBean" scope="page">
    
<jsp:setProperty name="client" property="currentPage" value="<%=pageContext%>"/>
</jsp:useBean>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  
<head>
    
    
<title>View Jsp Translation</title>
    
    
<meta http-equiv="pragma" content="no-cache">
    
<meta http-equiv="cache-control" content="no-cache">
    
<meta http-equiv="expires" content="0">
    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    
<meta http-equiv="description" content="This is my page">
    
  
</head>
  
  
<body>
    Client Info:
<jsp:getProperty name="client" property="clientInfo" />
  
</body>
</html>

 

package com.bean;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.PageContext;

public class SthBizBean {

    PageContext pctx 
= null;

    
public void setCurrentPage(PageContext pctx) {
        
this.pctx = pctx;
    }


    
public String getClientInfo() {
        StringBuffer buf 
= new StringBuffer();
        ServletRequest request 
= pctx.getRequest();
        buf.append(
"<br>协议:" + request.getProtocol() + "<br>").append(
                
"地址:" + request.getRemoteAddr() + "<br>").append(
                
"端口:" + request.getRemotePort());
        
return buf.toString();
    }


}

==========================

java.lang.Object
  extended byjavax.servlet.jsp.JspContext
      extended byjavax.servlet.jsp.PageContext

去查看一下PageContext这个父类型。

public abstract java.lang.Object findAttribute(java.lang.String name)
Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.

看好这个方法是试图从四个范围内取值,如果都取不到,就会返回null。

public abstract void removeAttribute(java.lang.String name)

去除所有的属性值。

可以单独设置,作用范围

public abstract void removeAttribute(java.lang.String name,
                                     int scope)

就是用子类PageContext设置的常量。

============================================================

可以自己写自定义标签完成复杂的页面表现功能。

直接使用JSTL就行了。

=======================

JSTL配置EL,就可以使得JSP开发人员与JavaBean业务实现人员完全独立工作。测试也可以独立进行。

因为使用EL语言,不再需要<jsp:useBean>指令来设置一个JavaBean的对象到某一个范围内,并设置一个变量。

使用EL,直接可以使用Attribute了。

${user.name}

等价于

判断是否为空
<%=user.getName()%>

而且不需要判断user是否为空。

---------

EL有很多内嵌对象,当然只限制于在EL表达式中使用。

${pageContext.request.contextPath}

看到按照JAVABEAN命名的好处了吧,都可以按照标准命名去取值的。多方便。

参数

<c:if test=""${!empty param.username}">
      do sth
</c:if>

访问javabean

${bean1.a.c}

相当于

<%=bean1.getA().getC()%>

注意getA()方法本身就是返回一个javabean对象,所以可以继续javabean访问。



对于集合对象,Map对象。

访问可以通过另外的方式访问。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="com.bean.UserBean"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

Map userMap 
= new HashMap();
UserBean user_a 
= new UserBean();
user_a.setName(
"ljl");
user_a.setAddress(
"bj");
UserBean user_b 
= new UserBean();
user_b.setName(
"superman");
user_b.setAddress(
"Mars");

userMap.put(
"ua",user_a);
userMap.put(
"ub",user_b);

request.setAttribute(
"userMap",userMap);

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  
<head>
    
<base href="<%=basePath%>">
    
    
<title>My JSP 'ViewEL.jsp' starting page</title>
    
    
<meta http-equiv="pragma" content="no-cache">
    
<meta http-equiv="cache-control" content="no-cache">
    
<meta http-equiv="expires" content="0">
    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    
<meta http-equiv="description" content="This is my page">
    
    
<!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    
-->
  
</head>
  
  
<body>
    This is my JSP page. 
<br>
    
    ${"${userMap.ua}"}: ${userMap.ua}
    
<br>
    ${'${userMap["ua"]}'}: ${userMap["ua"]}
  
</body>
</html>

结果:

This is my JSP page.
${userMap.ua}: com.bean.UserBean@21af3d5
${userMap["ua"]}: com.bean.UserBean@21af3d5

-----------

        
    ${userMap["ub"].name} 
    ${userMap["ub"].address}

直接访问属性

这只是一种简单的情况,有时做应用并不是这样。

====================

 代码示例:

  <c:forEach items="${cart.cartItem}" var="item">
  <TR align=middle>
    <TD height=30><INPUT type=checkbox value="${item.value.product.id}" name=item></TD>
    <TD height=30>${item.value.product.name}&nbsp;</TD>
    <TD height=30>${item.value.product.price}&nbsp;</TD>
    <TD height=30><INPUT maxLength=10 size=10 value="${item.value.number}" name=itemnum></TD>
    <TD height=30>${item.value.cost}&nbsp;</TD>
  </TR>
  </c:forEach>

以上为一个购物篮的页面的部分代码:

这设计时。Cart类 有一个HashMap集合保存着选购的Item。key为产品Id,而value是页面需要展示的东西。

是一个个Item对象。

对于key为Id,或者页面不关心,甚至根本不知道是什么的HashMap如何遍历呢?

EL,和JavaBean的完美组合再次让我理解JavaBean的封装性的好处。

java.util
Interface Map.Entry<K,V>

A map entry (key-value pair). The Map.entrySet method returns a collection-view of the map, whose elements are of this class.

也就是说Map里每一个元素是一个一个的Entry。

再看看Entry方法。

 KgetKey()
          Returns the key corresponding to this entry.
 VgetValue()
          Returns the value corresponding to this entry.

哈哈,javabean规范!

${item.value.product.name}

就取到了。

==========

JSTL

http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL.html

如果做过自定义标签的开发,就很容易使用了。。



  <c:forEach items="${cart.cartItem}" var="item" varStatus="i">
  
<TR align=middle>
    
<TD height=30>${i.count}&nbsp;</TD><%-- ${i.index}  --%>
    
<TD height=30>${item.value.product.name}&nbsp;</TD>
    
<TD height=30>${item.value.product.price}&nbsp;</TD>
    
<TD height=30>${item.value.number}&nbsp;</TD>
    
<TD height=30>${item.value.cost}&nbsp;</TD>
  
</TR>
  
</c:forEach>


=================

struts真的太简单了

ActionServlet委托RequestProcessor完成功能。

ActionForm有几种        DynActionForm的使用和验证kuangjia

    public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest) 
    
{
        ActionErrors errors 
= new ActionErrors();
        
        
if(name == null || name.trim().length() == 0)
        
{
            ActionError error 
= new ActionError("errors.name.required");
            errors.add(
"name", error);
        }

        
        
if(password == null || password.trim().length() == 0)
        
{
            ActionError error 
= new ActionError("errors.password.required");
            errors.add(
"password", error);
        }

        
        
return errors;
    }

页面

<html:errors/>

errors.password.required

就是资源文件的内容

==============

第二种控制异常的方法

抛异常

struts-config.xml

<action attribute="addcourseForm" name="addcourseForm" parameter="addcourse" path="/addcourse" scope="request" type="exam.java.advanced.action.ExamIssueMappingActionAction">
            
<exception key="operate.addcourse" path="/error.jsp" type="exam.java.advanced.BusinessException" />
            
<forward name="success" path="/success.jsp" redirect="true" />
        
</action>

public class ExamIssueMappingActionAction extends MappingDispatchAction {

    
public ActionForward addcourse(ActionMapping mapping, ActionForm arg1,
            HttpServletRequest request, HttpServletResponse arg3)
            
throws Exception {
        EnrollmentBiz biz 
= new EnrollmentBiz();
        
try {
            Course crs 
= new Course();
            DynaActionForm f 
= (DynaActionForm) arg1;
            crs.setId((String) f.get(
"courseid"));
            crs.setName((String) f.get(
"name"));
            crs.setDescription((String) f.get(
"description"));

            biz.saveCourse(crs);
            
return mapping.findForward("success");
        }
 catch (Exception ex) {
            ex.printStackTrace();
            
throw new BusinessException(ex);
        }

    }


=============

验证框架

现在struts-config.xml注册验证的插件,

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
  <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
                            /WEB-INF/validation.xml" />
 </plug-in>

org.apache.struts.action
Interface PlugIn

这个接口就是插件接口,可以自己实现这个接口。

按照人家ValidatorPlugIn的方式写一个属性,以便在struts-config.xml中描述插件时,提供具体值。

pathnames

    public String getPathnames()
    {
        return pathnames;
    }

    public void setPathnames(String pathnames)
    {
        this.pathnames = pathnames;
    }


StringTokenizer st = new StringTokenizer(pathnames, ",");


-----------

org.apache.struts.config.ModuleConfig

该对象在init时传入,可以利用来获得struts-config.xml这个文件的信息。

=====================

DispatchAction就是对于不同form表单在同一Action中处理的解决方案,struts-config.xml在Action标记中加一个parameter属性method,form的action则用function.do?method=add

LookupDispatchAction就是对于同一个页面不同的按钮想都在一个Action中处理。需要重写一个getMap方法。

MappingDispatchAction就是每个方法一个Action标记对应。



最后就是使用令牌的方式来防止重复提交。

org.apache.struts.action.Action

这个父类的方法

protected java.lang.String generateToken(javax.servlet.http.HttpServletRequest request)

protected boolean isTokenValid(javax.servlet.http.HttpServletRequest request)

protected void resetToken(javax.servlet.http.HttpServletRequest request)



posted on 2006-03-12 18:14 北国狼人的BloG 阅读(1531) 评论(1)  编辑  收藏 所属分类: 达内学习总结

评论:
# re: Servlet 2.4 和JSP 2.-的深入学习和Struts的轻松掌握 2007-02-07 12:00 | chris-in
够详细的 !,学了不少的 东西! 3QQQQQ!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: