struts2基础——需要注意的几点
2017-03-01 14:11
375 查看
struts是流行和成熟的基于MVC设计模式的web应用程序框架,使用struts可以帮助我们减少运用MVC设计模型来开发web应用的时间。目录:一、struts2的工作原理及文件结构二、三种访问Servlet API的方式三、struts接收参数的三种方式四、自定义拦截器
一、struts2的工作原理及文件结构
注:FilterDispatcher被替成StrutsPrepareAndExecuteFilter(如果使用FilterDispatcher过滤器时,程序员自己写的Filter过滤器必须放在所有过滤器的前面。而StrutsPrepareAndExecuteFilter过滤器可以让程序员在执行action之前写自己的Filter)描述Struts流程:网页产生HttpServletRequest请求->经过多个过滤器->到达ActionMaaper,判断是否是action请求(如果是)->通过StrutsPrepareAndExecuteFilter过滤器到达Actionproxy,一方面通过configuration Manager(配置管理器)读取struts.xml文档,另一方面创建一个实例,经过一系列的拦截器->执行到Action->返回result(对应了视图)->经过一系列的拦截器(逆序)->通过HttpServletResponse返回到用户实例。二、三种访问servlet API的方法
struts2中没有提供任何一个servlet对象,不存在HttpServletRequest,HttpServletResponse对象。但是Struts2提供了三种方式间接的去访问Servlet API1、ActionContext
通过ActionContext的getContext()静态方法获取ActionContext对象,通过ActionContext对象的一些getSession(),getApplication(),put()等方法,但是千万要注意的是,get获取到的对象都为Map键值对类型。com.opensymphony.xwork2.ActionContext1 public String execute() { 2 if ("ping".equals(username)) { 3 /* 4 * ActionContext可以获得Servlet对象 但是无法获得response响应对象获得 5 * 获得的request、session、Application 都是Map类型 6 */ 7 8 ActionContext.getContext().put("用户名", username); 9 Map session=ActionContext.getContext().getSession(); 10 Map application=ActionContext.getContext().getApplication(); 11 Map request=(Map)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST); 12 } else { 13 ActionContext.getContext().put("info", "信息"); 14 } 15 return SUCCESS; 16 }
2、ServletActionContext
通过调用ServletActionContext类的一些包括getResponse(),getRequest(),getServletContext()等在内的静态方法,这些静态方法的返回类型是和Servlet中的对象类型是一一对应的。其中getResponse()返回类型为HttpServletResponse,getRequest()返回类型为HttpServletRequest().1 public String execute2() throws IOException { 2 if ("ping".equals(username)) { 3 HttpServletResponse response=ServletActionContext.getResponse(); 4 HttpServletRequest request=ServletActionContext.getRequest(); 5 HttpSession session=ServletActionContext.getRequest().getSession(); 6 ServletContext application=ServletActionContext.getServletContext(); 7 } else { 8 9 } 10 System.out.println(username); 11 return SUCCESS; 12 }
3、实现xxxAware接口
(1)实现ServletRequestAware,ServletResponseAware,ServletSessionAware1 public class LoginAction extends ActionSupport implements ServletRequestAware 2 3 4 private HttpServletRequest request; 5 //需实现方法 public void setServletRequest(HttpServletRequest request) { this.request=request; } //response示例 6 public String execute1() throws IOException { 7 if ("ping".equals(username)) { 8 response.setContentType("text/html;charset=utf-8"); 9 PrintWriter out = response.getWriter(); 10 out.print("<script type='text/javascript'>alert('验证码输入错误!')</script>"); 11 out.print("<script type='text/javascript'>location.href='/index.jsp'</script>"); 12 out.flush(); 13 out.close(); 14 } else { 15 response.setContentType("text/html;charset=utf-8"); 16 PrintWriter out = response.getWriter(); 17 out.print("<script type='text/javascript'>alert('验证码输入错误!')</script>"); 18 out.flush(); 19 out.close(); 20 } 21 System.out.println(username); 22 return SUCCESS; 23 }(2)实现RequestWare、SessionWare、ApplicationWare等接口
public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {private Map<String, Object> request;private Map<String, Object> session;private Map<String, Object> application;//DI dependency injection//IoC inverse of controlpublic String execute() {request.put("r1", "r1");session.put("s1", "s1");application.put("a1", "a1");return SUCCESS;}@Overridepublic void setRequest(Map<String, Object> request) {this.request = request;}@Overridepublic void setSession(Map<String, Object> session) {this.session = session;}@Overridepublic void setApplication(Map<String, Object> application) {this.application = application;}}
三、struts三种接收参数方式
Struts有三种方式接收参数,且这三种方式都是自动完成赋值的setter方法。1、使用Action的属性接收参数
代码:struts.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN""http://struts.apache.org/dtds/struts-2.3.dtd"><struts><package name="default" namespace="/" extends="struts-default"><action name="LoginAction" method="login" class="com.third.LoginAction1"><result>/loginSuccess.jsp</result></action></package></struts>login.jsp(登陆提示页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><h1>login page</h1><form action="LoginAction.action" method="post"><table><tr><td>username:</td><td><input type="text" name="username"/></td></tr><tr><td>password:</td><td><input type="password" name="password"/></td></tr><tr><td><input type="submit" value="submit"></td><td><input type="reset" value="reset"></td></tr></table></form></body></html>loginSuccess.jsp(登陆成功提示界面)
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>login success!</title></head><body><h1>login success!</h1></body></html>LoginAction.java
1 package com.third;23 import com.opensymphony.xwork2.ActionSupport;45 public class LoginAction1 extends ActionSupport {67 private String username;8 private String password;910 public String login(){//这里能够打印出来传入的值,则说明能够自动调用setter方法完成赋值11 System.out.println("username:"+username+" password:"+password);12 return SUCCESS;13 }1415 public String getUsername() {16 return username;17 }1819 public void setUsername(String username) {20 this.username = username;21 }2223 public String getPassword() {24 return password;25 }2627 public void setPassword(String password) {28 this.password = password;29 }3031 }运行结果截图:
2、使用DomainModel接收参数
注:这里在表单传值是,必须指明这个属性值,到底穿个action中的那个引用,例如user.username.代码:struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts><package name="default" namespace="/" extends="struts-default"><action name="LoginAction" method="login" class="com.third.LoginAction"><result>/loginSuccess.jsp</result></action></package></struts>login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'login.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><h1>login page!</h1><form action="LoginAction.action" method="post"><table><tr><td>username:</td><td><input type="text" name="user.username"/></td></tr><tr><td>password:</td><td><input type="password" name="user.password"/></td></tr><tr><td><input type="submit" value="submit"></td><td><input type="reset" value="reset"></td></tr></table></form></body></html>loginSuccess.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'loginSuccess.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><h1>login success!</h1></body></html>User.java
package com.third;public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}LoginAction.java
1 package com.third;23 import org.apache.struts2.ServletActionContext;45 import com.opensymphony.xwork2.ActionContext;6 import com.opensymphony.xwork2.ActionSupport;7 import com.opensymphony.xwork2.inject.Context;89 public class LoginAction extends ActionSupport {1011 private User user;12 public User getUser() {13 return user;14 }1516 public void setUser(User user) {17 this.user = user;18 }19 public String login(){//这里可以打印出传入的值的话,Action完成了自动调用setter方法赋值20 System.out.println("username:"+user.getUsername()+" password:"+this.getUser().getPassword());21 return SUCCESS;22 }2324 }运行结果截图:
3、使用ModelDriven接受参数
struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts><package name="default" namespace="/" extends="struts-default"><action name="LoginAction" method="login" class="com.third.LoginAction"><result>/loginSuccess.jsp</result></action></package></struts>login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'login.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><h1>login page!</h1><form action="LoginAction.action" method="post"><table><tr><td>username:</td><td><input type="text" name="username"/></td></tr><tr><td>password:</td><td><input type="password" name="password"/></td></tr><tr><td><input type="submit" value="submit"></td><td><input type="reset" value="reset"></td></tr></table></form></body></html>loginSuccess.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'loginSuccess.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><h1>login success!</h1></body></html>User.java
package com.third;public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}LoginAction.java
package com.third;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;import com.opensymphony.xwork2.inject.Context;public class LoginAction extends ActionSupport implements ModelDriven<User> {private User user=new User();public String login(){//这里打印出传入的参数值,说明自动调用setter方法赋值System.out.println("username:"+user.getUsername()+" password:"+user.getPassword());return SUCCESS;}@Overridepublic User getModel() {return user;}}运行结果截图:
四、自定义拦截器
注:特别要注意在使用拦截的器的时候,使用表单传值,会导致Action中获得的属性的值为null,或是其他的默认的初始化值。1、实现Interceptor接口-void init()方法:初始化拦截器所需要的资源-void destory()方法:释放init()中分配的资源-String intercept(ActionInvocation invocation)throws Exception:实现拦截器功能,利用ActionInvocation参数获取Action状态,返回result字符串作为逻辑视图。代码:struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts><package name="default" namespace="/" extends="struts-default"><!--注册拦截器 --><interceptors><interceptor name="timefigureFilter" class="com.third.TimeInterceptor"></interceptor></interceptors><action name="LoginAction" method="login" class="com.third.LoginAction"><result>/loginSuccess.jsp</result><interceptor-ref name="timefigureFilter"></interceptor-ref></action></package></struts>login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'login.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><h1>login page!</h1><form action="LoginAction.action" method="post"><table><tr><td>username:</td><td><input type="text" name="username"/></td></tr><tr><td>password:</td><td><input type="password" name="password"/></td></tr><tr><td><input type="submit" value="submit"></td><td><input type="reset" value="reset"></td></tr></table></form></body></html>loginSuccess.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'loginSuccess.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><h1>login success!</h1></body></html>User.java
package com.third;public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}TimeInterceptor.java
1 package com.third;23 import javax.servlet.http.HttpServletRequest;45 import org.apache.struts2.ServletActionContext;67 import com.opensymphony.xwork2.ActionInvocation;8 import com.opensymphony.xwork2.interceptor.Interceptor;910 public class TimeInterceptor implements Interceptor {1112 @Override13 public void destroy() {14 // TODO Auto-generated method stub1516 }1718 @Override19 public void init() {20 // TODO Auto-generated method stub2122 }2324 @Override25 public String intercept(ActionInvocation invocation) throws Exception {26 HttpServletRequest request=ServletActionContext.getRequest();27 String username=request.getParameter("username");28 String password=request.getParameter("password");29 request.setAttribute("username", username);30 //1执行action之前31 long start=System.currentTimeMillis();32 //2执行下一个拦截器,直到最后一个拦截器,则执行目标Action33 String result=invocation.invoke();34 //3执行完action之后35 long end=System.currentTimeMillis();36 System.out.println("执行Action花费的时间为:"+(end-start)+"ms");37 return result;38 }3940 }LoginAction.java
1 package com.third;23 import org.apache.struts2.ServletActionContext;45 import com.opensymphony.xwork2.ActionContext;6 import com.opensymphony.xwork2.ActionSupport;7 import com.opensymphony.xwork2.ModelDriven;8 import com.opensymphony.xwork2.inject.Context;910 public class LoginAction extends ActionSupport implements ModelDriven<User> {1112 private User user=new User();13 public String login(){//着重看着两行代码运行打印的结果14 System.out.println("username:"+user.getUsername());//System.out.println("username:"+ServletContext.getRequest().getAttribute("username");//这里也可完成正常的获值15 System.out.println("username:"+ServletActionContext.getRequest().getAttribute("username"));16 return SUCCESS;17 }1819 @Override20 public User getModel() {2122 return user;23 }2425 }运行结果截图:注:注意看结果,打印的第一个username的属性值为null,而第二个为表单填写的dasd。这里涉及到拦截器的使用导致的表单传值问题。
分析:拦截器的使用导致的表单传值问题
原因:登陆界面填写完成之后,表单需要实现页面跳转,而这些将会交给struts,struts在调用action的过程其实是调用action中的struts.xml配置action标签method属性指定的方法(默认是execute()),而在调用这个方法前会对表单的属性信息将会别匹配赋值给action中同名属性。正常情况下没有自定义的拦截器,通过表单传递的属性值没有问题。要完成这个功能,有很大程度上, Struts 2 要依赖与 ValueStack 对象。这个对象贯穿整个 Action 的生命周期 (每个 Action 类的对象实例会拥有一个 ValueStack 对象 ) 。当 Struts 2 接收到一个 action 的请求后,会先建立Action 类的对象实例,但不会调用 Action 方法,而是先将 Action 类的相应属性放到 ValueStack 对象的顶层节点(ValueStack 对象相当于一个栈 ). 只是所有的属性值都是默认的值,如 String 类型的属性值为 null,int 类型的属性值为 0 等。 在处理完上述工作后, Struts 2 就会调用拦截器链中的拦截器,当调用完所有的拦截器后,最后会调用 Action 类的 Action 方法,在调用 Action 方法之前,会将 ValueStack 对象顶层节点中的属性值赋给 Action 类中相应的属性。大家要注意,在这里就给我们带来了很大的灵活性。也就是说,在 Struts 2 调用拦截器的过程中,可以改变ValueStack 对象中属性的值,当改变某个属性值后, Action 类的相应属性值就会变成在拦截器中最后改变该属性的这个值。好多废话~总结就是:在拥有自定义的过滤器时,表单传属性值会先赋值给Action中属性,当运行完过滤器时,才会调用Action中的方法,在调用之前会将 ValueStack 对象中的默认初始化值赋给action中的属性,然后调用action中的方法,这样action中的属性全是ValueStack 对象中的默认初始化值。解决的方法:间接访问Servlet的API,通过request对象去访问属性和属性值。如:HttpServletRequest request=ServletActionContext.getRequest();String username=request.getParameter("username");2、方式二:继承AbstractInterceptor类
-提供了init()和destroy()方法的实现-只需要实现intercept()方法即可代码:struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts><package name="default" namespace="/" extends="struts-default"><!--注册拦截器 --><interceptors><interceptor name="timefigureFilter1" class="com.third1.TimeInterceptor"></interceptor></interceptors><action name="TimeAction" class="com.third1.TimeAction"><result>/index.jsp</result><!--引用拦截器 --><interceptor-ref name="timefigureFilter1"></interceptor-ref></action></package></struts>TimeInterceptor.java
1 package com.third1;23 import org.apache.struts2.ServletActionContext;45 import com.opensymphony.xwork2.ActionInvocation;6 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;78 public class TimeInterceptor extends AbstractInterceptor {910 @Override11 public String intercept(ActionInvocation invocation) throws Exception {12 //1.执行action之前13 long start=System.currentTimeMillis();14 //2.执行下一个拦截器,如果已经是最后一个拦截器,则执行目标Action1516 ServletActionContext.getRequest().setAttribute("username", "小帅哥");17 ServletActionContext.getRequest().getSession().setAttribute("username","小美女");18 ServletActionContext.getServletContext().setAttribute("username", "少艾");19 String result=invocation.invoke();20 //3.执行Action之后21 long end=System.currentTimeMillis();22 System.out.println("执行Action花费的时间:"+(end-start)+"ms");23 //获取request对象,调用其setAttribute函数,将时间作为属性保存到request对象中24 ServletActionContext.getRequest().setAttribute("time", (end-start));25 ServletActionContext.getRequest().getSession().setAttribute("time1",(end-start));26 ServletActionContext.getServletContext().setAttribute("time2", (end-start));27 return result;28 }2930 }TimeAction.java
1 package com.third1;23 import com.opensymphony.xwork2.ActionSupport;45 public class TimeAction extends ActionSupport {67 @Override8 public String execute() throws Exception{910 for(int i=0;i<3;i++){11 Thread.sleep(1000);12 }13 return SUCCESS;14 }15 }index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"><title>My JSP 'index.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><h1>执行Action用户名:<%=request.getAttribute("username") %>(通过request方式获取)</h1><h1>执行Action用户名:<%=session.getAttribute("username") %>(通过session方式获取)</h1><h1>执行Action用户名:<%=application.getAttribute("username") %>(通过application方式获取)</h1><h1>执行Action花费的时间:<%=request.getAttribute("time") %>(通过request方式获取)</h1><h1>执行Action花费的时间:<%=session.getAttribute("time1") %>(通过session方式获取)</h1><h1>执行Action花费的时间:<%=application.getAttribute("time2") %>(通过application方式获取)</h1></body></html>运行结果截图:分析:对比两种颜色标记的代码区,对比一下他们,并且结合结果进行分析。我们不难发现过滤器的调用分为两个阶段,第一个阶段是在产生HttpServletRequest请求之后、action方法调用之前;第二阶段是产生与action之后,jsp页面(Template显示)跳转之后,HttpServletResponse之前。所以当你在String result=invocation.invoke(); 这条语句之后通过request,application,session给它设置属性值,将会没有起到任何作用。可以结合struts2的工作原理及文件结构图进行参考。
相关文章推荐
- struts2基础——需要注意的几点
- struts2基础——需要注意的几点
- struts2基础——需要注意的几点
- python基础——需要注意的几点
- 在Web中编写文件上传程序需要注意的几点
- 使用JSTL的标签是需要注意的几点问题
- 做好一个论坛需要注意的几点
- IIS下的ASP程序转换到Apache下PHP几点需要注意的几点
- 编程需要注意陷阱:Java继承是有害的-Java基础-Java-编程开发
- apache下配置php需要注意的几点
- 配置OSPF时需要注意的几点
- Tips Struts2 部署在生产环境中需要注意的参数
- 在Web中编写文件上传程序需要注意的几点
- 创业起步阶段需要注意的几点
- 操作excel需要注意几点
- 论文投稿参考——向国外投稿需要注意些下面几点
- 海外老师谈英语学习需要注意的几点
- ACCESS转SQLserver2000所需要注意的几点(转载)
- 使用innerHTML时需要注意的几点问题
- 旧的代码在2005下使用需要注意以下几点