Struts2的开始
Struts2的作用
现在项目一般都是按照三层架构来开发的,表现层,业务逻辑层,数据访问层,Struts2就是用来代替servlet处理表现层的一种框架,用来处理页面的请求跳转与数据显示等,Struts2里面还是用servlet来实现的,只不过被高度封装了。
搭建Struts2开发环境
下载jar包
从官网http://struts.apache.org/上下载所需要的jar包
拷贝jar包到项目中去
打开Struts2发行包\apps\struts2-blank\WEB-INF\lib,把其中jar都拷贝过来即可。
编写配置文件
在构建路径的顶端,创建一个配置文件struts.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>
</struts>
声明部分可以拷贝struts-core-xxx.jar中的struts-default.xml里的头部声明。
配置控制映射
在项目的web.xml中配置如下信息
<!-- 配置Struts2框架的核心控制器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
开始一个小例子
页面编写
<body>
<a href="${pageContext.request.contextPath}/uuu/helloWorld.action">点击</a>
</body>
配置文件编写
<struts>
<!-- name为包名,唯一的; namespace为命名空间,先找到namespace,找到了就在当前namespace下找action,找不到action则在默认的namespace下找action,extends是继承某个包,默认写struts-default,该包可以在struts-default.xml中找到 -->
<package name="p1" extends="struts-default" namespace="/uuu">
<!-- name为请求链接名(动作名称),class为请求的类全名,默认为com.opensymphony.xwork2.ActionSupport
method为请求类里的处理方法,默认为execute() -->
<action name="helloWorld" class="com.jyh.action.HelloWorldAction" method="sayHello">
<!-- result为返回的页面 -->
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
动作类编写
package com.jyh.action;
public class HelloWorldAction {
public String sayHello(){
return "success";
}
}
结果视图编写
创建success.jsp和error.jsp
案例执行过程简析
页面点击发送请求,由web.xml配置文件中配置的struts拦截器拦截,读取struts中的配置,先找到namespace,然后在对应的namespace下找到action,然后到action中class指向的类中找到method指向的方法,返回的字符串与result中的name属性匹配,然后跳转到结果页面。页面中的链接就是:当前项目路径/namespace/action.name。
动作类
动作类的三种编写方式
方式一
如上图所示,直接编写一个普通的类
方式二
实现com.opensymphony.xwork2.Action接口
package com.jyh.action;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public class Demo1 extends ActionSupport {
public String execute() throws Exception {
return SUCCESS;
}
}
Action接口中的常量:
String SUCCESS:success。一切正常。
String NONE:none。动作方法执行后,不转向任何的结果视图。或者在动作方法中返回null。
String ERROR:error。动作方法执行时遇到异常,转向错误提示页面。
String INPUT:input。验证、转换失败,转向输入页面。
String LOGIN:login。检测用户是否登录,没有登录转向此视图。
方式三
继承com.opensymphony.xwork2.ActionSupport(推荐)
意义:提供了一些基本的功能。比如验证和国际化消息提示等。
动作类中动作方法的编写
public String xxx(){};
动作类的通配符映射
<!-- name中的*号代表定义一个通配符,页面的链接与name属性匹配代表给通配符*赋值,如页面中链接为addCustomerUI
则表示第一个*为add,第二个*为UI,后面的{1}代表引用第一个统配符号,以*在name属性出现的顺序为序号来引用,
所以可以看成method="add",result转向页面为/customer/UICustomer.jsp -->
<action name="*Customer*" class="com.jyh.action.CustomerAction" method="{1}">
<result name="success">/customer/{2}Customer.jsp</result>
</action>
动态方法调用:DMI(Dynamic Method Invocation)
在访问时指定执行的动作方法:
http://localhost:8080/XXX/demo4!m1 执行demo4动作对应动作类的m1动作方法
默认情况下:会报错,说找不到demo4!m1这个动作方法。因为struts2框架默认是禁止动态方法调用的。
<constant name="struts.enable.DynamicMethodInvocation" value="true">
注意:不建议使用。容易暴露动作类中的动作方法,害怕非法执行。
动作类获取ServletAPI
方式一(推荐)
package com.jyh.action;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public class ServletAction extends ActionSupport {
@Override
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext context = ServletActionContext.getServletContext();
System.out.println(request);
System.out.println(response);
System.out.println(context);
return null;
}
}
方式二
package com.jyh.action;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
public class ServletAction2 implements ServletRequestAware,ServletResponseAware,ServletContextAware {
/**
* 拦截器注入的这些东西(servletConfig拦截器)
*/
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext context;
public String execute() throws Exception {
System.out.println(request);
System.out.println(response);
System.out.println(context);
return null;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletContext(ServletContext context) {
this.context = context;
}
}
Struts2配置文件struts.xml
Struts2的其它一些配置文件和写法
自带的一些配置文件
- default.properties:struts2-core**.jar org.apache.struts包中(只读)
- struts-default.xml:struts2-core**.jar中(只读)
- struts-plugin.xml:在插件的jar包中(只读)
- struts.xml:在应用的构建路径顶端。自己定义的Struts配置文件(推荐)
- struts.properties:在应用的构建路径顶端。自己编写(不推荐)
- web.xml:配置过滤器时,指定参数。自己编写(不推荐)
特别注意:顺序是固定的。后面的配置会覆盖前面的同名配置信息。
一些常用的默认参数的修改与设置
包含其他配置文件
<include file="user.xml"></include>
<!-- 修改链接默认后缀,多个后缀可以用逗号隔开 -->
<constant name="struts.action.extension" value="do"></constant>
<!-- 设置浏览器是否缓存静态内容,默认值为true -->
<constant name="struts.serve.static.browserCache" value="false"></constant>
<!-- 当struts的配置文件修改后系统是否自动重新加载该文件,默认值为false,推荐打开 -->
<constant name="struts.configuration.xml.reload" value="true"></constant>
<!-- 开发模式,会非常详细的打印出一些错误信息,开启它则默认开启了i18n.reload、configuration.xml.reload。 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 视图主题(simple,xhtml,css_xhtml),默认为xhtml,也就是struts2自带的视图主题,simple为不普通的标签不带任何主题 -->
<constant name="struts.ui.theme" value="simple"></constant>
<!-- 与spring集成时,指定由spring负责action对象的创建 -->
<constant name="struts.objectFactory" value="spring"></constant>
<!-- 该属性设置struts是否支持动态方法调用,默认为false-->
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
<!-- 上传文件大小限制 -->
<constant name="struts.multipart.maxSize" value="100000000"></constant>
package元素
意义:分模块开发。
属性:
- name:必须的。配置文件中要唯一。就是一个名字。
- extends:指定父包。会把父包中的配置内容继承下来。一般需要直接或间接的继承一个叫做“struts-default”的包(在struts-default.xml配置文件中)。如果不继承该包,那么Struts2中的核心功能将无法使用。
- abstract:是否是抽象包。没有任何action子元素的package可以声明为抽象包。
- namespace:指定名称空间。一般以”/”开头。该包中的动作访问路径:namesapce+动作名称。如果namespace=””,这是默认名称空间,和不写该属性是一样的。
action元素
作用:定义一个动作。
属性:
- name:必须的。动作名称。用户用于发起请求。在包中要唯一。
- class:指定动作类的全名。框架会通过反射机制实例化。默认是:com.opensymphony.xwork2.ActionSupport。
- method:指定动作类中的动作方法。框架会执行该方法。默认是execute()。
默认类在struts-default.xml中声明了,也可以用
<default-class-ref class="完整类名"></default-class-ref>
覆盖
结果视图result元素
- name:逻辑视图名称。它对应的是动作方法的返回值。默认值:success。
type:结果类型,到达目标的形式。默认值:dispatcher-转发。
全局视图:
<global-results></global-results>
,直接写在包下- 局部视图:
<results></global>
,写在action下
在什么下范围就多大,先找action下的局部视图(范围精确),再找报下的全局视图
默认拥有的结果类型(result的type元素)
struts-default.xml中定义的结果视图
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>
- freemarker:用于转发到另外一个freemarker模板。(页面静态化)
- velocity:用于转发到另外一个velocity模板。
- httpheader:用于输出http协议的消息头。
- xslt:XML有关的样式
- redirect:用于重定向到另外一个JSP页面。
- redirectAction:用于重定向到另外一个动作。
- stream:用于文件下载(日后再讲。文件上传和下载)
- plainText:以纯文本的形式展现页面。输出源码。
- chain:用户转发到另外一个动作。
- dispatcher:用于转发到另外一个JSP页面。
<!-- 同一个包下一个动作转发到另一个动作 -->
<package name="d1" extends="struts-default" namespace="/n1">
<action name="demo1" class="com.jyh.action.Demo1" method="execute">
<result name="success" type="chain">demo2</result>
</action>
<action name="demo2" class="com.jyh.action.Demo1" method="execute">
<!-- <result name="success" type="dispatcher">/demo1.jsp</result> -->
<!-- 同上,dispatcher表示转发到页面 -->
<result name="success" type="dispatcher">
<param name="location">/demo1.jsp</param>
</result>
</action>
</package>
<!-- 转发到另一个包中的动作 -->
<package name="d2" extends="struts-default" namespace="/n2">
<action name="demo3" class="com.jyh.action.Demo1" method="execute">
<result name="success" type="chain"><!-- 配置type="chain"意思是从这个动作跳到另一个动作 -->
<param name="namespace">/n1</param><!-- 配置转发目标动作所在的命名空间 -->
<param name="actionName">demo2</param><!-- 配置转发目标动作的名称 -->
</result>
</action>
</package>
自定义结果类型(result的type元素)
1.编写一个类,直接或间接实现com.opensymphony.xwork2.Result接口。一般继承org.apache.struts2.dispatcher.StrutsResultSupport类
package com.jyh.action;
/**
* 自定义结果类型,生成验证码
*/
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import cn.dsna.util.images.ValidateCode;
import com.opensymphony.xwork2.ActionInvocation;
@SuppressWarnings("serial")
public class CaptchaResult extends StrutsResultSupport {
private int width = 200;//长度
private int height = 80;//宽度
private int codeCount = 4;//验证码个数
private int lineCount = 100;//干扰线条数
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setCodeCount(int codeCount) {
this.codeCount = codeCount;
}
public void setLineCount(int lineCount) {
this.lineCount = lineCount;
}
protected void doExecute(String finalLocation, ActionInvocation invocation)
throws Exception {
ValidateCode vCode = new ValidateCode(width, height, codeCount, lineCount);
BufferedImage image = vCode.getBuffImg();
HttpServletResponse response = ServletActionContext.getResponse();
ImageIO.write(image, "jpeg", response.getOutputStream());
}
}
2.声明定义结果类型
<!-- 自定义结果类型 -->
<package name="d3" extends="struts-default">
<!-- 声明定义结果类型 -->
<result-types>
<!-- name为结果类型名称,class为具体实现的类 -->
<result-type name="captcha" class="com.jyh.action.CaptchaResult"/>
</result-types>
</package>
3.使用自定义的结果类型
<action name="captcha">
<!-- 使用定义的结果类型 -->
<result name="success" type="captcha">
<!-- 设置结果类型对应的实现类中的属性 -->
<param name="width">200</param>
<param name="height">80</param>
<param name="codeCount">4</param>
<param name="lineCount">100</param>
</result>
</action>