zoukankan      html  css  js  c++  java
  • Servlet、Filter和Listener

    Java Servlet是与平台无关的服务器端组件,运行于Servlet容器中(如Tomcat),Servlet容器负责Servlet和客户端的通信以及调用Servlet的方法,Servlet和客户端的通信采用“请求/响应”的模式。Servlet可完成以下功能:

    1、创建并返回基于客户请求的动态HTML页面。

    2、创建可以嵌入到现有HTML页面中的HTML片段。

    3、与其它服务器资源(如数据库或基于Java的应用程序)进行通信。

    4、接收多个客户端的输入,并将结果广播到多个客户端上,例如,Servlet可以实现支持多个参与者的游戏服务器。

    5、根据客户请求采用特定的MIME(Multipurpose Internet Mail Extensions)类型对数据过滤,例如进行图像格式转换。

    Servlet的框架由两个包组成:javax.servlet和javax.servlet.http。在javax.servlet包中定义了所有Servlet类必须实现或扩展的通用接口和类。在javax.servlet.http包中定义了采用HTTP协议通信的HttpServlet类。

    Servlet框架的核心是javax.servlet.Servlet接口,所有的Servlet类都必须实现这个接口。Servlet接口定义的方法如下:

    1、init方法,负责初始化Servlet对象。

    2、service方法,负责响应客户端的请求。

    3、destroy方法,当Servlet对象退出生命周期时,负责释放占用的资源。

    4、getServletConfig方法,获得ServletConfig接口,可以得到Servlet的相关参数。

    5、getServletInfo方法,获得Servlet的相关信息。

    在javax.servlet包中,GenericServlet类实现了Servlet接口,在javax.servlet.http包中,HttpServlet类扩展了GenericServlet

    类。当用户开发自己的Servlet时,必须扩展以上两个类中的一个,如果扩展自GenericServlet类,则必须自己实现service方法,

    如果扩展自HttpServlet类,则不需要自己实现service方法,因为HttpServlet类已经实现了该方法。

    Servlet、Filter和Listener - poorboy030103 - poorboy030103的博客

    GenericServlet类的service方法是一个抽象方法,只有两个参数:ServletRequest和ServletResponse。HttpServlet类的service方法也只有两个参数:HttpServletRequest和HttpServletResponse。HttpSevletRequest接口和HttpResponse接口分别扩展自ServletRequest和ServletResponse接口,都提供了与特定协议HTTP相关的数据。

    ServletRequest接口的方法如下:

    getAttribute            获得属性值

    getContentType      获得客户请求数据的MIME类型。

    getInputStream      获得可以读取客户请求数据的输入流。

    getParameter          获得参数值

    getRemoteAddr      获得客户端的IP

    getRemoteHost       获得客户端的主机名

    getRemotePort              获得客户端的端口

    setAttribute            设置属性值。

    ServletResponse接口的方法如下:

    getOutputStream    获得可以向客户羰发送二进制数据的输出流对象ServletOutputStream

    getWriter               获得可以向客户端发送字符数据的PrintWriter对象

    getCharacterEncoding    获得Servlet发送的响应数据的字符编码

    getContentType      返回Servlet发送的响应数据的MIME类型

    setCharacterEncoding    设置Servlet发送的响应数据的字符编码。

    setContentType      设置Servlet发送的响应数据的MIME类型。

    Servlet的init方法有如下两种形式:

    public void init(ServletConfig config) throws ServletException

    public void init() throws ServletException

    在Servlet的初始化分阶段,Servlet容器会为Servlet创建一个ServletConfig对象,用来存放Servlet的初始化配置信息,如Servlet的初始参数。如果Servlet覆盖了带参数的init方法,则必须在函数体内先调用super.init(config); 以确保config参数引用了ServletConfig对象。如果Servlet覆盖了没有带参数的init方法,则不需要调用super.init(); 方法,可以通过调用getServletConfig()方法来获得ServletConfig对象。

    Servlet容器会为Web应用创建一个唯一的全局的ServletContext对象,可以把它看成是一个Web应用的服务器端组件的共享内存。它有如下方法:

     etAttribute(String name,Object obj) 将一个对象与一个属性名绑定,并存放到

    ServletContext中

    getAttribute(String name) 获得指定名称的属性值。

    removeAttribute(String name) 删除指定名称的属性。

    getAttributeNames() 返回所有属性名的一个Enumeration对象。

    getInitParameter(String name) 获得指定名称的参数值,该参数是Web应用的初始化参数.

    getInitParameterNames() 返回Web应用的所有初始化参数的名称的Enumeration对象.

    getMimeType(String file) 返回文件的MIME类型.

    getRealPath(String path) 返回网络路径path对应的文件系统路径.

    getServerInfo() 返回Servlet容器的名称和版本

    注意: 一般在HptpServlet的子类中,将doPost方法的实现合并到doGet方法中,也就是在doPost方法中简单地调用doGet方法.因为一般情况下对于Get和Post请求,它们都是一样的处理.

    编译了Servlet后,将它打包成jar放到WEB-INF/lib目录下,或将Servlet的class文件放到WEB-INF/classes/目录下,再在WEB-INF/web.xml配置文件中配置这些servlet,就可以在Web应用中访问servlet了,配置如下:

     <servlet>

    <servlet-name>my_servlet</servlet-name>

    <servlet-class>com.mycompany.ServletClass1</servlet-class>

    < init-param> <!--定义servlet的初始化参数, 可以有多个init-param参数-->

    < param-name>iParam< /param-name>

    < param-value>2< /param-value>

    < /init-param>

    < load-on-startup>2< /load-on-startup> <!--定义servlet的加载顺序-->

    </servlet>

    <servlet-mapping>

    <servlet-name>my_servlet</servlet-name>

    <url-pattern>*.hello</url-pattern>

    </servlet-mapping>

    Session相关

    在Servlet API中定义了javax.servlet.http.HttpSession接口,Servlet容器必须实现这一个接口。当一个Session开始时,Servlet容器将创建一个HttpSession对象,在HttpSession对象中可以存放客户状态的信息。Servlet容器为HttpSession对象分配一个唯一的标识符,叫做Session ID,Servlet容器把Session ID作为Cookie保存在客户的浏览器中,每次客户发出HTTP请求时,Servlet容器可以从HttpRequest对象中读取Session ID,然后根据Session ID找到相应的HttpSession对象,从而获得客户的状态信息。HttpSession接口有如下方法:

    getId()    返回Session ID

    invalidate()      使当前的Session失效,Servlet容器会释放HttpSession对象占用的资源。

    setAttribute(String name,Object obj)     将一对name/value属性保存到HttpSession对象中。

    getAttribute(String name)      返回名字为name的属性值。

    getAttributeNames()      返回HttpSession对象中所有的属性名。

    isNew()   判断这个Session是不是新创建的。

    setMaxInactiveInterval()              设定Session可以处于不活动状态的最大时间(以秒为单位),                                              超过这个时间,Session就会自动失效,如果设置为负数,则不                                             限制Session的不活动状态时间。

    getMaxInactiveInterval()       返回Session可以处于不活动状态的最大时间。

    当客户第一次访问Web应用中支持Session的某个页面时,就会开始一个新的Session,接下来,当客户浏览这个Web应用的其它页面时,始终处于同一个Session中。以下情况之一,Session就会失效:

    1、客户端关闭浏览器。

    2、Session过期,即客户在指定的最大时间内没有与Web服务器交互。

    3、服务器端调用了HttpSession的invalidate()方法。

    如果客户端浏览器不支持或禁用Cookie,则Servlet容器无法从客户端浏览器中取得作为Cookie的Session ID,也就无法跟踪客户的状态,因此客户端的每次请求支持Session的JSP页面时,Servlet容器都会创建一个新的HttpSession对象。对于这种情况,需要通过HttpServletResponse的encodeURL()方法重写客户请求的URL,它把Session ID添加到URL信息中,也就是说,对于支持Session的JSP页面中的所有连接URL,都要调用encodeURL()方法来重写这些URL,例如:

    对于<a href=”login.jsp”/>应该改为<a href=”<%=response.encodeURL(“login.jsp”)%>”/>

    这样,即使客户禁用Cookie,也能使用Session来跟踪客户的状态信息了。

    Session的持久化:

    Session的持久化就是将HttpSession对象从内存中转移到文件系统或数据库中,这样做的好处是:减少系统资源的占用,如果Servlet容器突然关闭或重启,或Web应用重启,这些持久化了的HttpSession对象可以再重新加载进来,对于客户端,还是使用同一个Session。

    Session的持久化是由Session Manager来管理的,Tomcat提供了两个实现类:

    l         org.apache.catalina.session.StandarManager

    l         org.apache.catalina.session.PersistentManager

    1、StandarManager是默认的Session Manager。它的实现机制是:当Tomcat服务器关闭或重启,或Web应用被重新加载时,会将内存中所有的HttpSession对象保存到文件系统中,默认的文件路径是:%CATALINA_HOME%workCatalina<applicaton-name>SESSIONS.ser

    重启Tomcat后,Tomcat服务器把SESSIONS.ser中的持久化HttpSession对象加载到内存中。

    2、PersistentManager能够把HttpSession对象保存到Session Store中,它提供了比较StandarManager更灵活的管理功能,具有容错能力,控制内存中HttpSession对象的数目等。

    Tomcat实现Session Store的接口为org.apache.catalina.session.Store,目前提供了两个实现这一接口的类:org.apache.catalina.session.FileStore和org.apache.catalina.session.JDBCStore。FileStore会将HttpSession对象保存到文件系统中;而JDBCStore则将HttpSession对象保存到数据库表中。

    下面给出这两个类的配置:

    配置FileStore:

    在server.xml中,在Web应用的<Context>元素加入<Manager>元素,例如:

    <Context path=”/helloapp” docBase=”helloapp” debug=”0” reloadable=”true”>

           <Manager className=”org.apache.catalina.session.PersistentManager”>

                  debug=0;

                  saveOnRestart=”true”

                  maxActiveSessions=”-1”

                  minIdleSwap=”-1”

                  maxIdleSwap=”-1”

                  maxIdleBackup=”-1”

                  <Store className=”org.apache.catalina.session.FileStore” directory=”mydir”/>

           </Manager>

    </Context>

    属性

    作用

    className

    指定Session Manager的实现类名,或Session Store的实现类名

    debug

    设定Session Manager采用的跟踪级别,取值0到99,越小越跟踪信息越少,发布产品时,应该设置为0,以提高性能。

    saveOnRestart

    如果为true,则当Tomcat关闭时,所有的有效HttpSession对象都保存到Session Store中;当Tomcat重启时,加载这些HttpSession对象。

    maxActiveSessions

    设置处于活动状态的Session的最大数目,如果超过这一数目,Tomcat把一些超过的Sessin对象保存到Session Store中。-1表示不限制。

    minIdleSwap

    Session处于不活动状态的最小时间,单位为秒,超过这一时间,Tomcat有可能把这个Session对象移到Session Store中。

    maxIdleSwap

    Session处于不活动状态的最大时间,超过这一时间,Tomcat就一定会将这个Session对象移到Session Store中。

    maxIdleBackup

    Session处于不活动状态的最大时间,超过这一时间,Tomcat就就会将这个Session对象拷贝到Session Store中进行备份。

    directory

    指定Session Store在哪个文件系统目录下存放持久化的Session对象的信息,文件名是Session ID.session。

    配置JDBCStore:

    在server.xml中,在Web应用的<Context>元素加入<Manager>元素,例如:

    <Context path=”/helloapp” docBase=”helloapp” debug=”0” reloadable=”true”>

           <Manager className=”org.apache.catalina.session.PersistentManager”>

                  debug=0;

                  saveOnRestart=”true”

                  maxActiveSessions=”-1”

                  minIdleSwap=”-1”

                  maxIdleSwap=”-1”

                  maxIdleBackup=”-1”

                  <Store className=”org.apache.catalina.session.JDBCStore”

                         driverName=”com.mysql.jdbc.Driver”

                         connectionURL=”jdbc:mysql://localhost:3306/demo?user=root password=1234”

                         sessionTable=”tomcat_sessions”

                         sessionIdCol=”session_id”

                         sessionDataCol=”session_data”

                         sessionValidCol=”session_valid”

                         sessionMaxInactiveCol=”max_inactive”

                         sessionLastAccessedCol=”last_access”

                         sessionAppCol=”app_name”

                         checkInterval=”60”

                         debug=”0”

                  />

           </Manager>

    </Context>

    说明:上面的元素属性的含义与FileStore的相同,上面的配置假设在MySQL服务器上的demo数据库的tomcat_sessions表中存放持久化Session对象的信息,这个表的结构如下:

    CREATE TABLE tomcat_sessions(

           session_id VARCHAR(10) NOT NULL PRIMARY KEY,

           session_data MEDIUMBLOB,

           session_valid CHAR(1) NOT NULL,

           max_inactive   INT NOT NULL,

           last_access     BIGINT NOT NULL,

           app_name       VARCHR(255),

           KEY kapp_name(app_name)

    );

    Filter相关

    Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改,它在Servlet被调用之前检查Request对象,修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response内容。Servlet过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件,具有以下特点:

    l         Servlet过滤器可能检查和修改ServletRequest和ServletResponse对象

    l         可以指定Servlet过滤器和特定的URL关联,只有当客户请求访问此URL时,才会触发该过滤器工作

    l         多个Servlet过滤器可以被串联起来,形成管道效应,协同修改请求和响应对象

    l         所有支持Java Servlet规范2.3的Servlet容器,都支持Servlet过滤器

    所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。该接口定义了以下3个方法:

    l         init(FilterConfig)     这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后就会调用这个方法。在这个方法中可以通过FilterConfig来读取web.xml文件中Servlet过滤器的初始化参数。

    l         doFilter(ServletRequest, ServletResponse, FilterChain)  这是完成实际的过滤操作的方法,当客户请求访问与过滤器关联的URL时,Servlet容器先调用该方法。FilterChain参数用来访问后续的过滤器的doFilter()方法。

    l         destroy() Servlet容器在销毁过滤器实例前调用该方法,在这个方法中,可以释放过滤器占用的资源。

    下面是一个过滤器的例子,它可以拒绝列在黑名单上的客户访问留言簿,而且能将服务器响应客户请求所花的时间写入日志:

    //WEB-INF/classes/NoteFilter.class

    import java.io.*;

    import javax.servlet.*;

    import javax.servlet.http.*;

    public class NoteFilter implements Filter{

           private FilterConfig config=null;

           private String blackList=null;

           public void init(FilterConfig config)throws ServletException{

                  this.config=config;

                  blackList=config.getInitParameter(“blacklist”);

           }

           public void destroy(){

                  config=null;

           }

           public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

                  throws IOException, ServletException{

                  String userName=((HttpServletRequest)request).getParameter(“user_name”);

                  if(userName!=null)

                         userName=new String(userName.getBytes(“ISO-8859-1”),”GB2312”);

                  if(userName!=null && userName.indexOf(blackList)!=-1){

                         PrintWriter out=response.getWriter();

                         out.print(“<html><body>”);

                         out.print(“<h1>对不起,”+userName+”,你没有权限留言</h1>”);

                         out.print(“</body></html>”);

                         out.flush();

                         return;

                  }

                  long before=System.currentTimeMillis();

                  config.getServletContext().log(“NoteFilter:before call chain.doFilter()”);

                  chan.doFilter(request, response);

                  config.getServletContext().log(“NoteFilter:after call chain.doFilter()”);

                  logn after=System.currentTimeMillis();

                  String name=””;

                  if(request instanceof HttpServletRequest)

                         name=((HttpServletRequest)request).getRequestURL();

                  config.getServletContext().log(“NoteFilter:”+name+”:”+(after-before)+”ms”);

           }

    }

    发布Servlet过滤器,必须在web.xml文件中加入<filter>和<filter-mapping>元素,如下:

    <filter>

           <filter-name>NoteFilter</filter>

           <filter-class>NoteFilter</filter-class>

           <init-param>

                  <param-name>blackList</param-name>

                  <param-value>捣蛋鬼</param-value>

           </init-param>

    <filter>

    <filter-mapping>

           <filter-name>NoteFilter</filter-name>

           <url-pattern>/note</url-pattern>

    </filter-mapping>

    多个过滤器可以串连起来协同工作,Servlet容器将根据它们在web.xml中定义的先后顺序,依次调用它们的doFilter()方法。而这些过滤之间的关系不需要任何配置。

    Listener的作用类似于load-on-startup的Servlet,在Web应用启动时被加载,在Web应用关闭时被销毁,Listener用来作为Web应用的后台服务,比load-on-startup的Servlet更早被加载到Servlet容器中。自定义的Listener类必须实现ServletContextListener接口,并实现该接口的两个方法:contextInitialized(ServletContextEvent)和contextDestroyed(ServletContextEvent),例如:

    public class GetConnListener implements ServletContextListener{
     public void contextInitialized(ServletContextEvent sce){
      try{
       ServletContext application=sce.getServletContext();
       String driver=application.getInitParameter("driver");
       String url=application.getInitParameter("url");
       String user=application.getInitParameter("user");
       String password=application.getInitParameter("password");
       Class.forName(driver);
       Connection conn=DriverManager.getConnection(url, user, password);
       application.setAttribute("conn", conn);
      }catch(Exception e){
       System.out.println("Listener中获取数据库连接出现异常:"+e.getMessage());
      }
     }
     public void contextDestroyed(ServletContextEvent sce){
      ServletContext application=sce.getServletContext();
      Connection conn=(Connection)application.getAtrribute("conn");
      if(conn!=null){
       try{
        conn.close();
        conn=null;
       }catch(Exception e){}
      }
     }
    }

    Listener配置:

    <listener>

      <listener-class>lee.GetConnListener</listener-class>

    </listener>

    自定义JSP标签库

    实现自定义标签的处理类

    JSP容器编译JSP网页时,遇到自定义标签,就会调用这个标签的处理类。标签处理类必须扩展自javax.servlet.jsp.TagSupport类或javax.servlet.jsp.BodyTagSupport类。

    1、TagSupport类的主要方法如下:

    l         doStartTag      JSP容器遇到自定义标签的起始标志时调用该方法。

    l         doEndTag       JSP容器遇到自定义标签的结束标志时调用该方法。

    l         setValue(String k, Object v)   在标签处理类中设置key/value。

    l         getValue(String k)          在标签处理类中获得key对应的value。

    l         removeValue(String k)    在标签处理类中删除key/value。

    l         setPageContext(PageContext pc)   设置PageContext对象,由JSP容器在调用doStartTag或doEndTag方法之前调用。

    l         setParent(Tag t)     设置该标签的上层标签的处理类,由JSP容器在调用doStartTag或 doEndTag方法之前调用。

    l         getParent()     返回该标签的上层标签的处理类。

    2、TagSupport类有两个重要属性:

    l         parent     该标签的上层标签的处理类。

    l         pageContext    Web应用中的javax.servlet.jsp.PageContext对象,提供了保存和访问Web应用的共享数据方法:setAttribute(String name, Object value, int scope)和getAttribute(String name, int scope)。其中scope参数用来指定属性存在的范围,可选值有:PageContext.PAGE_SCOPE、PageContext.REQUEST_SCOPE、PageContext.SESSION_SCOPE和PageContext.APPLICATION_SCOPE。

    注意:在TagSupport的构造函数中不能访问pageContext成员,因为此时JSP容器还没有调用setPageContext 方法对pageContext进行初始化。

    3、处理标签的方法:

    当JSP容器遇到自定义标签的起始标志时,就会调用该标签处理类的doStartTag()方法。doStartTag()方法返回一个整数值,用来决定程序的后续流程,有两个可选值:Tag.SKIP_BODY和Tag.EVAL_BODY_INCLUDE。Tag.SKIP_BODY表示标签之间的内容被忽略,例如:

    <prefix:mytag>

           Hello World!

    </prefix:mytag>

    如果这个标签的处理类的doStartTag()方法返回Tag.SKIP_BODY,则Hello World!字符串不会显示在网页上。Tag.EVAL_BODY_INCLUDE表示标签之间的内容会被处理。

    当JSP容器遇到自定义标签的结束标志时,就会调用该标签处理类的doEndTag()方法。doEndTag()方法也返回一个整数值,表示程序的后续流程,也是有两个可选值:Tag.SKIP_PAGE和Tag.EVAL_PAGE。Tag.SKIP_PAGE表示立刻停止执行JSP页面,该标签的结束标志之后的所有页面内容全部会初忽略,任何已有的输出内容立刻返回到客户的浏览器上;Tag.EVAL_PAGE表示按正常的流程继续执行JSP页面的内容。

    4、自定义标签的属性

    例如:<prefix:mytag attribute1=”value1”>…</prefix:mytag>

    那么在标签处理类中必须将这个属性作为类的成员变量,并且必须提供相应的getter和setter方法,例如:

    private int attribute1;

    public void setAttribute1(int value){ attribute1=value;}

    public int getAttribute1(){return attribute1;}

    以下是一个自定义标签<message>的处理类的例子:

    // WEB-INF/classess/mypack/MessageTag.class

    package mypack;

    import javax.servlet.jsp.JspException;

    import javax.servlet.jsp.JspTagException;

    import javax.servlet.jsp.TagSupport;

    import javax.servlet.http.HttpSession;

    import java.util.Properties;

    import java.io.*;

    public class MessageTag extends TagSupport{

           private String key=null;

           public MessageTag(){}

           public void setKey(String key){

                  this.key=key;

           }

           public String getKey(){

                  return key;

           }

           public int doEndTag() throws JspException{

                  try{

                         pageContext.getOut.print(key);

                  }catch(Exception e){

                         throw new JspTagException(e.getMessage());

                  }

                  return SkIP_BODY;

           }

           public void release(){

                  super.release();

           }

    }

    创建标签库描述文件(Tag Library Descriptor, TLD)

    TLD文件中的元素可分为3类:

    l         <taglib>元素用来设置标签库的相关信息,它有如下属性:

    tlibversion       指定标签库的版本

    jspversion       指定JSP的版本

    shortname      指定标签库默认的前缀名(prefix)

    uri                 设置标签库的唯一访问标示符

    info                标签库的说明信息

    l         <tag>元素用来定义一个标签,它的属性如下:

    name              标签的名字

    tagclass          标签的处理类

    bodycontent    标签主体(body)的内容

    info                标签的说明信息

    说明:bodycontent属性有3个可选值:empty、JSP和tagdependent。empty表示标签没有主体,JSP表示标签的主体中可以加入JSP代码,tagdependent表示标签的主体的内容由标签的处理类自己去处理。

    l         <attribute>元素用来定义标签的属性,它有如下属性:

    name              属性名

    required          该属性是否必须,默认是false

    rtexprvalue     该属性的值是否可能通过”<%=…%>”的方式获得,当设置为true时,该属性就可以采用如下的方式设置值:<% int num=1;%> <prefix:mytag attribute1=”<%=num%>”/>

    以下是一个标签库描述文件的例子:

    <!--WEB-INF/mytag.tld-->

    <?xml version=”1.0” encoding=”ISO-8859-1”?>

    <!DOCTYPE taglib PUBLIC “-//Sun Microsystems,Inc.//DTD JSP TagLibrary 1.1//EN”

           “http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd”>

    <taglib>

           <tlibversion>1.0</tlibversion>

           <jspversion>1.1</jspversion>

           <shortname>mytaglib</shortname>

           <uri>/mytaglib</uri>

          

           <tag>

                  <name>message</name>

                  <tagclass>mypack.MessageTag</tagclass>

                  <bodycontent>empty</bodycontent>

                  <info>produce message by key</info>

                 

                  <attribute>

                         <name>key</name>

                         <required>true</required>

                         <rtexprvalue>true</rtexprvalue>

                  </attribute>

           </tag>

    </taglib>

    在web.xml文件中加入标签库的定义

    <taglib>

           <!--标签库的唯一标示符,与标签库描述文件中的<uri>元素的内容相同,在JSP页面中,也要通过这个定义来使用标签库-->

           <taglib-uri>/mytaglib</taglib-uri> 

           <!--指定标签库描述文件所在的位置-->

           <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>

    </taglib>

    在JSP页面中使用自定义的标签

    例如:

    <%@ taglib uri=”/mytaglib” prefix=”mm”%>

    <html>

    <body>

           <mm:message key=”hello world!”/>

    </body>

    </html>

  • 相关阅读:
    初认识AngularJS
    (imcomplete) UVa 10127 Ones
    UVa 10061 How many zero's and how many digits?
    UVa 11728 Alternate Task
    UVa 11490 Just Another Problem
    UVa 10673 Play with Floor and Ceil
    JSON对象和字符串的收发(JS客户端用typeof()进行判断非常重要)
    HTML.ActionLink 和 Url.Action 的区别
    EASYUI TREE得到当前节点数据的GETDATA方法
    jqueery easyui tree把已选中的节点数据拼成json或者数组(非常重要)
  • 原文地址:https://www.cnblogs.com/zhuawang/p/4890318.html
Copyright © 2011-2022 走看看