struts2

作者: 两分与桥 | 来源:发表于2018-09-13 16:35 被阅读6次

    SSH架构


    ssh.png

    struts的路径访问例子

    第一步,导包struts2

      <dependencies>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.5.16</version>
        </dependency>
      </dependencies>
    

    strtus.xml文件,只需要放在resource文件夹下,并不需要在web.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">
    !-- 相当于spring-mvc.xml -->
    <struts>
        !-- namespace用于定义一级请求路径
             http://localhost:8080/struts-day01/demo
         -->
        <package namespace="/demo" name="demo" extends="struts-default">
            !-- 在请求/demo/hello的时候Struts就会利用反射创建DemoAction对象,执行execute方法 -->
            <action name="hello" class="action.DemoAction">
                !-- result用于处理execute方法返回值与jsp视图的对应关系,也就是转发到哪个页面 -->
                <result name="hello">/WEB-INF/hello.jsp</result>
            </action>
            !-- method用于执行控制器中的特定方法 -->
            <action name="success" class="action.DemoAction" method="test">
                <result name="success">/WEB-INF/hello.jsp</result>
            </action>
        </package>
    </struts>
    

    DemoAction文件

    package action;
    
     * Struts控制器的默认控制器方法execute(执行)
    public class DemoAction {
         * 控制器方法,控制器方法返回值是视图的ID
        public String execute() {
            System.out.println("执行了控制器");
            return "hello";
        }
        
        public String test() {
            System.out.println("test方法");
            return "success";
        }
    }
    
    例子.png

    struts2传递参数,需要设置get/set方法

    在struts.xml的package标签中添加下面的路径

        <action name="param" class="action.ParamAction">
            <result name="hello">/WEB-INF/hello.jsp</result>
        </action>
    

    hello.jsp文件,获取传递的参数(背后用的还是反射机制)

    <p>hello world ${name}</p>
    

    ParamAction文件

    package action;
    
     * Struts2 利用Bean属性接收浏览器传递的参数
     * /demo/param?name=Tom
     * 
     * Integer类型的参数会自动进行转换
     * 如果age传过来的是字符串,值会变成null
    public class ParamAction {
        
        private String name;
        private Integer age;
        
        public void setName(String name) {
            this.name = name;
        }
        
        public void setAge(Integer age) {
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
        
        public String execute() {
            System.out.println("获取到的name = " + name);
            System.out.println("获取到的age = " + age);
            return "hello";
        }
    }
    

    访问路径:http://localhost:8080/struts-day01/demo/param?name=libai&age=aaa

    2.png

    使用域模型来获取请求数据

    封装一个父类,封装session等公共方法

    package action;
    
    import java.util.Map;
    
    import org.apache.struts2.interceptor.ApplicationAware;
    import org.apache.struts2.interceptor.RequestAware;
    import org.apache.struts2.interceptor.SessionAware;
    import com.opensymphony.xwork2.ActionSupport;
    
     * 所有控制器的基类,用于封装常用的session,request等,用于提供给子类进行复用
     * 
     * ActionSupport是Struts2提供的Action基础类用于复用公共代码的类
    public abstract class BaseAction extends ActionSupport implements SessionAware,ApplicationAware,RequestAware{
    
        protected Map<String, Object> session;
        public void setSession(Map<String, Object> session) {
            this.session = session;
        }
        
        protected Map<String, Object> application;
        public void setApplication(Map<String, Object> application) {
            this.application = application;
        }
        
        protected Map<String, Object> request;
        public void setRequest(Map<String, Object> request) {
            this.request = request;
        }
    }
    

    LoginAction

    package action;
    
    import java.util.Map;
    import org.apache.struts2.interceptor.SessionAware;
    
     * Struts2可以将session注入到实现SessionAware接口的Action对象中
     * 
     * 一般定义一个Action的父类,封装session等公共方法,子类只需要
     * 继承抽象父类就可以获得这些公共方法。
    
    public class LoginAction2 implements SessionAware{
        private Map<String, Object> session;
        public void setSession(Map<String, Object> session) {
            this.session = session;
        }
        
        private UserInfo user;
        private String error;
        
        public void setUser(UserInfo user) {
            this.user = user;
        }
        
        public UserInfo getUser() {
            return user;
        }
        
        public String getError() {
            return error;
        }
        
        public String execute() {
    
             * ActionContext在Struts2中代表当前Struts2环境相关信息
             * 
             * Map类型的session不依赖Servlet API
             * HttpSession就可以进行与容器无关的测试等离线测试,低耦合性
             * 
             * 离线:脱离Web容器单独使用,比如进行JUnit测试
             * 
             * 在底层Struts2容器会将map session中的信息同步到HttpSession中
            
    //      ActionContext ac = ActionContext.getContext();
    //      session= ac.getSession();
    //      System.out.println(session);
            session.put("login", true);
            System.out.println("user = " + user);
            if(!"libai".equalsIgnoreCase(user.getUsername())) {
                error = "用户名错误";
                return "login2";
            }
            if(!"123456".equals(user.getPassword())) {
                error = "密码错误";
                return "login2";
            }
            
            return "success";
        }
    }
    

    UserInfo 域模型类

    package action;
    
    import java.io.Serializable;
    
     * 域模型类:用于封装用户相关信息
     * 可以在登陆控制器和注册控制器重用该类
    public class UserInfo implements Serializable{
        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 toString() {
            return "UserInfo [username=" + username + ", password=" + password + "]";
        }
    }
    

    login.jsp文件

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>login2</title>
    </head>
    <body>
        <form action="check2.action" method="post">
            <p>用户名:<input name="user.username" type="text" value="${user.username}"/></p>
            <p>密码:<input name="user.password" type="password" value="${user.password}"/></p>
            <p><input value="提交" type="submit"/></p>
        </form>
        <h2>消息:${error}</h2>
    </body>
    </html>
    

    最终结果
    控制台打印获取到的数据

    user = UserInfo [username=sdf, password=sdf]
    
    2.png

    spring-struts

    导包,struts2-spring-plugin依赖的所有spring的核心包,都会自动导入,所以我们不必再导入spring的包了

        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-spring-plugin</artifactId>
            <version>2.5.16</version>
        </dependency>
    

    在web.xml中添加spring的配置信息

      !-- 用于在Web容器启动期间初始化Spring容器 -->
      <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/spring-*.xml</param-value>
      </context-param>
    

    在resource/conf下建立一个spring-mvc.xml配置文件,添加如下配置

        <context:component-scan base-package="web"></context:component-scan>
        <context:component-scan base-package="action"></context:component-scan>
    

    写一个测试的service

    package action;
    
    import org.springframework.stereotype.Service;
    
    @Service("demoService")
    public class DemoService {
        public String test() throws InterruptedException {
            String name = Thread.currentThread().getName();
            System.out.println("线程["+ name +"]调用service");
            Thread.sleep(10000);
            return "hello world";
        }
    }
    

    创建一个Action,用spring来注入上面的service

    package web;
    
    import javax.annotation.Resource;
    
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    
    import action.BaseAction;
    import action.DemoService;
    
    @Controller
    @Scope("prototype")
    public class WebAction extends BaseAction{
        
        private String name;
        
        //注入业务层组件
        @Resource(name="demoService")
        private DemoService service;
        
        public String execute() throws InterruptedException {
            System.out.println("访问WebAction");
            name = Thread.currentThread().getName();
            System.out.println("线程["+ name +"]调用Action");
            //控制器访问业务层,调用业务层方法
            String str = service.test();
            System.out.println(str);
            return SUCCESS;
        }
    }
    

    在struts文件中需要添加路径映射配置,

      <!-- 使用由Spring管理的Action组件webAction
          在配置Action期间,将class属性引用Bean ID即可 -->
      <action name="web" class="webAction">
        <result name="success">/WEB-INF/success.jsp</result>
      </action>
    

    最终的打印结果

    访问WebAction
    线程[http-bio-8080-exec-11]调用Action
    线程[http-bio-8080-exec-11]调用service
    hello world
    

    要十分注意struts2的线程安全性问题,解决办法是在每一个action上添加一个@Scope("prototype"),使得其变为多例模式,可以解决该问题


    struts2的线程安全性问题.png
    web.png

    相关文章

      网友评论

          本文标题:struts2

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