Struts2是MVC架构中的View层,和Struts相比,它不仅仅是一个版本的提升,还是完全不一样的东西
Struts2的整体架构
Struts需要依赖的jar包
- commons-fileupload-x.y.z.jar
- commons-io-x.y.z.jar
- commons-lang-x.y.jar
- commons-logging-x.y.z.jar
- commons-logging-api-x.y.jar
- freemarker-x.y.z.jar
- javassist-x.y.z.GA
- ognl-x.y.z.jar
- struts2-core-x.y.z.jar
- xwork-core.x.y.z.jar
pom文件的Maven依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging-api -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
<version>1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.0-GA</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.2.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.struts/struts2-core -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.struts.xwork/xwork-core -->
<dependency>
<groupId>org.apache.struts.xwork</groupId>
<artifactId>xwork-core</artifactId>
<version>2.3.36</version>
</dependency>
使用Struts2的基本步骤
创建一个Action类
public class HelloWorldAction{
private String name;
public String execute() throws Exception {
return "success";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建一个JSP页面
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
Hello World, <s:property value="name"/>
</body>
</html>
创建一个主页index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World From Struts2</h1>
<form action="hello">
<label for="name">Please enter your name</label><br/>
<input type="text" name="name"/>
<input type="submit" value="Say Hello"/>
</form>
</body>
</html>
配置文件struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="helloworld" extends="struts-default">
<action name="hello"
class="cn.w3cschool.struts2.HelloWorldAction"
method="execute">
<result name="success">/HelloWorld.jsp</result>
</action>
</package>
</struts>
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Struts 2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
日志文件logging.properties
org.apache.catalina.core.ContainerBase.[Catalina].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers = \
java.util.logging.ConsoleHandler
Struts.xml配置解析
<package>标签允许配置的分离和模块化。这在你进行一个大的项目并且项目分为多个不同的模块时,是非常有用的。
package标签中的属性
属性 | 描述 |
---|---|
name(必需) | 为package的唯一标识 |
extends | 指定package继承另一package的所有配置。通常情况下,我们使用struts-default作为package的基础。 |
abstract | 定义package为抽象的。如果标记为true,则package不能被最终用户使用。 |
namespace | Actions的唯一命名空间 |
Struts2拦截器
重要的拦截器,开箱即用
拦截器 | 说明 |
---|---|
alias | 允许参数在请求之间使用不同的别名。 |
checkbox | 通过为未检查的复选框添加参数值false,以辅助管理复选框。 |
conversionError | 将字符串转换为参数类型的错误信息放置到action的错误字段中。 |
createSession | 自动创建HTTP会话(如果尚不存在)。 |
debugging | 为开发人员提供一些不同的调试屏幕。 |
execAndWait | 当action在后台执行时,将用户发送到中间的等待页面。 |
exception | 映射从action到结果抛出的异常,允许通过重定向自动处理异常。 |
fileUpload | 便于文件上传。 |
i18n | 在用户会话期间跟踪选定的区域。 |
logger | 通过输出正在执行的action的名称提供简单的日志记录。 |
params | 设置action上的请求参数。 |
prepare | 这通常用于执行预处理工作,例如设置数据库连接。 |
profile | 允许记录action的简单分析信息。 |
scope | 在会话或应用程序范围内存储和检索action的状态。 |
ServletConfig | 提供可访问各种基于servlet信息的action。 |
timer | 以action执行时间的形式提供简单的分析信息。 |
token | 检查action的有效性,以防止重复提交表单。 |
validation | 提供action的验证支持。 |
结果类型
1.dispatch类型
<result name="success" type="dispatcher">
<param name="location">
/HelloWorld.jsp
</param >
</result>
dispatcher结果类型是默认的类型,如果未指定其他结果类型,则使用此类型。它用于转发到服务器上的servlet,JSP,HTML等页面。它使用RequestDispatcher.forward()方法。
2.freemake类型
<action name="hello" class="cn.w3cschool.struts2.HelloWorldAction" method="execute">
<result name="success" type="freemarker">
<param name="location">/hello.fm</param>
</result>
</action>
在这个例子中,我们将介绍如何使用FreeMaker作为视图技术。Freemaker是一个流行的模板引擎,使用预定义的模板生成输出。让我们创建一个包含以下内容的名为hello.fm的Freemaker模板文件:
Hello World ${name}
上面的文件是一个模板,其中name是一个参数,将使用定义的action从外部传递。你可以在CLASSPATH中保留此文件。
3.redirest类型
<action name="hello" class="com.tutorialspoint.struts2.HelloWorldAction" method="execute">
<result name="success" type="redirect">
<param name="location">
/NewWorld.jsp
</param >
</result>
</action>
redirect结果类型调用标准的response.sendRedirect()方法,使得浏览器向给定的位置创建一个新请求。
制作一个登陆拦截器(自己编写,放心可用)
1.login.jsp
<html>
<head>
<title>登录页</title>
</head>
<body vLink="#006666" link="#003366" bgColor="#E0F0F8">
<br>
<b>用户登录</b>
<s:form action="login">
<s:textfield name="user.username" label="用户名 " />
<s:password name="user.password" label="密 码" />
<s:submit value="登录"></s:submit>
</s:form>
<a href="regist.jsp">新用户注册</A>
<a href="changePassword.jsp">修改密码</a>
</body>
</html>
2.CheckLoginIntercepter.java
public class CheckLoginIntercepter extends AbstractInterceptor {
public String intercept(ActionInvocation actionInvocation) throws Exception {
if(LoginAction.class==actionInvocation.getAction().getClass()
|| RegistAction.class==actionInvocation.getAction().getClass()){//不拦截登陆和注册Action
return actionInvocation.invoke();
}
Map session = actionInvocation.getInvocationContext().getSession();//获取Session
if(session.get("username")==null){//从session中获取username
System.out.println("未登陆!!");
return Action.LOGIN;
}
System.out.println("已登陆!!");
return actionInvocation.invoke();
}
}
3.LoginAction.java
public final class LoginAction extends ActionSupport
{
private User user;
private ModelBean dbBusiness;
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
public String execute()
{
try{
dbBusiness =new ModelBean();
if (dbBusiness.checkUser(user))
{
Map sessionMap = ActionContext.getContext().getSession();
sessionMap.put("User",user);
return "success"; //用户正确
}else{
return "error"; //用户非法
}
}catch(SQLException e){
return "input"; //出现异常
}catch(ClassNotFoundException ne){
return "input"; //出现异常
}
}
}
4.struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<include file="struts-default.xml"/>
<package name="login-regist" extends="struts-default">
<interceptors>
<interceptor name="logincheck" class="interceptor.CheckLoginIntercepter"> </interceptor>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="logincheck"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"/>
<global-results>
<result name="login" type="redirect">/login.jsp</result>
</global-results>
<action name="login" class="action.LoginAction">
<result name="success">loginSuccess.jsp</result>
<result name="error">loginFail.jsp</result>
<result name="input">input.jsp</result>
</action>
</package>
</struts>
5.loginSuccess.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>登录成功页</title>
</head>
<body vLink="#006666" link="#003366" bgColor="#E0F0F8">
<h1><img src="img/smile.gif">
登录成功,<s:property value="user.username"/> 欢迎您 !
</h1><br>
<a href="login.jsp">重新登录</a> || <a href="regist.jsp">新用户注册</a>
</body>
</html>
值栈
值栈是一组对象,按照提供的顺序存储以下这些对象:
对象 | 说明 |
---|---|
Temporary对象 | 实际中存在各种在页面执行期间创建的temporary对象。例如,JSP标签循环集合的当前迭代值。 |
Model对象 | 如果在struts应用程序中使用Model对象,则当前Model对象放在值堆栈上的action之前。 |
Action对象 | 这是指正在执行的当前action对象。 |
命名对象 | 这些对象包括#application,#session,#request,#attr和#parameters以及所引用的相应的servlet作用域。 |
操纵值栈对象的方法
值栈方法 | 说明 |
---|---|
Object findValue(String expr) | 通过在默认搜索顺序中对值栈评估所给定的表达式来查找值。 |
CompoundRoot getRoot() | 获取将对象推入值栈的CompoundRoot。 |
Object peek() | 获取值栈顶部的对象而不改变值栈。 |
Object pop() | 获取值栈顶部的对象,并将其从值栈中删除。 |
void push(Object o) | 将对象放在值栈的顶部。 |
void set(String key,Object o) | 使用给定的key在值栈上设置一个对象,使其可通过findValue(key,...)检索。 |
void setDefaultType(Class defaultType) | 设置在获取值时要转换的默认类型。 |
void setValue(String expr,Object value) | 尝试使用由默认搜索顺序给定的表达式在值栈的bean上设置属性。 |
int size() | 获取值栈中的对象数。 |
OGNL
OGNL(Object-Graph Navigation Language,对象图导航语言)是一种强大的表达式语言,用于引用和操作值栈上的数据,还可用于数据传输和类型转换。
OGNL非常类似于JSP表达式语言。OGNL基于上下文中存有根对象或默认对象的理念,使用标记符号(即#号)来引用默认或根对象的属性。
如前面所述,OGNL是基于上下文的,而Struts构建了一个ActionContext映射以供OGNL使用。 ActionContext映射包含以下内容:
-
应用程序 - 应用程序作用域变量
-
会话 - 会话作用域变量
-
根/值栈 - 所有的action变量都存储在这里
-
请求 - 请求作用域变量
-
参数 - 请求参数
-
属性 - 存储在页面,请求,会话和应用程序作用域中的属性
有必要了解的是,Action对象在值栈中总是可用的,因此如果你的Action对象有x和y属性,你可以随时使用。
ActionContext中的对象使用#号引用,但是,值栈中的对象可以直接引用,例如,如果employee是action类的属性,则可以按如下方式引用:
<s:property value="name"/>
替代
<s:property value="#name"/>
如果你在会话中有一个名为“login”的属性,你可以按如下方式检索:
<s:property value="#session.login"/>
OGNL还支持处理集合 - 即Map,List和Set。例如,要显示颜色的下拉列表,你可以执行以下操作:
<s:select name="color" list="{'red','yellow','green'}" />
Struts2文件上传
Action中的execute()函数
public String execute()
{
/* Copy file to a safe location */
destPath = "C:/apache-tomcat-6.0.33/work/";
try{
System.out.println("Src File name: " + myFile);
System.out.println("Dst File name: " + myFileFileName);
File destFile = new File(destPath, myFileFileName);
FileUtils.copyFile(myFile, destFile);
}catch(IOException e){
e.printStackTrace();
return ERROR;
}
return SUCCESS;
}
Struts2连接数据库
Action中的execute()函数
public String execute() {
String ret = ERROR;
Connection conn = null;
try {
String URL = "jdbc:mysql://localhost/struts_tutorial";
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL, "root", "root123");
String sql = "SELECT name FROM login WHERE";
sql+=" user = ? AND password = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
name = rs.getString(1);
ret = SUCCESS;
}
} catch (Exception e) {
ret = ERROR;
} finally {
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printstacktrace()
}
}
return ret;
}
Struts2发送邮件
Action中的execute()函数
public String execute()
{
String ret = SUCCESS;
try{
Session session = Session.getDefaultInstance(properties,
new javax.mail.Authenticator() {
protected PasswordAuthentication
getPasswordAuthentication() {
return new
PasswordAuthentication(from, password);
}});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse(to));
message.setSubject(subject);
message.setText(body);
Transport.send(message);
}
catch(Exception e){
ret = ERROR;
e.printStackTrace();
}
return ret;
}
Struts2本地化/国际化(i18n)
来源是英文单词 internationalization的首末字符i和n,18为中间的字符数。
1.建立不同语言的properties,命名格式
bundlename_language_country.properties
2.配置properties文件
Struts2类型转换
public class EnvironmentConverter extends StrutsTypeConverter {
@Override
public Object convertFromString(Map context, String[] values, Class clazz) {
Environment env = new Environment(values[0]);
return env;
}
@Override
public String convertToString(Map context, Object value) {
Environment env = (Environment) value;
return env == null ? null : env.getName();
}
}
Struts2主题和模板
struts2定义
术语 | 描述 |
---|---|
tag(标签) | 从JSP,FreeMarker或Velocity内部执行的一小段代码。 |
template(模板) | 一些代码,通常是写在FreeMarker上的,可以由某些标签(HTML标签)呈现。 |
theme(主题) | 封装在一起以提供公共功能的模板集合。 |
三个内置主题
Theme(主题) | 描述 |
---|---|
simple theme | 没有“bells and whistles”的最小主题。例如,textfield标签呈现HTML<input/>标签无标记、验证、错误报告或任何其他格式或功能。 |
xhtml theme | 这是Struts 2使用的默认主题,提供了simple theme具备的所有基础,并添加了几个功能,如HTML的标准两列表布局、每个HTML的标记、验证和错误报告等。 |
css_xhtml theme | 这个主题提供了simple theme具备的所有基础,并添加了几个功能,如基于CSS的标准两列布局,对HTML Struts标签使用<div>,HTML Struts每个标签的标记,根据CSS样式表放置等。 |
struts.properties
# Standard UI theme
struts.ui.theme=xhtml
# Directory where theme template resides
struts.ui.templateDir=template
# Sets the default template type. Either ftl, vm, or jsp
struts.ui.templateSuffix=ftl
Struts2异常处理
全局异常映射,在Struts2的struts.xml的package中配置
<global-exception-mappings>
<exception-mapping exception="java.lang.NullPointerException" result="error" />
</global-exception-mappings>