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
使用域模型来获取请求数据
封装一个父类,封装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
网友评论