1,Struts2.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">
<struts>
<!-- constant:配置struts2的基本属性,在struts2-core核心包的/org/apache/struts2/default.properties中找 -->
<!-- 乱码解决 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 自定义扩展名,一下可以没有,可以为.do可以为.action -->
<constant name="struts.action.extension" value="action,,do" />
<!-- 当配置文件更改后自动装载 。同时要开启开发者模式 -->
<!--true:是开发者模式。外部不可访问;false:外部可以访问 ,出错时候友好的提示信息;实际发布的时候选择false,为了安全 -->
<constant name="struts.devMode" value="true" />
<constant name="struts.configuration.xml.reload" value="true" />
<!-- 启动动态方法action配置 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 把struts的action对象交给spring容器管理 -->
<constant name="struts.objectFactory " value="spring" />
<!-- include这个是团队开发模式使用的,多个xml文件的时候就使用 ,这样每个人只要维护自己的配置文件即可 -->
<!-- <include file="直接指定扩展xml文件的路径即可"/> -->
<!-- struts是基于包管理的 name随便写,namespace是指不同命名空间, extends必须是struts-default,直接或者间接继承,简介继承就使用json-default
从Struts-core核心包中可以看到json-default 继承了struts-default,扩展了其中的过滤器配置
可以配置多个包,用于团队开发 -->
<!-- 配置文件加载顺序:struts-default.xml->struts-plugin.xml->struts.xml -->
<package name="default" namespace="/" extends="json-default">
<!-- 配置默认执行的action,当所请求的action不存在的时候默认执行的action-->
<default-action-ref name="default"/>
<!-- 配置默认执行的class ,当一个action没有配置class的时候就是这个去处理,可以不指定,也有框架自己默认的-->
<default-class-ref class="com.yc.ssm.action.UserAction"/>
<!-- 配置全局结果集 -->
<global-results>
<result name="fail">/login.jsp</result>
</global-results>
<!-- 请求这个名字name是url请求名,不需要加后缀(.action)
CLASS是请求对用的action类的全类名
method配置处理请求的方法,默认为execute方法
方法返回值类型必须是String,必须是public的
在action的配置中不配置class将由默认的action(ActionSupport类)来执行
-->
<action name="User_*" class="com.yc.ssm.action.UserAction" method="{1}">
<!-- name:匹配请求方法返回值,默认是success
type:结果处理类型
默认是dispatcher转发;
chain:是指action链,执行actionA后直接指定actionB,地址栏是第一个action
dispatcher:转发,特点和Servlet一致,如果Request中有数据要显示则用
redirect:重定向,如果重定向到jsp页面,可以直接重定向
但是如果重定向到另一个action,需要注意是否配置action的后缀名
redirectAction:重定向到另一个action,不用加action的后缀名,自动帮你加上了
stream:以流的形式显示-文件下载
还有一些就不具体讲了
-->
<result name="success" type="dispatcher">/page/index.jsp</result>
<result type="json" name="json">
<param name="contentType">
text/html
</param>
</result>
</action>
<action name="default">
<result>/404.jsp</result>
</action>
</package>
</struts>
2,web.xml中的配置
<!-- struts框架的核心(过滤器)其它过滤器都配置在它之前 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!-- struts core如果是2.5 的版本则要删除ng -->
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
注:这个filter一定要放在其它的过滤器之后,不然就不会执行其它的过滤器了
3,Action类的官方推荐写法
(Struts2的Action是线程安全的,每次请求都将会创建一个新的action,)
/**
* ActionSupport:官方推荐继承这个类(验证) :其中的一些默认的配置
*ModelDriven:模型驱动,自动注入
*UserBean:指需要注入的对象
* @author shuang
*
*/
@Controller
public class UserAction extends ActionSupport implements ModelDriven<UserBean>{
private UserBean userBean = new UserBean();
public UserBean getModel() {
return userBean;
}
}
使用以上写法,在action类中就可以任意使用我们的实体类userBean对象,但是提交的数据的name一定要和实体类的属性保持一致
4,最好的使用解耦和的方式获取jsp内置对象
其一:ActionContext.getContext().getSession()获取session对象
/**
* ActionContext.getContext().getSession()一般使用这种解耦合的方式获取内置对象
* ActionContext是一个map结构的容器,是action的上下文,
* 存放action执行过程中的数据信息,比如session的,Application的等
* 每次请求的时候创建一个新的ActionContext
* 而ActionContext采用了ThreadLocal的方式来存放ActionContext
* 所以ActionContext是线程安全的
* ActionContext是基于请求创建的,所以在非请求的线程中是不能访问的,获取也是为空的
* @return
*/
ActionContext:Struts2的ACtion不用依赖于web容器,本身只是一个普通的java类而已,但是在web开发中我们往往需要
获得Request等对象,这时候就可以通过ActionContext,
ActionContext正如其名,是action执行的上下文,他内部有个map属性,它存放了action执行时需要用到的对象,
在每次执行action之前都会创建新的ActionContext对象,所以ActionContext是线程安全的,新new的ActionContext是保存在
一个ThreadLocal变量中,即采用ThreadLocal模式,ThreadLocal变量为每个线程提供独立的变量值的副本,使得每个线程都可以独立
的使用自己的副本,而不会和其他的线程发生冲突
通过ActionContext获取的session,Request等并不是真的httpservletRequest等对象,而是将对象里面的值重新包装成了map对象
,这样的封装,我们及获取了我们需要的值,同时避免了跟web容器直接打交道,实现了完全的解耦
ps:ThreadLocal:提供了线程局部变量,存放线程局部变量的一个容器,
以上测试可以知道ThreadLocal是线程安全的
ActionContext包含6大对象:
1,Application
2,request
3,session
4,attr(page->request->sesssion->application)括号中是取值顺序
5,parameters
6,ValueStack(值栈)
ValueStack(值栈)
1、是ActionContext中的一个对象,值栈是栈结构(FILO:先进后出);
Struts2中值栈存放的数据是Action对象
注意:Action对象可以ValueStack,我们可以对象值栈进行操作,但是建议不是很熟就不要去操作了
5,包
<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.yc</groupId>
<artifactId>spring-struts-mybatis</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- struts2框架 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.28</version>
</dependency>
<!-- struts2使用json格式传输数据的时候使用的包 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.16</version>
</dependency>
<!--struts2整合spring的插件包 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.5-BETA3</version>
</dependency>
<!-- spring框架的核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.6.RELEASE</version>
<scope>runtime</scope>
</dependency>
<!-- spring框架支持数据访问层的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.6.RELEASE</version>
<scope>runtime</scope>
</dependency>
<!-- spring框架支持表现层的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.6.RELEASE</version>
<scope>runtime</scope>
</dependency>
<!-- spring框架支持单元测试的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
<scope>runtime</scope>
</dependency>
<!-- aspectj框架的包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
<scope>runtime</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.5</version>
<scope>runtime</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
<scope>runtime</scope>
</dependency>
<!--oracle 数据库驱动包 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>oracle-driver</artifactId>
<version>oracle11g</version>
<scope>runtime</scope>
</dependency>
<!-- 数据库连接池的包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
<scope>runtime</scope>
</dependency>
<!-- mybatis框架核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
<scope>runtime</scope>
</dependency>
<!-- mybatis与spring整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
<scope>runtime</scope>
</dependency>
<!-- jstl包 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 邮件发送包 -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.5</version>
</dependency>
<!-- gosn包 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-struts-mybatis</finalName>
</build>
</project>
遇到的问题:取自网站
在struts2中发现,调用action中的方法,方法会被执行两次,后来发现调用的方法是get开头的,把它改为其他名称开头的后,就不会执行两次了。继续查找,发现调用的是返回json数据格式的action,如果是调用返回页面的action就不会有这种问题。
1.
2.
结论:action中方法最好不要以get开头。