struts2 入门
前言
Struts2 简介
官方解释:
Struts2 是一个基于MVC设计模式的Web应用框架,它本质上相当于一个 servlet。
在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。
其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。
Struts 2以WebWork为核心,采用 拦截器的机制来处理用户的请求,这样的设计也 使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。
虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
个人理解:
Struts2是什么?
Struts2轻量级的MVC框架,主要解决了请求分发的问题,重心在控制层和表现层。低侵入性,与业务代码的耦合度很低。Struts2实现了MVC,并提供了一系列API,采用模式化方式简化业务开发过程。
- 1、运行在web层.负责处理请求的.
- 2、struts2已经帮我们封装了很多web中常用的功能(拦截器)
- 3、struts2 与 struts1 没什么关系. struts2是基于webwork框架
Struts2与Servlet对比
-
优点:业务代码解耦,提高开发效率。
提供了对MVC的一个清晰的实现,这一实现包含了很多参与对所以请求进行处理的关键组件,如:拦截器、OGNL表达式语言、堆栈。
-
缺点:执行效率偏低,需要使用反射、解析XML等技术手段,结构复杂。
不同框架实现MVC的方式
Servlet:
Spring:
Struts2:
Struts2工作流程
Struts2工作流程图,如下:
当Web容器收到请求(HttpServletRequest)它将请求传递给一个标准的的过滤链包括(ActionContextCleanUp)过滤器。
经过Other filters(SiteMesh ,etc),需要调用FilterDispatcher核心控制器,然后它调用ActionMapper确定请求哪个Action,ActionMapper返回一个收集Action详细信息的ActionMaping对象。
FilterDispatcher将控制权委派给ActionProxy,ActionProxy调用配置管理器(ConfigurationManager) 从配置文件中读取配置信息(struts.xml),然后创建ActionInvocation对象。
ActionInvocation在调用Action之前会依次的调用所用配置拦截器(Interceptor N)一旦执行结果返回结果字符串。ActionInvocation负责查找结果字符串对应的(Result)然后执行这个Result Result会调用一些模版(JSP)来呈现页面。
拦截器(Interceptor N)会再被执行(顺序和Action执行之前相反)最后响应(HttpServletResponse)被返回在web.xml中配置的那些过滤器和核心控制器(FilterDispatcher)。
环境搭建
基本目录结构展示:
pom.xml
导入依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dj</groupId>
<artifactId>pre_struts</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>pre_struts Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- struts.xml(核心配置文件) -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.13</version>
</dependency>
</dependencies>
<build>
<finalName>pre_struts</finalName>
<plugins>
<!--第一步就是配置maven-compiler-plugin插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
web.xml
<!-- 修改web.xml由2.3至3.1 -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>
struts.xml
struts-base.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>
<constant name="struts.i18n.encoding" value="UTF-8" />
<constant name="struts.devMode" value="true" />
<constant name="struts.configuration.xml.reload" value="true" />
<constant name="struts.i18n.reload" value="true" />
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<!-- 动态方法调用必须写这个 -->
<package name="base" extends="struts-default" abstract="true">
<global-allowed-methods>regex:.*</global-allowed-methods>
</package>
</struts>
struts-sy.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 name="sy" extends="base" namespace="/sy">
<action name="/demo_*" class="com.dj.web.HelloAction" method="{1}">
<result name="rs">/rs.jsp</result>
</action>
</package>
</struts>
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>
<include file="struts-default.xml"></include>
<include file="struts-base.xml"></include>
<include file="struts-sy.xml"></include>
</struts>
Action
- 不需要指定父类(ActionSupport)业务方法的定义
- public String xxx(); //execute
- Action是多例模式(注:在spring中的配置中一定要注意)
--------Action用来接收参数
参数赋值
-
Action中定义属性,并提供get/set方法
如:Cal2, getCal2/setCal2 -
ModelDriven
返回实体,不能为null,不需要提供get/set方法 -
ModelDriven返回实体和Action中属性重名,ModelDriven中优先级更高
action 案例如下 :
注意: cal1 没有set/get方法
效果对比展示 :
jsp :
继承ModelDriven < Cal > 后打印 :
取消继承ModelDriven < Cal > 后打印 :
与J2EE容器交互
我们开发一般使用 :注入耦合
非注入
-
耦合
ServletActionContext -
解耦(建立使用解耦模式)
ActionContext
注入
-
耦合
注入接口 :
ServletRequestAware
ServletResponseAware
RequestAware -
解耦
具体代码 :
/**
* implements modelDrivern 接收参数值
* @return
*/
public String accept1() {
System.out.println("cal1"+cal1);
//req.setAttribute("cal1", cal1);
//非注入耦合
HttpServletRequest req = ServletActionContext.getRequest();
req.setAttribute("cal1", cal1);
//非注入解耦
// ActionContext context = ActionContext.getContext();
// context.get("aaaaa");
return "rs";
}
/**
* 类实例.属性名 接收参数值
* @return
*/
public String accept2() {
System.out.println("cal2"+cal2);
return "rs";
}
/**
* set/get 接收参数值
* @return
*/
public String accept3() {
System.out.println("sex:"+sex);
return "rs";
}
@Override
public Cal getModel() {
return cal1;
}
@Override
public void setServletRequest(HttpServletRequest req) {
this.req = req;
}
@Override
public void setServletResponse(HttpServletResponse resp) {
this.resp = resp;
}
@Override
public void setRequest(Map<String, Object> arg0) {//几乎不用
//this.req = arg0.get("javax.servlet.http.HttpServletRequest");
}
核心文件配置
-
include 包含文件
file -
package 包
name 包名
extends 继承
namespace 虚拟路径
abstract 通常用来被继承 -
action 子控制器
name:helloAction,helloAction_*
class 全限定名
method:execute,{1} -
result 结果码处理
Name 结果码配置
type:dispatcher|redirect
动态方法调用
注意:
- 动态方法调用,新版本中已禁用,可自行开启或关闭
- 子控制器的访问路径:名称空间+"/"+子控制器名字_xxx+".action"
jsp 具体代码展示 :
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>
<h3>动态方法调用</h3>
<a href="${pageContext.request.contextPath }/sy/demo_add.action">增加</a><br><br>
<a href="${pageContext.request.contextPath }/sy/demo_del.action">删除</a>
<h3>后台接收jsp传递参数的三种方式</h3>
<h4>方式一</h4>
1、<a href="${pageContext.request.contextPath }/sy/demo_accept1.action?num1=20&&num2=5">accept1</a>
<br><br>
<h4>方式二</h4>
2、<a href="${pageContext.request.contextPath }/sy/demo_accept2.action?cal2.num1=20&&cal2.num2=5">accept2</a>
<br><br>
<h4>方式三</h4>
3、<a href="${pageContext.request.contextPath }/sy/demo_accept3.action?sex=nv">accept3</a>
</body>
</html>