Struts2实现了MVC模式:
Model:Action接口/ActionSupport类 (业务控制器)多实例单线程
View:Struts2提供了4种视图技术 jsp freemarker velocity xslt,同时提供了Result接口,允许用户自定义扩展
Controller:一组拦截器和前端控制器StrutsPrepareAndExecuteFilter
配置前端控制器web.xml
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Struts2的常量配置
default.properties struts-default.xml struts-plugins.xml[插件配置] struts.xml struts.properties web.xml
struts.xml中的常量配置方法:
<constant name="struts.action.extension" value="action" />
抽象包 --只能被继承使用
<package name="default" extends="struts-default" abstract="true"></package>
Action的定义方法:
1、不实现任何接口,不继承任何类
2、Action接口(5大常量和execute方法)
3、ActionSupport
Action的配置:
<action name="hello" class="com.yan.action.HelloAction"></action>
使用hello.action访问HelloAction中的execute方法
<action name="hello" class="com.yan.action.HelloAction" method="show"></action>
使用hello.action访问HelloAction中的show方法
Action的编程:
将一个类对象相关的CRUD方法定义在一个Action类中
public class MyAction{
public String add()throws Exception{}
public String del()throws Exception{}
public String load()throws Exception{}
......
}
<action name="user_*" class="com.yan.MyAction" method="{1}">
user_add.action访问MyAction类中的add方法
<action name="*_*" class="com.yan.{1}Action" method="{2}">
User_add.action访问com.yan.UserAction类中的add方法
特例:<action name="*">如果不定义<action>的class属性,则默认ActionSupport类
<result>/{1}.jsp
实现了hello.action直接访问/hello.jsp页面,不需要额外定义对应的Action类
ActionSupport提供了服务器端数据校验的支持,可以通过编码实现服务器端数据校验
如果Action类中有一个方法public String add()throws Exception,则对应的服务器端数据校验方法为
public void validateAdd(){}。校验方法名称规则为"validate"+方法名,注意方法名首字母大写
执行流程:当客户提交数据时,首先框架自动化构建对应的Action对象(反射),然后框架的拦截器负
责接收用户提交数据,并通过set方法将参数注入到Action对象中,然后调用validateXXX方法实现服务器端
数据校验,然后如果有validate方法则继续执行validate方法;以上方法中如果调用this.addFieldError添
加了报错信息,则自动跳转到<result name=input>对应的页面;如果没有添加任何报错信息,则执行对应的
方法xxx或者execute
Action如何接收请求参数:
1、属性驱动
2、模型驱动
3、对象驱动OGNL <input name="user.username"/>
Action中如何使用Servlet Api
1、ActionContext --Map
2、ServletActionContext ---API
3、实现xxxAware接口
(Map API)
Action中添加报错信息的方法
addActionError("报错信息")
<s:actionerror/>
addFieldError("输入域名称","报错信息")
<s:fielderror/>显示所有输入域相关的报错信息
<s:fielderror name="username"/>显示<input name="username"/>对应的报错信息
Struts2为了简化页面编写,提供了一个标签库,可以分为2大类:<%@ taglib uri="/struts-tags" prefix="s"%>
UI标签用于生成可以显示的标签,例如输入域,Struts2提供了4种主题:
xhtml默认 css_xhtml simple ajax(事实上高版本中已经移到其它包)
非UI标签用于进行页面的显示逻辑控制,例如<s:if>
UI标签
<s:head/>
<s:form
<s:textfield
<s:password
<s:submit
<s:reset
<s:file>
非UI标签
<s:if test="userList!=null and userList.size()>0">
<s:elsif test="">
<s:else>
<s:iterator>
<s:iterator value="#userList" var="u1">
<s:property value="#u1.id"/>
<s:url var="u1" action="list">
<s:param name="pages.pageNum" value="1"/>
</s:url>
<s:a href="%{#u1}">首页</s:a>
在Maven中进行反向映射
1、在pom.xml中添加插件
2、配置反向映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<classPathEntry location="E:/libs/driver/ojdbc6.jar" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@localhost:1521:EDUASK" userId="yanjun"
password="tiger">
</jdbcConnection>
<javaModelGenerator targetPackage="com.yan.entity"
targetProject="src/main/java">
<property name="enableSubPackages" value="ture" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.yan.mapper"
targetProject="src/main/resources">
<property name="enableSubPackages" value="ture" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.yan.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="ture" />
</javaClientGenerator>
<table tableName="T_USERS" domainObjectName="User"
enableCountByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" enableUpdateByExample="false" />
</context>
</generatorConfiguration>
3、用Maven命令mvn mybatis-generator:generate生成
<package name="包名称,没有什么特殊要求,只是在整个应用中不要出现重复,出了被引用之外,没有什么特殊含义"
extends="父包名称,表示新定义的包需要继承这个包,父包中的定义子包可以直接继承,不需要重复定义"
abstract="true用于定义抽象包,表示则这个包不能直接使用,只能被其它包进行继承"
namespace="/user设置名空间,表示这个包中的所有请求路径都应该是/user打头,在具体的Action匹配过程中,不
是通过name进行匹配,而是首先匹配对应的名空间,以查找对应的包;如果不定义名空间,则默认名空间为空,进行匹配时
首先匹配名空间对应的包;如果匹配失败,则匹配名空间为空的包"
如何在配置文件中定义action的属性
<action name="user" class="com.yan.action.UserAction">
<param name="属性名称">值</param>
<result>配置
用于定义逻辑地址名和物理地址之间的对应关系
<result name="login">/WEB-INF/content/user/login.jsp</result>
name是逻辑地址名,如果不定义name属性,则默认属性是success;地址跳转方式默认采用的请求转发
type属性
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
</result-types>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
当定义<result>时如果不定义对应的type属性,则属性值默认为dispatcher,请求转发到对应的jsp页面 【重点】
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
用于实现从一个action请求转发到下一个action。同时前一个action中的属性会自动向后传递
<action name="show" class="com.yan.MyAction">
<result type="chain">
<param name="actionName">list</param>跳转的action的名称
<param name="namespace">/abc</param>跳转的action所属的名空间的名称
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>支持freemarker视图
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>支持Velocity视图
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> 支持xslt视图
<result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />直接显示页面的源码
<result-type name="postback" class="org.apache.struts2.result.PostbackResult" />回退
<result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>用于生成一个头响应信息,类似于response.sendError
<action name="test1">
<result type="httpheader">
<param name="error">500</param>出错代码,例如404等
<param name="errorMessage">页面不存在!</param>默认的报错信息
</result>
</action>
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>用于实现重定向到一个新的地址[可以是jsp,
也可以是action]只是需要配置为地址,而且IDE工具对调转到action的地址会报错,但是不影响使用
<result name="login" type="redirect">
<param name="location">/index.jsp</param>具体要跳转的地址(可以是下一个action的name,也可以是某个具体的jsp路径),允许使用?name=value传值
</result>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>用于实现重定向到一个action,
其中包含参数actionName和namespace,同type=chain.如果跳转的action在同一个名空间中,namespace可以不定义 【重点】
<action name="test1" class="com.yan.action.UserAction" method="tologin">
<result name="login" type="redirectAction">
<param name="actionName">tologin</param>
<param name="namespace">/user</param>
</result>
</action>
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>用于直接输出数据到输出流中
其中包括一个参数inputName,这是输入流的属性名称,Action从这个输入流中读取数据,并写出到输出流 【重点】
动态生成校验码:
public class PicAction extends ActionSupport implements SessionAware{
private int width = 120, height = 120;
private String source="0123456789";
private Map<String,Object> session;
private InputStream is;
@Override
public String execute() throws Exception {
BufferedImage buffer = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = buffer.getGraphics();
g.setColor(Color.CYAN);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawRect(2, 2, width-6, height-6);
String checkcode=this.generateCheckcode(6);
session.put("checkcode",checkcode);
g.setFont(new Font("宋体",Font.BOLD,28));
g.setColor(new Color(88,66,200));
g.drawString(checkcode, 10, height-10);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ImageIO.write(buffer, "jpg", baos);
baos.flush();
is=new ByteArrayInputStream(baos.toByteArray());
return super.execute();
}
<action name="pic" class="com.yan.action.PicAction">
<param name="height">40</param> 给action配置参数,Action类定义中应该有对应的属性【get/set】
<param name="source">qwertyuiopasdfghjklzxcvbnm0123456789</param>
<result type="stream">
<param name="inputName输入流的名称,需要输出的内容需要关联到这个输入流上">is</param>给type定义参数
<param name="bufferSize缓冲区的大小,单位是字节">8192</param>
<param name="contentType响应内容类型,采用MIME协议定义">image/jpeg</param>
</result>
</action>
Struts2中如何实现文件的上传?
1、commons-fileupload[commons-io]
Struts2中使用允许不同的上传组件,例如COS之类的,如何配置
常量定义
定义不同的上传组件,需要自行添加所依赖的jar
struts.multipart.parser=jakarta设置使用commons-fileupload上传组件
struts.multipart.saveDir=临时存放上传文件的文件夹
struts.multipart.maxSize=2097152允许上传文件的最大大小,单位是字节,默认值是2M
2、定义页面的要点:
<form>必须method=post,必须添加enctype=multipart/form-data
<s:form method="post" enctype="multipart/form-data" action="upload.action">
<s:file name="photo" label="上传头像"/>
<s:submit value="提交数据"/>
</s:form>
3、定义Action接收上传的文件数据, 一对三
public class UploadAction extends ActionSupport {
private File photo;// 这个属性名称和文件域的name名称一致
private String photoContentType;//命名规则为"文件域的name"+ContentType,名称格式固定,用于表示上传文件的MIME类型
private String photoFileName;//上传文件的原始名称,其中不包含路径;命名规则为"文件域的name"+FileName,名称格式固定
具体的文件上传细节由commons-fileupload实现,在action中实际上只是负责进行存放的处理
private ServletContext application;
@Override
public String execute() throws Exception {
//获取upload文件夹部署后的绝对路径
String realPath=application.getRealPath("upload/");
File ff=new File(realPath);
if(!ff.exists())
ff.mkdirs();
File destFile=new File(realPath,photoFileName);
FileUtils.copyFile(photo, destFile);
return SUCCESS;
}
下载处理:
content-disposition attachment;filename=默认名称
public class DownloadAction extends ActionSupport implements ServletContextAware {
private String fname;
private InputStream is;
private ServletContext application;
@Override
public String execute() throws Exception {
is=application.getResourceAsStream("upload/"+fname);
return super.execute();
}
<action name="download" class="com.yan.action.DownloadAction">
<result type="stream">
<param name="contentDisposition">attachment;filename=${fname}</param>
<param name="inputName">is</param>
<param name="bufferSize">8192</param>
</result>
</action>
OGNL:
Struts2为了实现在各个组件之间共享数据,引入了ValueStack值栈
用户每次访问struts的action,都会创建一个Action对象、值栈对象、ActionContext对象;
然后把Action对象放入值栈中; 最后再把值栈对象放入request中,传入jsp页面。
1.ValueStack有一个实现类叫OgnlValueStack.
2.每一个action都有一个ValueStack.(一个请求,一个request,一个action,一个valueStack) valueStack生命周期就是request生命周期。
3.valueStack中存储了当前action对象以及其它常用web对象(request,session,application.parameters)
4.struts2框架将valueStack以“struts.valueStack”为名存储到request域中。
页面上提供了一个标签<s:debug/>可以自动生成一个超链接,点击链接可以查看ValueStack中的内容