• Java学习之struts2使用


    Java学习之struts2使用

    0x00 前言

    持续记录学习内容

    0x01 struts2 使用

    1. 导入ja包
    <dependencies>
    <dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>2.5.13</version>
    </dependency>
    </dependencies>
    
    1. web.xml配置
    <!--Struts2核心过滤器-->
    <filter>
    <filter-name>Struts2</filter-name>
    <filter-
    class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExe cuteFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>Struts2</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    1. Action类
    package action;
    
    import com.opensymphony.xwork2.Action;
    
    public class HelloWorldAction implements Action{
        //请求中传递的参数和返回给页面的值都定义成属性
        private String username
        private String password  
    //getter/setter方法
    @Override
    public String execute()throws Exception{
    //查看请求中传递的参数
    System.out.print1n(username);
    //改变这个message,会自动传递给页面
        message="hello:"+username;
    //SUCCESS是Action中的常量,值是success
        return SUCCESS;
    }}
    
    1. struts.xml
    <?xml version="1.0"encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
    "-/∥Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
    <.--所有的action都放在package中,必须继承struts-default-->
    <!--struts-default中有默认的拦截器配置,能处理参数等信息-->
    	<package name="default"extends="struts-default">
    <!--name对应的是请求的地址,class是处理请求的类-->
    <action name="hel1o"class="action.HelloWorldAction">
    <!--success是Action类中返回的字符串,根据不同字符串返回不同的页面-->
    <result name="success">index.jsp</result>
    </action>
    	</package>
    </struts>
    
    1. 编写index.jsp页面
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE HTML>
    <html>
    <head>
        <title>Title</title>
        <meta charset="UTF-8">
    </head>
    <body>
    <h1>struts2</h1>
    <form action="hello" method="post">
        id:<input name="user.id">
        username:<input name="user.username">
        <input type="submit" value="提交">
    </form>
    ${requestScope.message}
    </body>
    </html>
    

    访问到http://127.0.0.1/hello.action时,则就映射到HelloWorldAction.execute方法里面,而这里的方法返回SUCCESS,struts2这样进行了配置

    <action name="hel1o"class="action.HelloWorldAction">
    <!--success是Action类中返回的字符串,根据不同字符串返回不同的页面-->
    <result name="success">index.jsp</result>
    </action>
    

    <result name="success">index.jsp</result>

    则代表如果这个HelloWorldAction.execute方法返回的是success的话则映射到index.jsp文件中。

    struts默认支持的请求后缀是.action,如果需要配置其它的后缀,需要在struts.xml中配置:

    设置允许请求后缀为do和html

    <constant name="struts.action.extension" value="do, html"/>
    

    0x02 struts.xml详解

    constant 标签

    <!--设置请求后缀-->
    <constant name="struts.action.extension"value="do,html"/>
    <!--设置编码,解决中文乱码-->
    <constant name="struts.i18n.encoding"value="utf-8"/>
    <!--设置struts标签主题-->
    <constant name="struts.ui.theme"value="simple"/>
    

    constant用来配置常量。name属性是常量名,value属性是常量值。
    constant常量可以改变Struts2的一些行为,比如U山标签的样式、编码格式等。
    因为struts2默认的编码格式就是UTF-8,所以不用特意指定编码,中文也不会乱码。

    package标签

    <package name="default" namespace="/" extends="struts-default">
    

    package是包。Struts2的package与java中的package类似,可以把同一个业务模块的action和result集中到一个包中,方便管理。不同的是Struts2的包可以继承。比如商品有增删改查操作,订单也有增删该查操作,我们可以将商品和订单的action分别放两个package中方便管理。

    name属性是包的名字,一个struts.xml中可以有很多个package,通过name属性进行区分。

    namespace是命名空间,/代表的是根目录。namespace的作用类似于SpringMVC中在Controller类上加@RequestMapping注解。相当于此包中所有的action前都加一个父路径。如:

    <package name="user"namespace="/user"extends="struts-
    default">
    <action name="login"class="action.LoginAction">
    

    上面这个name=login的action,在访问的时候路径就是/user/login.action extends属性是继承,通常都会继承struts-default。在struts-default中定义了大量的struts特性,如拦截器和参数处理的功能,如果不继承struts-default,会遇到参数无法绑定或找不到action类。

    action标签

    <action name="1ogin"class="action.LoginAction">
    <--success是Action类中返回的字符串,根据不同字符串返回不同的页面-->
    <result name="success">index.jsp</result>
    <result name="error">error.jsp</result><result name="input">1ogin.jsp</result>
    </action>
    

    action标签用来处理请求和响应结果。
    name属性是请求的名字,此处不需要加.action。同一个package下的action不能重名。
    class属性指定处理该请求的类,是类的全路径。默认的处理请求时会去类中找名为execute的方法。如果不指定class,将默认ActionSupport为处理请求的类。
    result标签用来处理请求结果,name属性是Action类中返回的字符串。标签的值是要跳转的页面地址。name如果不写的话,默认是success。

    0x03 Action配置

    Struts2的主要核心是Action类。

    import com.opensymphony.xwork2.Action;public class HelloWorldAction implements Action{
    //请求中传递的参数和返回给页面的值都定义成属性
    
        private String username;
         private String message;
       //getter/setter方法
    @0verride
        public String execute()throws Exception{
    //查看请求中传递的参数
    System.out.println(username);
            
          
            
            //改变这个message,会自动传递给页面	
            message="hello:"+username;
    //SUCCESS是Action中的常量,值是success 
                return SUCCESS;
    

    一个Action业务里可以实现Action接口,也可以继承ActionSupport类。在ActionSupport中提供了一些实现好的业务方法。在以后的编程中,建议全部继承ActionSupport类。
    Action中的方法必须返回一个String类型的字符串,这个字符串与struts.xml中result标签的name属性相对应,struts.xml会根据返回的字符串查找对应的页面。
    在Action接口中提供了5个常用的结果常量:

    package com.opensymphony.xwork2;
    
    public interface Action {
        String SUCCESS = "success";
        String NONE = "none";
        String ERROR = "error";
        String INPUT = "input";
        String LOGIN = "login";
    
        String execute() throws Exception;
    }
    
    

    自定义业务

    在前面的学习中,Action类中只有一个execute方法。
    假如用户有注册和登录两个功能,我们可以把这两个功能写进同一个Action类:

    package action;import com.opensymphony.xwork2.ActionSupport;
    /∥继承ActionSupport类
    public class UserAction extends ActionSupport{
    //处理登录
    public String 1ogin(){
    //参数和业务略
    System.out.println("我是登录");
        return SUCCESS;
    //处理注册
    public String regist(){
    //参数和业务略
    System.out.println("我是注册");
            return SUCCESS;
    }
    

    注意所有处理请求的业务方法必须是public的,而且要返回一个String。struts.xml中配置:

    <package name="user"namespace="/user"extends="struts-
    default">
    <!-一通过method指定调用类中的哪个方法-->
    <action name="login"class="action.UserAction"
    method=“1ogin">
    <result name="success">index.jsp</result><!--登录成功去首页-->
    <result name="error">1ogin.jsp</result><!--登录失败回登录页-->
    </action>
    <action name="reg"class="action.UserAction"
    method="regist">
    <result name=“success">index.jsp</result><!--注册成功去首页-->
    <result name="error">regist.jsp</result><!--注册失败回登录页-->
    </action>
    </package>
    

    method="login"表示要调用类中的login方法处理请求。如果找不到login0方法,Struts2会在类中查找doLogin)方法。如果都找不到,将会报错。

    动态方法调用

    如果一个类中有多个业务方法,又不想给每个业务方法都配置一个action标签,可以使用动态党法调用,语法是:请求名!方法名.action当请求的格式是user!login.action时,代表调用UserAction中的login)方法处理当前请求。当请求的格式是user.regist.action时,代表调用UserAction中的regist)方法处理当前请求。

    <!--允许调用动态方法-->
    <constant name="struts.enable.DynamicMethodInvocation"
    value="true"/>
    

    action配置

    <!--允许动态调用的方法,新版里新增的设置-->
    <g1obal-a1lowed-methods>1ogin,regist</g1obal-a1lowed-methods>
    <action name="user"class="action.UserAction">
    <result name="success">/index.jsp</result><!--成功去首页-->
    <result name="error">/error.jsp</result><!--失败去错误-->
    </action>
    

    通配符使用

    <g1obal-allowed-methods>login,regist</global-allowed-methods>
    <action name="*User"class="action.UserAction"method="{1}">
    <result name="success">/index.jsp</result>
    <result name="error">{1}.jsp</result><!--失败了就返回原来的页面-->
    </action>
    

    User匹配所有以User结尾的请求,method={1}中的{1}匹配的就是 User中的。如果请求的地址是loginUser.action,那么{1}匹配的就是login,就会去类中调用login方法,并返回相应的结果。

    默认Action

    如果在struts.xml中找不到匹配的action,将会报错。可以设置一个默认的action。当所有请求都不匹配时,将匹配默认action。

    <default-action-ref name="default"/>
    <action name="default">
    <result>error.jsp</result>
    </action>
    

    对当前的package有效。
    action标签的clas省略将调用ActionSupport类。result的name省略将默认为success。
    注意default-action-re必须在所有的action标签上面。

    Result 配置

    常用结果有三种类型:dispatcher、redirect、redirectAction、chain

    dispatcher

    result的默认类型就是dispatcher。以下两个标签是等价的:
    dispatcher的结果等同于Servlet中的请求转发,即:
    request.getRequestDispatcher("success.jsp").forward(request,response);请求转发的意思是当前请求中的参数、属性在下一个页面或请求中仍然可
    以使用。

    <result name="success"type="dispatcher">index.jsp</result>
    <result name="success">index.jsp</result>
    

    redirect

    redirect是重定向,重定向之后,当前请求中的参数和属性在下一个页面或请求中将不能使用。

    <result name="success"type="redirect">index.jsp</result>
    

    相当于Servlet中的:response.sendRedirect("success.jsp");

    redirectAction

    redirectAction与redirect类似,不过redirectAction是重定向到某一个action

    <action name="reg"class="action.UserAction"method="regist">
    <result name="success"
    type="redirectAction">1ogin.action</result>
    <result name="error">regist.jsp</result>
    </action>
    

    如果要调用不同package下的action,需要在result中传参数:

    <action name="login"class="action.UserAction"method="login">
    <result name="success"type="redirectAction">
    <!--调用不同package下的action-->
    <param name="namespace">/</param>
    <param name="actionName">hel1o.action</param>
    <!--传递其它参数-->
    <param name="username">123</param>
    </result>
        <result name="error">login.jsp</result>
    </action>
    

    chain

    redirectAction不能共享request中的数据,如果想共享数据,可以将type设置为chain。

    <action name="reg"class="action.UserAction"method="regist">
    <!--注意chain的action后面没有后缀-->
    <result name="success"type="chain">login</result>
    <result name="error">regist.jsp</result>
    </action>
    

    动态获取结果

    private String username;private String page;
    //getter/setter方法略
    public String 1ogin(){
    //参数和业务略
    System.out.print1n(“我是登录");if("admin".equals(username)){//管理员去管理页page="admin-page";
        }else{//其他人去用户页page="user-page";return SUCCESS;
    }
    
    

    result配置

    <action name="login"class="action.UserAction"method="1ogin">
    <!--读取action中的属性值,返回不同页面-->
    <result name="success">${page}.jsp</result>
    <result name="error">login.jsp</result>
    </action>
    

    访问Servlet

    Struts2访问Servlet API有解耦和耦合两种方式

    解耦方式

    Struts2将部分Servlet APl中的对象封装成Map,可以通过ActionContext获取。获取到的Servlet API对象全部是Map

    public String regist(){
    ActionContext ac=ActionContext.getContext();
        Map request=(Map)ac.get("request"); //获取request
        Map session=ac.getSession(); //获取session Map 
       	application=ac.getApplication();
        //获取application 
        session.put("session_user",“123");
            //向session中存值
            return SUCCESS;
    

    需要注意的是Session和Application都有对应的get方法,而request没有,需要使用get("request")获取。
    页面上可以使用

    ${sessionScope.session_id}
    取值

    解耦方式

    该方式需要导入jar包

    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    </dependency>
    
    HttpServletRequest request=
    ServletActionContext. getRequest();
    
    HttpSession session=request.getSession(); HttpServletResponse response=
    ServletActionContext.getResponse();
    

    0x03 struts 标签

    <s:form action="/user/login.action"method="POST">
    <s:textfield name="username"1abel=“用户名"/>
    <s:password name="password"1abe1="密码“/>
    <s:submit value=“登录"/>
    </s:form>
    

    如果想使用原始的样式可以配置struts.xml

    <constant name="struts.ui.theme"value="simple"/>
    

    通用标签

    <s:if test=""></s:if>
    <s:elseif test=""></s:elseif>
    <s:else></s:else>
    

    si标签用于条件判断,相当于jstl中的

    <c:if test=""></c:if>
    

    s:elseif和s:else标签必须与s:if结合使用。

    <s:iterator value=""var=""status=""></s:iterator>
    

    s:iterator用于集合的遍历,相当于jstl中的

    0x04 数据校验

    通用校验

    Action类继承ActionSupport,ActionSupport中有一个validate方法进行数据校验,只需要重写该方法即可实现数据校验功能。

    package action;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class ValidateAction extends ActionSupport {
        private String username;//用户名不能为空,并且长度要大于6
    
        @Override
        public void validate() {
            System.out.println("validate()");
            if (username == null || username.trim().length() < 6) {
                addFieldError("username", "必须输入用户名,长度大于6");
            }
        }
    
        public void validateLogin() {
            System.out.println("validateLogin() ");
            if (username == null || username.trim().length() < 6) {
                addFieldError("username", "xxx");
            }
        }
    
        public String login() {
            System.out.println("登陆");
            return SUCCESS;
        }
    
        public String regist() {
            System.out.println("注册");
            return SUCCESS;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    }
    
    

    addFieldError要求必须给result配置一个input类型的结果。所以在调用logout方法时,会报找不到result input。

            <action name="valLogin" class="action.ValidateAction" method="login">
                <result name="success">main.jsp</result>
                <result name="input">val.jsp</result>
            </action>
    

    方法校验

    validate方法会验证当前Action类中所有的方法,如果只想验证其中的一个方法,可以使用validatexxx方法,其中xxx是被验证的方法名,首字母大写。

    //只验证1ogin方法,不验证其它方法
    public void validatelogin(){
    if(username==nul1 ll username.1ength()==0){
    //向页面中添加错误信息
    addFieldError("username",“用户名不能为空”);
    

    校验框架

    验证框架是把验证信息都写在xm文件中,对某一个Action类进行验证,需要在Action类的同一个包下创建xml文件,文件命名为Action类的类名validation.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
    
            "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
    
    <validators>
        <field name="username">
            <field-validator type="requiredstring">
                <message>必须输入用户名</message>
            </field-validator>
            <field-validator type="stringlength">
                <param name="minLength">6</param>
                <message>长度必须大于${minLength}</message>
            </field-validator>
        </field>
    </validators>
    

    validators标签:在校验框架中,所有的验证都写在validators标签中field标签:每一个需要验证的属性都是一个field标签,name指定要验证那个属性。
    field-validator标签:代表一种验证规则,通过type指定规则。

    0x05 拦截器

    拦截器可以在请求进入action之前做预处理,比如判断用户是否登录。也可以在action执行之后进行处理。和filter比较像,但是filter是基于函数回调,而拦截器是基于反射去实现。

    创建一个类需要实现Interceptor接口

    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    
    public class TimeInterceptor implements Interceptor {
    
        @Override
        public void destroy() {
    
        }
    
        @Override
        public void init() {
    
        }
    
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            long start = System.currentTimeMillis();
            String result = actionInvocation.invoke();//将请求放行,进入action
            long end = System.currentTimeMillis();
            System.out.println("运行时间:" + (end - start));
            return result;
        }
    
    

    在struts.xml中配置拦截器

    <package name="test" namespace="/" extends="struts-default,json-default">
            <interceptors>
    
                <interceptor name="time" class="interceptor.TimeInterceptor"/>
                <interceptor name="login" class="interceptor.LoginInterceptor"/>
                <interceptor-stack name="time-stack">
                    <interceptor-ref name="time"/>
                    <interceptor-ref name="login"/>
                    <interceptor-ref name="defaultStack"/>
                </interceptor-stack>
            </interceptors>
            <global-results>
                <result name="login">/login.jsp</result>
            </global-results>
    

    注意配置位置

    在需要拦截的Action中添加拦截器的引用

    <action name="hello"class="action.HelloWorldAction">
    <interceptor-ref name="time"/>
    <result name="success">index.jsp</result>
    </action>
    

    这时候去访问hell.action就可以进入到拦截器了。

    使用自定义拦截器会造成参数无法读取,这时候可以引入struts自带的拦截器。

    <default-interceptor-ref name="time"/>
    

    拦截器栈

    <interceptors>
    <interceptor name="time"
    class="interceptor.TimeInterceptor"/>
    <interceptor name="1ogin"
    class="interceptor.LoginInterceptor"/>
    <!--拦截器栈,多个拦截器捆绑在一起执行-->
    <interceptor-stack name="time-1ogin">
    <interceptor-ref name="time"/>
    <interceptor-ref name="1ogin"/>
    <interceptor-ref name="defaultStack"/>
    </interceptor-stack>
    </interceptors>
    

    将多个拦截器绑定到一起,只需要引用拦截器栈即可。

    登录拦截

    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    
    import java.util.Map;
    
    public class LoginInterceptor implements Interceptor {
        @Override
        public void destroy() {
    
        }
    
        @Override
        public void init() {
    
        }
    
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            ActionContext actionContext = ActionContext.getContext();
            Map session = actionContext.getSession();
            if(session.get("SEEION_USER")==null){//没有登陆
                return "login";
            }
            return actionInvocation.invoke();
        }
    }
    

    0x06 JSON

    导入依赖

      <dependency>
    
                <groupId>org.apache.struts</groupId>
    
                <artifactId>struts2-json-plugin</artifactId>
    
                <version>2.5.13</version>
    
            </dependency>
    

    Action类:

    public class JsonAction extends ActionSupport {
    
        private Map<String, Object> resultMap;
    
        @Override
        public String execute() throws Exception {
            resultMap = new HashMap<>();
            resultMap.put("key1", "abc");
            resultMap.put("key2", 123);
            return "success";
        }
    
        public Map<String, Object> getResultMap() {
            return resultMap;
        }
    
        public void setResultMap(Map<String, Object> resultMap) {
            this.resultMap = resultMap;
        }
    }
    
    <package name="default"namespace="/"extends="struts-
    default, json-default">
    <action name="json"class="action. JsonAction"
    method="getJson">
    <result type="json">
    <param name="root">resultMap</param>
    </result>
    

    这个包必须继承json-default

    0x07 文件上传

    public class FileAction extends ActionSupport {
        private File upload;
        private String uploadFileName;
    
        public String upload() {
            System.out.println(uploadFileName);
            try {
                String ext=uploadFileName.substring(uploadFileName.lastIndexOf("."));
                byte[] buffer = new byte[1024];
                FileInputStream fis = new FileInputStream(upload);
                FileOutputStream fos = new FileOutputStream("d:/upload/" + System.currentTimeMillis()+ext);
                int len = fis.read(buffer);
                while (len != -1) {
                    fos.write(buffer);
                    len = fis.read(buffer);
                }
                fos.close();
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return SUCCESS;
        }
    

    Action代码中的upload与页面表单中的upload相对应。使用xxFileName封装文件名,其中的xx指代File变量的名字。

    Struts.xml配置

            <action name="upload" class="action.FileAction" method="upload">
                <result name="success">/upload.jsp</result>
            </action>
    

    上传页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE HTML>
    <html>
    <head>
        <title>Title</title>
        <meta charset="UTF-8">
    </head>
    <body>
    
    <form action="upload.do" method="post" enctype="multipart/form-data">
        <input type="file" name="upload"/><input type="submit" value="上传">
    </form>
    <a href="down.do?fileName=1559974348355.png">下载</a>
    </body>
    </html>
    

    0x08 结尾

    冲冲冲!!!

    WX:TG9yaTI1NDgyNjYxNDU= 欢迎各位师傅来一起做技术交流
  • 相关阅读:
    《深入理解java虚拟机》第二章:Java内存区域与内存溢出异常-20210716
    mongodb 占用内存及解决方法
    JDK常用分析工具
    mysql表碎片清理和表空间收缩
    Java Array 和 String 的转换
    Discourse 如何查看自己发布的主题
    Discourse 用户的邮件无法投递的时候如何处理
    IntelliJ IDEA 如何在 Java 中进行快速注释
    Java Arrays.asList 和 new ArrayList(Arrays.asList()) 的对比
    Druid 加载 Kafka 流数据的 索引属性(IndexSpec)
  • 原文地址:https://www.cnblogs.com/nice0e3/p/14800343.html
Copyright © 2020-2023  润新知