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