zoukankan      html  css  js  c++  java
  • struts2基本介绍

    前言


    文本


    Struts2


    Apache SoftWare Foundation Tomcat/Struts1/Struts2/Ibaitas/


    MVC框架:Struts1/Struts2/JSF/WebWork


    Struts2是由Apache软件基金会与webWork的研发团队合作开发
    www.apache.org
    Struts2是一个单控制器的开源免费的框架。



    框架搭建


    1.新建WEBproject导入JAR包 


    antlr-2.7.2.jar  语法解析器
    commons-beanutils-*.jar  commons项目下用来处理Bean的工具包
    commons-chain-*.jar   commons项目下用来处理流程链的
    commons-collections-*.jar commons项目下全部集合处理的工具包
    commons-digester-*.jar  将xml解析成 java对象
    commons-fileupload-*.jar 文件上传的
    commons-io-*.jar 处理IO流
    commons-lang-*.jar 处理普通java对象的
    commons-logging-*.jar commons项目下日志处理工具包
    commons-logging-api-*.jar commons项目下日志处理工具包
    commons-validator-*.jar   commons项目下处理验证
    oro-*.jar 文本文件处理的
    freemarker-*.jar freemarker模版语言相关的
    struts2-core-*.jar Struts2核心包
    xwork-*.jar webwork核心包,包涵非常多command
    ognl-*.jar  Struts2表达式语言

    以上这些包在搭建Struts2框架时必须导入
    其它jar包:

    *-plugin-*.jar 以plugin结束的是其它框架与Struts2整合的插件包


    2.拷贝配置文件


    struts.xml  struts2的配置文件
    web.xml 核心控制器的配置文件
    在2.1.6版本号之前使用的核心控制器 FilterDispatcher

    2.1.6版本号之后org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter



    3.測试框架搭建




    实现Action


    1.实现Action接口实现接口中定义的全部方法


    implements Action
    Action接口中定义了五个字符串常数以及一个 public String execute() throws Exception;
    五个常数:
    SUCCESS-->"success"
    NONE-->"none"
    INPUT-->"input"
    ERROR-->"error"

    LOGIN-->"login"


    2.普通类,必须含有一个无參的返回值为String类型的execute方法


    public class LoginAction2 {
    public String execute(){
    System.out.println("LoginAction2");
    return "success";
    }

    }


    *3.通过继承ActionSupport来实现自己定义Action


    public class LoginAction3 extends ActionSupport{

    @Override
    public String execute() throws Exception {
    System.out.println("LoginAction3--execute");
    return SUCCESS;
    }

    }


    Struts.xml中对于Action的配置


    package标签用来管理Action
    name属性:区分package
    namespace:定义的是package中Action的訪问路径

    extends:配置文件通过继承的方式实现其它配置文件里定义的属性


    <package namespace="/user" name="user" extends="struts-default">
    Action标签用来配置相应的Action实现
    name属性:配置Action的訪问路径
    class属性:配置当前Action标签相应的实现类
    <action name="loginAction" class="" >
    Result标签用来配置Action返回的页面
    name属性:匹配Action的字符串返回值定位相应的返回页面
    type属性:定义页面返回到浏览器的方式
    <result>/success.jsp</result>
    </action>

    </package>




    接收前台页面參数


    1.接收单个參数


    public class LoginAction3 extends ActionSupport{
    //定义一个參数成员变量
    private String userName;
    //提供getter/setter
    public String getUserName() {
    return userName;
    }

    public void setUserName(String userName) {
    this.userName = userName;

    }


    JSP页面:


    <input type="text" name="userName">
    name属性的值必须和Action中成员变量的名称同样

    2.通过对象接收參数


    public class LoginAction2 {
    private User user;
    public User getUser() {
    return user;
    }
    public void setUser(User user) {
    this.user = user;

    }


    JSP页面:
    <input type="text" name="user.userName">

    3.ModelDriven接收參数


    public class LoginAction implements Action,ModelDriven{
    private User user = new User();
    public User getUser() {
    return user;
    }
    public void setUser(User user) {
    this.user = user;
    }
    public Object getModel() {
    return user;
    }
    }

    JSP页面:
    <input type="text" name="userName">
    name属性的值必须和Action中对象的属性名同样

    关于參数接收:
    通常通过继承ActionSupport方式来实现Action
    在接收參数方面,经常使用普通成员变量和对象类型两种
    假设通过Action接收方式接收对象类型參数。必须在创建相应引用时初始化

    Action中使用作用域


    1.通过ActionContext来设置作用域 


    ActionContext对象所表示的是当前Action对象的执行环境
    //通过静态方法获得对象,ActionContext为线程单例
    ActionContext context = ActionContext.getContext();
    //request.setAttribute();
    context.put("requestScope", "req");
    //session
    Map session = context.getSession();
    session.put("sessionScope", "session");
    //ServletContext
    Map app = context.getApplication();
    app.put("app", "application");

    2.通过ServletActionContext对象来设置作用域


    //通过ServletActionContext来获得request对象
    //ServletActionContext单例
    HttpServletRequest request = ServletActionContext.getRequest();
    request.setAttribute("requestScope", "requestScope");
    HttpSession session = request.getSession();
    session.setAttribute("sess", "sessionScope");
    ServletContext context = session.getServletContext();

    context.setAttribute("app", "app");


    3.通过实现ServletRequestAware接口来设置作用域


    //设置HttpServletRequest成员变量接收接口中传递的request參数
    public class TestServletRequest extends ActionSupport implements ServletRequestAware{
    private HttpServletRequest request;
    public void setServletRequest(HttpServletRequest request) {
    this.request = request;
    }

    參数接收过程中的类型转换


    1.自己定义类型转换


    a.參数类型转换类。必须继承StrutsTypeConverter


    public class DateConverter extends StrutsTypeConverter{
    /**
    * 将String类型的參数转换成特定对象类型
    * @param Map context ActionContext 对象
    * @param String[] values 參数数组
    * @param Class toClass
    */
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {

    /**
    * 将特定对象类型转换成String类型
    * @param Map context ActionContext 对象
    * @param Object o 目标对象
    */
    @Override
    public String convertToString(Map context, Object o) {

    b.配置參数接收过程中的配置文件


    局部转换器:针对特定Action,配置文件放置在相应Action同样文件夹下


    Action类名-conversion.properties
    TestParametersAction-conversion.properties
    配置内容:
    Action类中特定对象类型的成员变量名称 = 转换类的全限定名
    birthday = com.zhongx.struts2.day2.DateConverter
    全局转换器:对projectAction中全部特定类型,将配置文件存储在SRC下
    xwork-conversion.properties
    配置内容:
    特定转换的对象类型 = 转换类的全限定名
    java.util.Date = com.zhongx.struts2.day2.DateConverter

    后台验证


    通过继承ActionSupport重写validate方法来实现


    validate方法会在运行execute方法之前先被调用进行输入參数格式校验
    //通过validate方法进行校验
    @Override
    public void validate() {
    System.out.println("validate");
    String name = users.get(0).getUserName();
    int age = users.get(0).getAge();
    if(name==null || "".equals(name)){
    //将错误提示信息设置到错误信息域中
    this.addFieldError("error", "name is null");
    }else if(age>200||age<0){
    this.addFieldError("error", "age is error");
    }else{
    System.out.println("ok");
    }
    }

    一旦错误信息域中有错误提示。那么Struts2默认会查找相应Action配置中
    <result name="input"> 所相应的jsp返回
    <result name="input">/error.jsp</result>
    那么在错误页面:
    通过struts2标签来获取错误信息:
       <s:fielderror><s:param>error</s:param></s:fielderror>

    前台JS校验 Struts2后台校验


    有点: 校验不须要经过server,运行效率高 安全
    缺点: 不安全。easy被用户篡改 校验必须连接server,运行效率低
    建议:前台js校验和后台Struts2校验并用。




    Struts2文件上传下载


    文件上传:


    1.前台jsp页面


    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="pic">

       </form>


       2.后台程序參照TestFileUploadAction



    文件下载


    參照TestFileDownAction



    配置文件
    <action name="fileDownAction" class="com.zhongx.struts2.day3.TestFileDownAction">
    <result name="down">/list.jsp</result>
    配置下载结果类型 type = stream
    <result name="fileDown" type="stream">
    stream类型的结果类型接收两个參数
    inputName 名称的參数是Action中的输入流
    <param name="inputName">downFileInput</param>
    contentDisposition 參数设置文件的展示方式以及下载 时的默认文件名
    <param name="contentDisposition">attachment;fileName=${file}</param>
    </result>
    </action>


    Action中方法的动态调用


    1.通过。+方法名称显示调用
    调用dynaMethodAction中的相应的add方法
    dynaMethodAction!add
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    2.通过配置文件设置调用的方法名称
    通过method属性设置默认调用的方法
    <action name="dynaMethodAction" class="com.zhongx.struts2.day4.TestDynaMethodAction" method="delete">
    </action>
    3.通过*通配符匹配调用方法
    //method中通过动态获得调用的方法的方法名
    //调用过程中dynaMethodAction_方法名称
    <action name="dynaMethodAction_*" method="{1}" class="com.zhongx.struts2.day4.TestDynaMethodAction">
    <result name="ok">{1}_success.jsp</result>

    Struts2的国际化


    Internationalization(i18n)


    1.在src文件夹下新建资源文件


    资源文件名_语言简写_国别简写.properties
    appRes_zh_CN.properties
    文件内容:
    key = value  //user=u7528u6237u540D
    //user = userName
     

    2.将资源文件配置在Struts.xml中


    <constant name="struts.custom.i18n.resources" value="资源文件名"></constant>

    3.获得匹配国家的语言


    占位符
    <s:text name="key"></s:text>
    // <s:text name="user"></s:text>
     
    在浏览器显示时依据浏览器的国别设置获得相应的语言显示

    在书写资源文件时,假设相应国家的语言是非拉丁语系的语言,那么资源文件必须经过Unicode编码
    user=u7528u6237u540D
    手动将资源文件转换成Unicode编码
    native2ascii  命令转换 native2ascii -encoding gbk 输入文件   输出文件


    Struts2的result type


    <result name="" type="xxxx">
    type = dispatcher 默认,从Action到前台页面的转发
      chain      从Action到Action的转发
      redirect      从Action到前台页面的重定向
      redirectAction  从Action到Action的重定向
      stream     向浏览器输出一个InputStream类型的流,一般用作文件下载
      freemarker 向浏览器输出freemarker模版
      velocity 向浏览器输出velocity模版
      xslt 向浏览器输出xml/xslt模版
      plainText 向浏览器原样输出(输出源文件)
      httpheader 控制特定HTTP协议的输出
      

    自己定义的Result type类型


    1.定义type实现类


    public class TestResult implements Result

    2.配置Result type类型


    a.定义type类型而且绑定实现类


    <package name="day4" namespace="/" extends="struts-default">
    <result-types>
    <result-type name="type名称" class="实现类的全限定名称"></result-type>
    </result-types>

    b.使用自己定义的type


    <action name="" class="">
    <result name="" type="自己定义type名称" ></result>

    还能够通过继承StrutsResultSupport来实现自己定义result类型
    实现doExecute方法


    拦截器(Interceptor)



    认识拦截器

    struts-default.xml
    标签
    <interceptors>
    <interceptor name="拦截器名称" class="拦截器的实现类"></interceptor>
    </interceptors>

    Action中应用拦截器
    <action>
    <interceptor-ref name="引入拦截器的名称"></interceptor-ref>
    </action>

    默认Struts.xml中
    <package name="" namespace="" extends="struts-default">
    默认当前包中的 Action继承struts-default中使用的拦截器
    struts-default默认使用
    拦截器栈 defaultStack
    拦截器栈中引入18个经常使用拦截器
    比方 :
    i18n
    fileUpload
    params
    workflow等
    </package>

    自己定义的拦截器


    a.通过实现接口来实现自己定义拦截器



    b.通过继承AbstractInterceptor来实现拦截器


    //通过继承父类的形式来实现拦截器
    public class MyInterceptor3 extends AbstractInterceptor{
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
    String path = invocation.invoke();
    return path;
    }
    }


    配置自己定义拦截器


    a.直接引用
    <package name="day5" namespace="/" extends="struts-default">
    <!-- 配置自己定义的拦截器以及功能实现类 -->
    <interceptors>
    <interceptor name="myInte1" class="com.zhongx.struts2.day5.MyInterceptor1"></interceptor>
    </interceptors>
    <action name="testIntercepter" class="com.zhongx.struts2.day5.TestInterceptorAction">
    <!-- 使用自己定义的拦截器 -->
    <interceptor-ref name="myInte1"></interceptor-ref>
    <result name="ok">/success.jsp</result>
    <result name="success">/index.jsp</result>
    </action>
    </package>
    b.通过配置拦截器栈来引用



    表单反复提交


    问题:同一个表单携带同样的数据被提交多次

    通过Struts2的拦截器   token来处理多次提交问题


    <interceptors>
    <interceptor-stack name="my_stack">
    <interceptor-ref name="token"></interceptor-ref>
    <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
    </interceptors>

    在Action中使用自己定义的拦截器栈
    <action name="testToken" class="com.zhongx.struts2.day4.TestTokenAction">
    <interceptor-ref name="my_stack"></interceptor-ref>

    <result name="ok">/success.jsp</result>
    <!-- 一旦反复提交。那么token拦截器会返回invalid.token 来查找相应的返回结果-->
    <result name="invalid.token">/error.jsp</result>

    </action>

    在JSP页面


    表单中增加<s:token></s:token>标签来标识是否为同一表单
    <form action="testToken">
      <s:token></s:token>
      username:<input id="name" type="text" name="userName">
      年龄:<input id="age" type="text" name="age">
      <input type="submit" value="submit">

       </form>


    方法级别的拦截器


     继承MethodFilterInterceptor来实现拦截器
    String doIntercept(ActionInvocation)
    配置文件
    <package name="day6" namespace="/" extends="struts-default">
    <!--配置拦截器实现类-->
    <interceptors>
    <interceptor name="methods" class="com.zhongx.struts2.day6.TestMethodInterceptor"></interceptor>
    </interceptors>

    <action name="testMethod" class="com.zhongx.struts2.day6.TestMethodInterceptorAction">
    <!--引入拦截器-->
    <interceptor-ref name="methods">
    <!-- 不被拦截的方法  -->
    <param name="excludeMethods">login</param>
    <!-- 被拦截的方法 -->
    <param name="includeMethods">add,delete,execute</param>
    </interceptor-ref>

    <result name="exe">/success.jsp</result>
    <result name="delete">/delete_success.jsp</result>
    <result name="add">/add_success.jsp</result>
    <result name="login">/login.jsp</result>
    </action>
    </package>


    OGNL和值栈以及Struts2标签


    OGNL(Object Graphic Navigation Language,对象图导航语言)
    方便开发者查找对象,高速的获得对象的属性和相应的值
    OGNL从值栈中获取对象方便,可以高速从复杂类型对象(树形文件夹结构非常深)中获取属性
    在没有Struts2前webWork框架中已经採用了OGNL来获取属性
    使用OGNL必须 导入OGNL.jar



    Action对象,其它对象
    (root区)

    ValueStack (context,context用OGNL訪问必须加#号)
    paramters 包涵HTTP请求參数的对象 
    request  HTTP请求对象
    session   HTTP会话对象
    application  当前应用对象
    attr 包涵作用域对象

    OGNL訪问属性必须结合Struts2标签使用


    基本标签


    获取属性值
    <s:property value="">
    格式化日期
    <s:date name="" format="">
    向作用域设值
    <s:set var="test" value="users[0]" scope="action"></s:set>
    设置路径
    <s:url value="/testAction" ></s:url>
    创建对象
    <s:bean name="com.zhongx.struts2.day1.User" var="uu">
    设置參数
    <s:param name="userName">testBean</s:param>
    </s:bean>
    将对象设置在root区,标签结束对象回收
    <s:push value="users[0]">
    <s:property value="userName"/>
    <s:property value="age"/>
    <s:property value="address.street"/>
    </s:push>
    分支控制
    <s:if test="users[0].age>0">
    </s:if>
    <s:elseif>
    </s:elseif>
    <s:else>
    </s:else>

    迭代标签
    <!-- 
    ?

    表示选出符合条件的全部对象
    ^表示符合条件的第一个对象
    $表示符合条件的最后一个对象
    users.{$#this.age>1}
    -->
    <s:iterator var="u" value="users.{$#this.age>1}" status="status"><br>
    <s:property value="#u.userName"/>
    <!-- 循环下标 -->
    <s:property value="#status.index"/>
    <!-- 循环记录数 -->
    <s:property value="#status.count"/>

    </s:iterator>

    获得值栈
    <s:debug></s:debug>

    UI标签


    <s:head/>
    <s:form>
    <s:textField>
    <s:password>
    <s:select>
    <s:radio>
    <s:checkboxlist>
    <s:textarea>
    <s:submit>
    <s:reset>

    <s:form action="">
    <s:textfield name="name"></s:textfield>
    <s:password name="password"></s:password>
    <s:select name="city" list="{'北京','上海','广州'}" ></s:select>
    <s:select name="city" list="users" listKey="age" listValue="userName" ></s:select>
    <s:radio name="sex" list="#{'m':'男','n':'女'}"></s:radio>
    <s:checkboxlist  name="in" list="{'beij','shangh'}" ></s:checkboxlist>
    <s:checkboxlist  name="in" list="users" listKey="age" listValue="userName"></s:checkboxlist>
    <s:textarea cols="5px" rows="5px"></s:textarea>
    <s:submit value="submit"></s:submit>
    <s:reset value="reset"></s:reset>
    </s:form>

    Struts2中使用Json


    1.从Action中传递一个Json对象到前台JS中


    a.导入Json相应的依赖库
    json-lib-*.jar
    struts2-json-plugin-*.jar
    b.通过Ajax发送请求到处理Action
    action中提供一个返回对象类型的成员变量而且提供getter/setter方法
    private User user;
    c.配置Action
    通过继承json-default来继承result type="json"
    <package name="json" namespace="/" extends="json-default">
    <action name="testJsonAction" class="com.zhongx.struts2.day6.TestJsonAction">
    <result type="json"></result>
    </action>
    </package>

    通过这样的方式会将对象类型的成员变量以Json形式返回给页面的回调函数


    2.从前台JS传递一个Json类型的字符串到后台Action

    參照testJson2.jsp


      TestJsonAction2.java




    异常(Exception)


    何为异常:
    怎么处理异常
    try{}catch(){}
    当前方法中能解决的,就捕获解决
    throw
    当前方法解决不了,交给调用者处理

    JavaEE中处理异常


    throw DAO---->DaoException
    ClassNotFoundException
    IOException
    SQLException
    NetWorkAdapterException
    throw Biz---->DaoException
    业务异常
    UserNotExistException
    UserOrPasswordException


    try{}catch(){} Action--->DaoException
     UserNotExistException
     UserOrPasswordException


    UI   提供友好提示

    异常分类


    两大类
    check Exception
    编译时,编译器会检查程序
     ClassNotFoundException
     IOException
     SQLException
     
    RuntimeException
    执行过程中。检查的异常 
    NullPointerException
    ClassCastException
    IndexOutOFboundsException

    检查异常是在程序中必须处理


    自己定义异常


    extends Exception
    採用
    extends RuntimeException

    Struts2中Action的异常处理


    1.在Action中trycatch
    try{
    //调用biz处理业务
    User user = userBiz.queryUserByName(name, password);
    }catch(DaoException e){
    依据不同异常返回不同页面
    return "error";
    }catch(UserNotExistException e){
    this.addFieldError("message", "user not exist");
    依据不同异常返回不同页面
    return "input";
    }catch(PasswordErrorException e){
    this.addFieldError("message", "password is error");
    return "input";
    }

    2.声明式异常处理


    将全部异常配置在Struts.xml中,Action中不做不论什么处理
    <action name="loginAction" class="com.zhongx.bank.action.LoginAction">
    配置异常对象以及发生异常跳转的 相应页面
    exception属性:配置异常的全限定名称
    result:配置异常发生时相应跳转的result结果
    <exception-mapping 
    exception="com.zhongx.bank.exception.DaoException"
    result="error"
    ></exception-mapping>
    <exception-mapping 
    exception="com.zhongx.bank.exception.UserNotExistException"
    result="input"
    ></exception-mapping>
    <exception-mapping 
    exception="com.zhongx.bank.exception.PasswordErrorException"
    result="input"
    ></exception-mapping>

    <result name="success">/manager.jsp</result>
    <result name="input">/login.jsp</result>
    <result name="error">/error.jsp</result>
    </action>

    页面获取异常信息


    从值栈中获取,异常信息存放在值栈中Action对象中
    <s:property value="exception.message" s:property/>
    重定向不能获取到异常信息

    Filter与Interceptor 差别?


    1.Filter在运行流程时,採用方法回调来实现流程调用
     Interceptor在运行流程中採用的是反射实现
    2.拦截目标不同。Filter拦截全部请求,Interceptor拦截特定Action的请求

    3.Filter在运行目标Action之前拦截。Interceptor在Action运行前后都拦截


    自己定义Struts1


    commons-digester.jar解析XML
    实现XML标签到对象的转换
    1.依据目标XML的结构定义解析规则文件
    參照rule.xml
    2.创建集合对象接收封装解析的XML
    ModelConfig config = new ModelConfig();
    Digester digester = DigesterLoader.
    createDigester(ActionServlet.class.getClassLoader().getResource("com/zhongx/struts/rule.xml"));
    //将存储集合对象传入
    digester.push(config);
    //解析目标 XML
    digester.parse(ActionServlet.class.

    getClassLoader().getResourceAsStream("mystruts.xml"));


    Struts1和Struts2差别


    1.核心控制器实现不同


    2.Action的实现方式不同


    3.參数接收方式不同


    4.后台验证实现不同


    5.Action中绑定值到视图的实现方式不同


    6.框架支持的页面显示技术不同


    7.页面运行的表达式语言不同


    8.Action运行流程不同


    9.Action的线程安全方面不同

     
     
     



    总结











    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4675214.html
Copyright © 2011-2022 走看看