美文网首页
JavaWeb编程实战宝典(6)___第6章 Struts2进阶

JavaWeb编程实战宝典(6)___第6章 Struts2进阶

作者: 岁月静好浅笑安然 | 来源:发表于2019-11-04 17:55 被阅读0次

第6章 Struts2进阶

第6章 Struts2进阶

6.1 认识Struts2的基本配置

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
    "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    
    <!-- 声明包 -->
    <package name="myPackge" extends="struts-default">
        <!-- 配置Action -->
        <action name="query" class="com.hwp.QueryAction">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>


6.1.1 配置web.xml

 <!-- Struts2过滤器 -->
    <filter>
        <!-- 过滤器名称 -->
        <filter-name>struts2</filter-name>
        <!-- 过滤器类 -->
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <!-- Struts2过滤器映射 -->
    <filter-mapping>
        <!-- 过滤器名称 -->
        <filter-name>struts2</filter-name>
        <!-- 过滤器映射 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

6.1.2 配置struts.xml

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
    "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <!-- 声明包 -->
    <package name="myPackage" extends="struts-default">
        <!-- 定义action -->
        <action name="first">
            <!-- 定义处理成功后的映射页面 -->
            <result>/first.jsp</result>
        </action>
    </package>
</struts>

6.1.3 配置struts.properties

struts.properties文件用于配置struts2中所需的大量属性,一般存放在src根目录下,可以通过default.properties了解,实例代码

struts.i18n.encoding=ISO-8859-1
struts.locale=de_DE
struts.multipart.saveDir=\temp
struts.multipart.maxSize=12345

### Load custom property files (does not override struts.properties!)
struts.custom.properties=test,org/apache/struts2/othertest

# added the MockTag to the path of Tags that the TagDirective will search through
struts.velocity.tag.path = org.apache.struts2.views.velocity.ui, org.displaytag.tags

struts.ui.templateDir = template

### Load custom default resource bundles
struts.custom.i18n.resources=testmessages,testmessages2

### XSLT Cache
struts.xslt.nocache = true

也可以省略配置 struts.properties,直接通过struts.xml配置文件的常量来配置Struts2属性

    <!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
    "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <!-- 通过标签来配置编码格式-->
    <constant name="struts.il18.encoding" value="GBK"></constant>

</struts>

6.1.4 学习Struts2的DTD

6.2 深入认识Struts2的配置元素

6.2.1 配置bean

struts-default.xml中的示例代码

 <bean type="com.opensymphony.xwork2.conversion.impl.CollectionConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.CollectionConverter" scope="singleton"/>
    <bean type="com.opensymphony.xwork2.conversion.impl.ArrayConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.ArrayConverter" scope="singleton"/>
    <bean type="com.opensymphony.xwork2.conversion.impl.DateConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.DateConverter" scope="singleton"/>
    <bean type="com.opensymphony.xwork2.conversion.impl.NumberConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.NumberConverter" scope="singleton"/>
    <bean type="com.opensymphony.xwork2.conversion.impl.StringConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.StringConverter" scope="singleton"/>

<bean>标签有如下几个属性

  • class(必选):表示Bean的类名
  • type(可选),表示Bean实现的接口
  • name(可选),表示Bean的实例名字,对应相同类型的多个Bean来说,它们的name属性值必须唯一。
  • socpe(可选),表示Bean实例的作用域,这个属性值必须是default、singleton、request、session或thread其中之一
  • static(可选):该属性指定Bean是否使用静态方法注入,当指定type属性是,该属性不能为true
  • ooptional(可选):表示Bean是否为一个可选Bean

6.2.2 配置常量(constant)

  • struts.properties 配置(不建议使用)
  • struts.xml (推荐使用)
  • web.xml配置(不建议使用)

在实际开发中推荐使用struts.xml中配置常量,其他两种方式不推荐使用

6.2.3 配置包含(include)

struts2允许将一个配置文件分解成多个配置文件,默认装载struts.xml,其他的使用<include>引用

    <struts>
        <include file="struts-help.xml"/>
    </struts>

6.2.4 配置包(package)

    <!-- 声明包 -->
    <package name="myPackage" extends="struts-default">
        <!-- 定义action -->
        <action name="first">
            <!-- 定义处理成功后的映射页面 -->
            <result>/first.jsp</result>
        </action>
    </package>
  • name(必选) 指定包的名字
  • extends(可选) 指定该包继承其他包的名字
  • namespace(可选) 指定包的命名空间
  • nabstract(可选) 指定一个包是否为一个抽象包,抽象包不能包含Action

6.2.5 配置命名空间

命名空间来解决在同一个Web应用中Action重名问题,Struts2的命名空间相当于java中的package关键字

6.2.3 配置拦截器

如struts-default.xml代码片段

    <interceptors>
            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
            </interceptors>

6.3 掌握Struts2 注释(Annotation)

6.3.1 设置当前包的父包—————ParentPackage注释

6.3.1 指定当前包的命名空间—————Namespace注释

6.3.1 指定当前Action结果—————Results与Result注释

6.3.1 通过注释配置Action

6.4 掌握Struts2的Action

6.4.1 了解Action类的getter和setter方法

public class CompanyAction{
    private String employee;
    private float salary;
    ... 省略setter和getter方法
    public String execute(){
    System.out.println(employee);
    System.out.println(salary);
    return  "success";
    }
}

浏览器输入以下地址,会输出对应的数据

http://localhost:8080/webdemo/company.action?employee=bill&salary=2000

6.4.2 实现Action接口

    public MyAction implements Action{
        public String execute(){
            if(...){
                return SUCCESS;
            }else{
                return ERROR;
            }
        }
    }

6.4.3 继承ActionSupport类

6.4.4 实例:用ActionContext访问Servlet API

  • login.jsp
<%@ page language="java"   pageEncoding="UTF-8"%>
        <!-- 引用Struts2标签 -->
     <%@ taglib prefix="s" uri="/struts-tags"%>
<!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>用户登录</title>
</head>
<body>
<s:form action="login">
    <s:textfield label="用户" name="username"/>
    <s:textfield label="密码" name="password"/>
    <s:submit value="登录"/>  
</s:form>
</body>
</html>
  • LoginAction.java
    
    //处理用户登录信息的LoginAction类
public class LoginAction implements Action {
    //封装username请求参数的属性
    private String username;
    //封装password请求参数的属性
    private String password;
    //setter和getter方法
    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;
    }
    //保存用户信息的Map对象
    private static Map<String, String> users=new HashMap<>();
    static{
        users.put("a","1234");
        users.put("b", "4321");
    }
     //用户处理用户请求的execute方法
    @Override
    public String execute() throws Exception {
        try {
            //获取ActionContext对象,可以通过该对象实例访问Servlet API
            ActionContext ctx=ActionContext.getContext();
            //获取Map对象,可以用这个Map对象访问Servlet对象
            Map<String, Object> application = ctx.getApplication();
            //获取Map对象,可以用这个Map对象访问HttpSession对象
            Map<String, Object> session = ctx.getSession();
            //从ServletContext获取计数器变量
            Integer  count=(Integer) application.get("count");
            //将用户名保存在HttpSession对象
            session.put("username", getUsername());
            //此处逻辑,通过输入的用户名去找密码,如果,密码存在则用户不为空
            String pw=users.get(username);
            if(pw==null){
                ctx.put("info", "用户不存在");
                return ERROR;
            }else{
                //密码比较,找到的密码和输入的密码比较,一样说明登录成功
                if(pw.equals(getPassword())){
                    if(count==null){
                        count=1;
                    }else{
                        count++;
                    }
                    application.put("count",count);
                    ctx.put("info","已登录成功");
                    return SUCCESS;
                }else{
                    ctx.put("info","用户不存在,登录失败");
                    return ERROR;
                }
                
            }
        } catch (Exception e) {
            return ERROR;
        }
        
    }

}

  • success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
     <%@ taglib prefix="s" uri="/struts-tags"%>
<!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>登录成功</title>
</head>
<body>
    本站访问次数:${applicationScope.count}<p/>
    用户名:${sessionScope.username}<p/>
    ${requestScope.session.info} 
</body>
</html> 
  • error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
      <%@ taglib prefix="s" uri="/struts-tags"%>
<!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>
${requestScope.info} <p/>
<h1>登录失败</h1>
</body>
</html>
  • web.xml 配置
  • struts.xml

6.4.5 实例:通过aware拦截器访问Servlet API

  • ApplicationAware接口:获取ServletContext关联的Map对象
  • CookieAware 接口:获得和Cookie数组关联的Map对象
  • ParameterAware接口:获取和请求参数关联的Map对象
  • ServletRequestAware接口:获得HttpServletRequest对象
  • ServletResponseAware接口:获得HttpServletResponse对象
  • LoginAwareAction.java,其他的代码一样
//LoginAwareAction实现了Action接口、ServletRequestAware、ApplicationAware接口
public class LoginAwareAction implements Action ,ServletRequestAware,ApplicationAware{
    //封装请求参数的usernam属性
    private String  username;
    //封装请求参数的password属性
    private String password;
    //HttpServletRequest类型变量
    private HttpServletRequest request;
    //Map类型变量
    private Map application;
    //setter和getter方法
    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;
    }
    private static Map<String, String> users=new HashMap<>();
    //封装用户信息
    static{
        users.put("bill", "1234");
        users.put("mike", "4321");
    }
    
    @Override
    public void setApplication(Map<String, Object> application) {
        this.application=application;
        
    }
    
    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request=request;
        
    }

    @Override
    public String execute() throws Exception {
        try {
            //获取HttpSession对象
            HttpSession session = request.getSession();
            //获取计数器变量
            Integer count=(Integer) application.get("count");
            
            session.setAttribute("username",getUsername());
            //此处根据账号来获取密码,获得得到密码说明账号存在
            String pw=users.get(username);
            if(pw==null){
                request.setAttribute("info","用户不存在,登录失败");
                return ERROR;
                
            }else{
                System.out.println(pw+"-----"+getUsername());
                //密码比较,密码一样返回成功,计数加  1
                if(pw.equals(getPassword())){
                    if(count==null){
                        count=1;
                    }else{
                        count++;
                    }
                    application.put("count",count);
                    request.setAttribute("info","登录成功");
                    return SUCCESS;
                }else{
                    request.setAttribute("info",getUsername()+"---"+pw);
                    return ERROR;
                }
            }
            
        } catch (Exception e) {
            return ERROR;
        }
    }

    

}

6.4.6 实例:利用动态方法处理多个提交申请

比如一个表单有多个提交,例如分别有登录和注册
LoginRegisterAction.java

public class LoginRegisterAction  implements Action{
    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;
    }

        //处理登录请求
    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
    //处理注册信息
    public String register() throws Exception {
        return "register";
    }

}

struts.xml配置,主要代码

        <action name="loginregister" class="com.hwp.LoginRegisterAction">
            <result name="success">/success1.jsp</result>
            <result name="error">/error1.jsp</result>
            <result name="register">/register.jsp</result>
        </action>

web.xml

success1.jsp

error1.jsp

register.jsp

loginrigister.jsp

    <%@ page language="java"   pageEncoding="UTF-8"%>
     <%@ taglib prefix="s" uri="/struts-tags"%>
<!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>用户登录</title>
</head>
<body>
<s:form action="loginregister">
    <s:textfield label="用户" name="username"/>
    <s:textfield label="密码" name="password"/>
    <s:submit value="登录"/>  
    <!-- 此处还要重新配置action,即表单action+惊叹号+Action类中的方法名 -->
    <s:submit value="注册" action="loginregister!register"/>  
</s:form>
</body>
</html>

6.4.7 实例:利用menthod属性处理多个提交请求

6.4.8 使用通配符

1、2数字表示匹配第几个通配符
action类

public class ActionTest {
    //添加方法
    public String userAdd(){
        return "success";
    }
    //修改方法
    public String userUpdate(){
        return "success";
    }
    //删除方法
    public String userDelete(){
        return "error";
    }
    //查询方法
    public String userSel(){
        return "success";
    }
    }

struts.xml配置,主要代码
方法一

    <action name="ActionTest*" class="com.hwp.ActionTest" method="{1}">
        <result name="success">/success.jsp</result>
        <result name="error">/error.jsp</result>
    </action>

方法二

    <action name="*_*" class="com.hwp.ActionTest" method="{2}">
        <result name="success">/success.jsp</result>
        <result name="error">/error.jsp</result>
    </action>

请求路径 类名字_方法名.action

    <a hrft="ActionTest_userAdd.action">添加</a>
    <a hrft="ActionTest_userUpdate.action">修改</a>
    <a hrft="ActionTest_userDelete.action">删除</a>
    <a hrft="ActionTest_userSel.action">查询</a>

6.4.8 设置默认的Action

配置完默认的Action后,对于系统无效的请求,系统都会调用forwardAction,但要注意,默认Action一定要在所有的<action>之前配置,也就是说
<default-action-ref>标签要放在<action>标签之前

    <struts>
        <!--配置一个默认的Action -->
        <default-action-ref name="forwardAction"/>
        <!--默认的Action的配置-->
        <action name="forwardAction" class="com.hwp.ForwardAction">
        ...
        </action>
    </struts>

6.5 配置跳转结果

典型的结果配置代码

    <action name="loginregister" class="com.hwp.LoginRegisterAction">
            <result name="success" type="dispatcher">
                <param name="location">/success.jsp</param>
            </result>
            
        </action>

简写形式

    <action name="loginregister" class="com.hwp.LoginRegisterAction">
            <result name="success" type="dispatcher">/success1.jsp</result>
    </action>

全局配置

    <struts>
        <package name="Struts2" extends="struts-default">
            <!-- 定义全局结果-->
            <global-results>
                <result name="success" >/success.jsp</>
            </global-results>
            <action name="query" class="action.QueryAction"/>
            
        </package>
    </struts>

上面代码配置了一个全局结果和一个Action,这个Action没有配置任何结果,当Action返回success时,就会转入全局结果success中定义的success.jsp页面

全局结果对当前包中所有的Action有效,如果某个结果不是在大多数Action中使用,就没必要配置全局结果。

6.5.1 了解Struts 2的配置结果

6.5.2 Struts2支持的处理结果类型

查看struts-default.xml文件,找到如下代码片段

     <result-types>
            <!-- Action链式处理的结果类型-->
            <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
            <!-- 用于转发URL的结果类型,一般转发的是JSP页面-->
            <result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
            <!-- 用于与FreeMarker整合的结果类型-->
            <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
            <!-- 用于控制http头的结果类型-->
            <result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
            <!-- 用于重定向的结果类型-->
            <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
            <!-- 用于重定向到其他Action的结果类型-->
            <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
            <!-- 用于向客户端输出字节流的结果类型-->
            <result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
            <!-- 用于整合Verlocity的结果类型-->
            <result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
            <!-- 用于整合XML/XSLT的结果类型-->
            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            <!-- 用于显示页面原始代码的结果类型-->
            <result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
            <!-- 定义全局结果-->
            <result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
        </result-types>

6.5.3 配置带有通配符的结果

6.5.4 通过请求参数的指定结果

ForwardAction.java

    public class ForwardAction implements Action{
        private String forward;
        ...省略setter/getter
        public String execute() throws Exception{
            return SUCCESS;
        }
    }

struts.xml

    <struts>
        <package name="Struts2" extends="struts-default">
            <!-- 配置动作-->
            <action name="forwardAction" class="com.hwp.ForwardAction">
            <!-- 从请求参数中获得JSP文件名-->
                <result name="success">/WEB-INF/${forward}.jsp</result>
            </action>
        </package>
    </struts>

在浏览器输入如下URL,会在浏览器中输出web1.jsp,等号后面的就是请求参数指定的jsp文件名

http://localhost:8080/Struts2_demo3/forwardAction.action?forward=webi

6.6 掌握模型驱动

6.6.1 了解驱动模型----ModelDriven

驱动模型,简单理解就是把常说的setter/getter的bean提取出

UserForm.java ,实体类

    public class UserForm{
        private String name;
        ... 省略setter和getter方法
    }

MyAction.java

    public class MyAction implements Action,ModelDriven<UserForm>{
        //初始化 UserForm
        private UserForm userForm=new UserForm();
        
        //处理用户请求的代码
        public String execute(){
            return SUCCESS;
        }
            //实现 ModelDriven接口的getModel方法,用于获得UserForm对象
        public UserForm getMOdel(){
            return userForm;
        }
    }

6.6.2 实例:使用模型驱动改进登录程序

6.7 处理Struts2的异常

6.7.1 了解Struts2处理异常的原理

6.7.2 实例:登录系统的异常处理

相关文章

网友评论

      本文标题:JavaWeb编程实战宝典(6)___第6章 Struts2进阶

      本文链接:https://www.haomeiwen.com/subject/fkgdbctx.html