Struts2学习笔记

编程技术  /  houtizong 发布于 3年前   149
SSH : Spring + Struts2 + Hibernate
三层架构(表示层,业务逻辑层,数据访问层) MVC模式 (Model View Controller)
分层原则:单向依赖,接口耦合

1、Struts2  =  Struts  + Webwork
2、搭建struts2开发环境
   a>、到www.apache.org下载开发包
   b>、以 apps/struts-blank.war为蓝本
   c>、复制WEB-INF/lib下的jar包至工程构建路径
   d>、在web.xml中添加struts2的前端控制器
       <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
      </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

   e>、在src目录中创建一个名称为struts.xml的配置文件


3、让配置文件产生提示

4、让一个DIV页面居中
    #continer {
       text-align : left;
       width : 1000px;
       height : 400px;
       border : 1px solid red;
       /*居中显示*/
       position : absolute;
       left : 50%;
       margin-left : -500px;
     }
   -------- 或  -------------------
   #continer {
       text-align : left;
       width : 1000px;
       height : 400px;
       margin : 0px auto; /*firefox居中*/
    }

    body {
       padding : 0px;
       margin : 0px;
       text-align : center;  /*IE居中*/
    }

5、控制器的职责
    /**
* 控制器的处理流程
* 1、获取请求参数
* 2、验证请求参数
* 3、处理用户请求(访问业务组件)
* 4、处理异常
* 5、为视图准备数据(将数据放入模型[model])
* 6、选择视图生成响应
*/

6、Action不是Servlet

7、Struts2的Action每次请求创建一个

8、输入校验
     a>、Action继承ActionSupport,覆盖validate()方法
b>、在参数格式不满足条件是调用addFieldError();
c>、只有调用过addFieldError()方法,代表验证失败,如果验证失败不会再执行execute()方法
d>、校验失败时action的执行结果为input,需要在struts.xml中添加name为input的result
e>、在jsp页面中要显示验证失败的错误消息,需要使用struts2的标签<s:fielderror/>

9、struts2框架自身可能产生5种result
    success
none
error
input
login

10、捕获请求参数
    a>、将请求参数设置为Action的属性
    <tr>
   <td width="70" align="right">用户名:</td>
   <td>
       <input type="text" name="username" />
   </td>
</tr>
<tr>
   <td align="right">密码:</td>
   <td>
       <input type="password" name="password" />
   </td>
</tr>

public class Reg1Action extends ActionSupport {
            private String username;
            private String password;
     }
   b>、直接将请求参数封装为对象
                <tr>
   <td width="70" align="right">用户名:</td>
   <td>
       <input type="text" name="user.username" />
   </td>
</tr>
<tr>
   <td align="right">密码:</td>
   <td>
       <input type="password" name="user.password" />
   </td>
</tr>

public class Reg1Action extends ActionSupport {
            private User user;
     }
   c>、使用模型驱动(ModelDriven)
                <tr>
   <td width="70" align="right">用户名:</td>
   <td>
       <input type="text" name="username" />
   </td>
</tr>
<tr>
   <td align="right">密码:</td>
   <td>
       <input type="password" name="password" />
   </td>
</tr>

          public class Reg1Action extends ActionSupport implements ModelDriven<User> {
            private User user;
public User getModel() {
                    if(user == null) {
                        user = new User();
}
return user;
}
      }

  默认情况下,请求参数是绑定至Action对象的属性,如果Action实现了ModelDriven接口,请求参数将不再绑定至Action,而是
  getModel()方法返回的对象上
11、Action如何向JSP传递数据
    a>、使用Action的属性
private String msg;
public String getMsg() {
return msg;
}

@Override
public String execute() throws Exception {
msg = "用户注册成功!";
return "message";
}

    b>、使用ActionContext
public String execute() throws Exception {
new UserServiceBean().save(user); // 执行保存
ActionContext.getContext().put("msg", "@@用户注册成功");
return "message";
}


12、访问Servlet api

    HttpServletRequest    :
     getParameter()        : 获取请求参数
getParameterValues()
getHeader("")
getContextPath()
getCookies()
setAttrbute(key,value)  : 共享数据
getRequestDispatcher().forward()  : 转发
HttpServletResponse
    addHeader() : 添加响应头
addCookie() : 添加Cookie
sendRedirect() : 重定向
HttpSession
        get/setAttribute()
invalidate() : 销毁session
ServletContext
   get/setAttribute()
   getRealPath()

a>、如果只是为了共享数据,可以使用Map
     aa>、直接获取
          Map<String, Object> session =  context.getSession(); //获取用于存储数据的map对象
  Map<String, Object> application = context.getApplication();
  String company = (String) session.get("company");
  session.put("data", "a session scope data");
  application.put("data", "a application scope data");
bb>、依赖注入

         public class ServletApi2Action extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {
   private Map<String,Object> request;
   private Map<String,Object> session;
   private Map<String,Object> application;

@Override
public void setRequest(Map<String, Object> request) {
System.out.println("call setRequest()");
this.request = request;
}

@Override
public void setApplication(Map<String, Object> application) {
this.application = application;

}

@Override
public void setSession(Map<String, Object> session) {

this.session = session;
}
}

b>、如果要执行其它操作,则必须使用原生对象
     aa>、直接获取
          HttpServletRequest request = ServletActionContext.getRequest();
  HttpServletResponse response = ServletActionContext.getResponse();
  HttpSession session = request.getSession();
ServletContext application = ServletActionContext.getServletContext();
bb>、依赖注入
      public class ServletApi4Action extends ActionSupport implements
      ServletRequestAware, ServletResponseAware, ServletContextAware {
private HttpServletRequest request;
private HttpServletResponse response;
private HttpSession session;
private ServletContext application;

@Override
public void setServletContext(ServletContext application) {
this.application = application;
}

@Override
public void setServletResponse(HttpServletResponse arg0) {
this.response = arg0;

}

@Override
public void setServletRequest(HttpServletRequest arg0) {
this.request = arg0;
this.session = request.getSession();
}
         }


13、一个Action处理多个请求
    a>、一个Action类有多个与execute()相似签名的方法,每个方法处理一个请求
         public class UserAction extends ActionSupport {
public String save() throws Exception {
return "message";
}

public String update() throws Exception {
return "message";
}

public String delete() throws Exception {
return "message";
}
         }

  b>、从struts2.3开始不可使用
     <a href="userMgr!save.action">添加用户</a>
     <a href="userMgr!update.action">修改用户</a>
     <a href="userMgr!delete.action">删除用户</a>

      c>、动态方法调用
        <!-- {1}代表第一个*号的值 -->
       <action name="user_*" class="com.sxt.struts2.web.action.UserAction" method="{1}">
           <result name="message">/WEB-INF/jsp/message.jsp</result>
       </action>

   <a href="user_save.action">添加用户</a>
   <a href="user_update.action">修改用户</a>
   <a href="user_delete.action">删除用户</a>
     d>、更复杂的示例
User_add.action,Employee_delete.action,Dept_query.action
<action name="*_*" class="xxx.action.{1}Action" method="{2}">
  <result name="input">/WEB-INF/jsp/{1}/{2}.jsp</result>
</action>


14、struts.xml中的配置项
    <struts>
       <bean class=""/> <!--注册bean组件-->
       <!-- 注册未知处理器 -->
   <unknown-handler-stack>
          <unknown-handler-ref name=""></unknown-handler-ref>
       </unknown-handler-stack>
       <include file="user.xml"/> <!-- 包含另一个配置文件-->
       <!-- 修改struts2工作中的一些设定 ,可修改的设定来自于struts2-core-2.x.xx.jar中org.apache.struts2包中default.properties-->
       <constant name="struts.i18n.encoding" value="utf-8"></constant> <!-- post请求参数的字符集 -->
   <!-- 抽象包中不能定义action -->
<!-- 一个action请求路径由 package的namespace + action的name属性组成 -->
<package name="default" extends="struts-default" abstract="false" namespace="/system/base">
             <!-- 注册result解析器类 -->
<result-types>
<result-type name="sxt" class="com.sxt.struts2.result.TestResult"></result-type>
</result-types>

<!-- 注册拦截器 -->
<interceptors>
<interceptor name="test" class="com.sxt.struts2.web.interceptor.TestInterceptor"></interceptor>
<!-- 用于将多个拦截器组合成一个 -->
<interceptor-stack name="testStack">
<interceptor-ref name="test"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

   <!-- 指定默认的拦截器 -->
  <default-interceptor-ref name="testStack"/>

<!-- 指定默认的Action类 <action name="" > -->
<!-- <default-class-ref class=""></default-class-ref> -->

<!-- 指定默认的action -->
<default-action-ref name="default"/>
<!-- 全局result设定,可以被该包中的所有action使用 -->
<global-results>
<result name="message">/WEB-INF/jsp/message.jsp</result>
</global-results>

<!-- 全局的异常处理声明 -->
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"/>
</global-exception-mappings>


<action name="test">
<result>/WEB-INF/jsp/message.jsp</result>
</action>

<action name="result" class="com.sxt.struts2.web.action.ResultAction">
<!-- 当action的执行结果为a时,由sxt所对应的解析器类生成响应 -->
<result name="a" type="sxt">
<param name="location">/WEB-INF/jsp/message.jsp</param>
</result>

  <!-- 声明Action需要使用哪些拦截器,一旦使用该元素,则默认拦截器不再有效 -->
<!--
<interceptor-ref name="test"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
-->

            </action>
</package>
</struts>

15、result的设定 (决定如何生成响应)
<!-- 转发至一个jsp -->
<result name="a" type="dispatcher">
<param name="location">/WEB-INF/jsp/message.jsp</param>
</result>

<!-- 重定向至一个jsp -->
<result name="b" type="redirect">
<param name="location">/WEB-INF/jsp/message.jsp</param>
</result>
<!-- 转发至一个Action -->
<result name="c" type="chain">
<param name="namespace">/aaa</param>
<param name="actionName">other</param>
</result>

<!-- 重定向至一个Action -->
<result name="d" type="redirectAction">
<param name="namespace">/aaa</param>
<!--动态传参 -->
<param name="actionName">other?username=${name}</param>
</result>

<!-- 文本响应 -->
<result name="e" type="plainText">
<!-- Content-Type : text/plain;charset=utf-8 -->
<param name="location">/WEB-INF/jsp/message.jsp</param>
<param name="charSet">utf-8</param>
</result>

   a>、转发操作,向下一个组件传值,直接将值存入ActionContext
        ActionContext.getContext().put(key,value);
   b>、重定位操作向下一个组件传值需要使用请求参数


16、拦截器(Interceptor)
     a>、编写一个类,实现Interceptor接口或继承AbstractInerceptor,完成String interceptor(ActionInvocation ai)方法
        public class TestInterceptor extends AbstractInterceptor /*implements Interceptor*/  {
/**
* 返回值为result
*/
@Override
public String intercept(ActionInvocation ai) throws Exception {
System.out.println("before...............");
String result = ai.invoke();  //放行
System.out.println("after.............\n");
return result;
}

}
    b>、在struts.xml注册拦截器
    <interceptors>
             <interceptor name="test" class="com.sxt.struts2.web.interceptor.TestInterceptor"/>
        </interceptors>


    c>、在action元素中声明该action所需要的拦截器
       <action name="aaa" class="xxx.XxxAction">
             <!-- 声明Action需要使用哪些拦截器,一旦使用该元素,则默认拦截器不再有效 -->
             <interceptor-ref name="test"></interceptor-ref>
             <interceptor-ref name="defaultStack"></interceptor-ref>
   </action>

17、国际化

    a>、实现步骤
    aa>、将页面中要显示的文字用特定的key编号后写到国际化资源文件中(可以有很多份,每份对应一个Locale,key相同,对应的文字不相同)
      Message.properties,Message_zh_CN.properties,Message_en_US.properties

        bb>、在struts.xml中注册国际化资源
             <constant name="struts.custom.i18n.resources" value="Message"/>
        cc>、在jsp页面中,使用s:text标签输出国际化消息
      <s:text name="login.title"/>

    b>、用户切换语言
    defaultStack中有一个名字为i18n的拦截器,它会检查请求参数中是否有一个名字为request_locale的请求参数,
如果有,则将该参数的值为转换为对应的Locale对象,并存入session,作为国际化的依据
        <a href="i18n_login.action?request_locale=zh_CN">中文</a>
<a href="i18n_login.action?request_locale=en_US">English</a>

   c>、在Action中要获取国际化消息使用getText(key)方法

   d>、struts2的国际化资源文件分为四种类型
       aa>、全局,在struts.xml注册的
   bb>、包范围,在action所在包中名字package的国际化资源文件: package.properties,package_zh_CN.properties
   cc>、Action范围,在action所在包中名字为Action名字的国际化资源文件: LoginAction.properties
   dd>、临时的,在使用时使用<s:i18n/>标签绑定的国际化资源文件
        <s:i18n name="com.sxt.struts2.resource.Hello">
                  <li> <s:text name="i18n.key2"></s:text> </li>
             </s:i18n>

       ee>、优先级为 : Action范围 > 包范围  > 全局范围

18、文件上传
   a>、在struts2框架中,文件上传操作是由defaultStack栈中一个名称为fileupload的拦截器完成的,该拦截器会检查请求是否是
       一个文件上传请求,如果是就会自动完成上传,并保存至服务器端临时目录中的一个临时文件中
   b>、前置条件
     <form action="upload.action" method="post" enctype="multipart/form-data">
          <input type="file" name="photo" />
</form>

   c>、Action开发

      public class UploadAction extends ActionSupport {
private File photo; // 指向了上传至服务端的临时文件
private String photoFileName; // 上传文件的文件名
private String photoContentType; // 上传文件的MIME类型

@Override
public String execute() throws Exception {
//文件上传
if(photo != null) {
   ServletContext context = ServletActionContext.getServletContext();
   String path = context.getRealPath("/WEB-INF/photos/" + photoFileName); //获取要保存文件的真实路径
   File dest = new File(path);
//文件复制
   FileUtils.copyFile(photo, dest);
}
return "message";
}
     }

   d>、控制文件上传的大小(默认最大2M)与类型
        aa>、在default.properties中有一个常量
      struts.multipart.maxSize=2097152    (产生actionError,使用<s:actionerror/>输出错误消息)
              <constant name="struts.multipart.maxSize" value="20971520"></constant>

    bb>、fileupload拦截器也定义了一个参数maximumSize (产生fieldError,使用<s:fielderror/>输出错误消息)
              <action name="upload" class="com.sxt.struts2.web.action.UploadAction">
<result name="input">/WEB-INF/jsp/file_upload.jsp</result>
<interceptor-ref name="defaultStack" >
<param name="fileUpload.maximumSize">10485760</param>
</interceptor-ref>
</action>

        cc>、如果上传失败,Action的执行结果为input,所以在action中应配置一个名称为input的result

        dd>、控制上传文件的类型,修改fileUpload拦截器的allowedTypes参数的值

ee>、错误消息的本地化,在应用国际化资源文件中,重新定义以下消息key的值
              struts.messages.error.file.too.large=\u4E0A\u4F20\u6587\u4EF6\u8D85\u8FC7\u6700\u5927\u5927\u5C0F!
  struts.messages.error.content.type.not.allowed=\u6587\u4EF6\u683C\u5F0F\u4E0D\u6B63\u786E!
  struts.messages.error.uploading =\u6587\u4EF6\u4E0A\u4F20\u51FA\u9519!
  struts.messages.upload.error.SizeLimitExceededException=\u4E0A\u4F20\u6587\u4EF6\u8D85\u8FC7\u6700\u5927\u5927\u5C0F!


19、文件下载
     a>、使用StreamResult即可
        <action name="download" class="com.sxt.struts2.web.action.DownloadAction">
           <result name="success" type="stream">
               <!-- 设定Content-Type响应头的值 -->
               <param name="contentType">application/octet-stream</param>
               <!-- 设定通访问Action的哪个属性(类型为InputStream)可以得到要下载文件的数据 -->
   <param name="inputName">fileData</param>
   <!-- 设定Content-Disposition响应头的值,产生下载对话框 -->
   <param name="contentDisposition">attachment; filename=${filename}</param>
           </result>
        </action>
b>、 Action中应有一个public InputStream getFileData(),在该方法中返回要下载文件的数据
       public InputStream getFileData() {
if (filename == null) {
return null;
}
ServletContext context = ServletActionContext.getServletContext();
return context.getResourceAsStream("/WEB-INF/photos/" + filename);
   }

   c>、中文文件名的处理
        aa>、获取请求参数时进行转码
public void setFilename(String filename) {
if (filename != null) {
try {
filename = new String(filename.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
this.filename = filename;
}
       bb>、产生下载对话框中的中文文件名:attachment; filename=${filename}
         public String getFilename() {
if (filename == null) {
return null;
}
//判断浏览器
HttpServletRequest request = ServletActionContext.getRequest();
String agent = request.getHeader("User-Agent");
try {
if(agent.contains("Firefox")) {  //火狐
return "=?UTF-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
} else {
return URLEncoder.encode(filename, "utf-8");
}
} catch (UnsupportedEncodingException e) {
return filename;
}
}

20、类型转换
      a>、所有的请求参数都是String或String[]类型,但服务器端可能期望是其它类型,如Date,int等,这就涉及到类型转换,
      Struts2框架可以自动处理类型转换,只要有对应的类型转换器(TypeConverter)

      b>、类型转换失败,action执行结果为input,并会以xwork.default.invalid.fieldvalue为key产生fielderror,可以在input视图使用<s:fielderror/>输出类型转换失败的错误消息


  c>、如果要改变错误消息,只需要在国际化资源文件中重新定义该key的值

      d>、如果目标类型(User)所应的转换器不存在,则不能转换,此时可以开发自己的类型转换器
      aa>、编写一个类实现TypeConverter接口,一般继承StrutsTypeConverter
       public class AddressTypeConverter extends StrutsTypeConverter /*implements TypeConverter*/ {
/**
* 字符串转对象
*/
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
/*if(toClass == Address.class) {
}*/
if(values == null || values.length == 0) {
return null;
}
String sAddr = values[0]; //获取请求参数的值
//将请求参数转换为Address类的对象
String[] aAddr = sAddr.split(",");
if(aAddr.length != 3) {
throw new IllegalArgumentException("请求参数addr格式不正确!");
}
return new Address(aAddr[0], aAddr[1], aAddr[2]);
}

/**
* 对象转字符串
*/
@Override
public String convertToString(Map context, Object o) {
if(o == null) {
return null;
}
Address addr = (Address)o;
return "province = " + addr.getProvince() + ",city = " + addr.getCity() + ",area= " + addr.getArea();
}
}

bb>、注册类型转换器
      aaa>、局部的,只对某一Action有效,在Action所在包中定义一个名字为ActionName-conversion.properties
        addr = com.sxt.struts2.web.converter.AddressTypeConverter
  bbb>、全局的,对所有Action都有效,在classpath的根下定义一个名字为xwork-conversion.properties的文件
        com.sxt.struts2.model.Address = com.sxt.struts2.web.converter.AddressTypeConverte


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

21、输入校验(服务器端的校验)

a>、覆盖validate()方法,编码校验
           aa>、一个Action只处理一个请求,只需要覆盖validate()方法

   bb>、一个Action处理多个请求,不同的请求有不同的校验规则,对应不同的验证方法
                 处理请求的方法为 save(),则对应的验证请求参数的方法为 validateSave()
如果有validate()方法,则任何一个请求都会执行

b>、使用验证框架,写配置文件实现校验(Action中不写validate()方法)
           aa>、一个Action只处理一个请求
        在Action类所在包装创建一个名称为: Action类名-validation.xml(如:RegAction-validation.xml)
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
   <field name="username">  <!-- 请求参数 -->
<!-- 验证规则,可用规则来自于xwork-core.xxx.xx.jar中com.opensymphony.xwork2.validator.validators包下default.xml -->
   <field-validator type="requiredstring">
<message>@@用户名不能为空!</message>
   </field-validator>
   <field-validator type="stringlength">
   <param name="minLength">5</param>
   <param name="maxLength">10</param>
   <message>@@用户名的长席必须在5~10位之间</message>
   </field-validator>
   </field>
                  </validators>
   bb>、一个Action处理多个请求,不同的请求有不同的校验规则
                假设Action类名为: Reg4Action,添加操作请求的action的名字为reg4_save.action,则验证文件的名称为:Reg4Action-reg4_save-validation.xml




22、OGNL : Object Graph Navigation Language(对象图导航语言)
      a>、ognl类似于EL,其作用就是进行表达式求值,主要用于struts2的标签
       JSP的开发:  EL + JSTL
               OGNL + struts2 tag


      b>、ognl中的变量求值
      <s:property value="a + b"/>
  aa>、EL表达式中的变量值来自于四个作用域

          bb>、OGNL表达式中的数据存储 ValueStack与Stack Context(在struts2中为ActionContext)
      aaa>、ValueStack中存入的是对象

  bbb>、Stack Context是一个Map结构,存放的是一些key -> value格式的数据

  ccc>、变量名以#开头,以变量名为key,从Stack Context中取数据

  ddd>、变量名不以#开头,从ValueStack栈顶对象开始,依次检栈中对象是否有该属性,有则返回该属性的值,如果栈中对象都没有该属性,再以变量名为key,从Stack Context中找
        <s:property value="username"/> : 先检查栈顶对象是否有username属性,有则返回该属性的值,若没有,检查栈的下一个对象

  eee>、当请求到来,Struts2框架会把请求的Action对象放在值栈的栈顶

      c>、当每次请求到来时,Struts2框架会为本次请求初始化一个ActionContext对象,
      并将与请求处理相关的数据(请求参数,Action对象,作用域中的数据)全部存储在ActionContext中

      d>、Stack Context默认有以下key的数据
       request : 所有request作用域的数据
   session : 所有session作用域的数据
   application : 所有application作用域的数据
   attr : 以上三个作用域的数据
   parameters : 所有请求参数
   action : 当前请求的Action对象


      e>、在struts2中为什么EL表达式可以访问Action的属性
      因为在struts2框架中,request对象被做了包装
  正常情况下:  request.getAttribute() 只能获取 request.setAttribute()的值
  改写之后,使得request.getAttribute()不但可以访问request.setAttribute()的数据,还可以访问ValueStack与stack context中的数据,查找过程等同于不加#
          简单的说在struts2中: ${requestScope.username} = request.getAtribute("username") + <s:property value="username"/>

22、Struts2的标签库
    a>、非UI标签
        <s:head/>  : 导入标签库所需的css,js
<s:fielderror/> : 输出addFieldError()的消息
        <s:actionerror/> : 输出addActionError()的消息
        <s:actionmessage/> : 输出addActionMessage()的消息
<s:i18n name="com.sxt.resource.Message"/>  : 绑定国际化资源文件
<s:text /> : 输出国际化消息
<s:property value="ognl"/> : 输出一个OGNL表达式的求值结果,不指定value属性,输出栈顶对象
<s:debug /> : 查看ValueStack与Stack Context中数据

<s:a action="tag2" namespace="/">UI标签示例</s:a> : 生成一个超链接
<s:a value="/index.jsp?username=%{#user1.username}">首页</s:a>  : %{} : 强制将其中的内容作为ognl表达式解析
<s:action name="tag3" executeResult="false"/>  : 调用一个Action
        <s:bean name="com.sxt.struts2.bean.User" var="user1" /> :创建一个bean对象,指定var,将创建的对象放入Stack context中,不指定,放入ValueStack,并在标签结束是从ValueStack中删除
        <s:param name="username">张三</s:param>   : 设置参数值
<s:param name="username" value="#username"/>  : value属性是一个ongl表达式

<s:date />  : 格式化日期
<s:number /> : 格式化数字
        <s:include value="/index.jsp"  /> : 包含另一个页面
<s:push/> : 将一个对象放至ValueStack的栈顶,并在标签结束时删除

<s:set /> :向stack context或作用域中放值
<s:url /> : 生成一个url
<s:if/> <s:elseif/> <s:else/>  : 分支选择
<s:iterator/> : 循环

b>、UI标签
   <s:form>
       <s:hidden />
   <s:textfield/>
   <s:password/>   
   </s:form>
   




























上一篇:spring学习笔记
下一篇:Hibernate学习笔记

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客