文章目录
1.下载struts2.3并把核心jar包添加到WEB-INF/lib目录下
struts2.3下载地址
核心jar包指的是以下八个,在这个简单的例子里我们暂时只需要这八个
2.struts的表单处理流程
对于一般的web应用而言,表单提交之后交给servlet进行处理再跳转到新的jsp页面。
使用struts的主要变换在于MVC中的controller部分,view和module部分基本不变。
流程:
<form action="login.action">
->在web.xml中查找对应的过滤器(struts2的核心过滤器是FilterDispatcher)—>在struts.xml中找到对应的action(在这里即为<action name="login" class="...">
的action)->再根据class那行代码找到对应的action类,框架初始化该action再自动执行action中的setXxx()方法填充数据,再自动执行action的execute()方法。
而为了能够自动填充数据,就对html表单中的name名称有特定要求。
3.简单示例
①jsp表单——login.jsp。——注意name属性的值
这就是一个普通的登录页面
<%@ 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>登录</title>
</head>
<body>
<form action="login" method="post">
请输入用户名:<input name="loginUser.account" type="text"><br/>
请输入密码:<input name="loginUser.password" type="password">
<input type="submit" value="登录">
</form>
</body>
</html>
②配置文件——web.xml
放在WEB-INF目录下。在现阶段只需要照抄即可,<url-pattern>/*</url-pattern>
的意思即为改应用下所有的请求都交给FilterDispatcher进行处理
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- 让Struts2的核心Filter拦截所有请求 -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
③登录后跳转的页面——loginSuccess.jsp和loginFail.jsp。——无变化
这个是为了测试是否登录成功,能区分出来就可以了,在这里我让它们分别输出成功和失败。
loginSuccess.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>
成功
</body>
</html>
loginFail.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>
失败
</body>
</html>
④创建bean——UserBean.java。——无变化
注意由于后面注入值的时候会自动调用无参构造,所以这里如果自己写了构造函数那么要把无参构造补上,不然会炸。
package cn.edu.zjut.bean;
public class UserBean {
public UserBean() {
// TODO Auto-generated constructor stub
}
private String account="";
private String password="";
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
⑤创建service类——UserService.java。——为action类的execute()方法提供接口
在这里我们把它简单地设计为只要用户名和密码相同即可登录成功
package cn.edu.zjut.service;
import cn.edu.zjut.bean.*;
public class UserService {
public boolean login(UserBean loginUser) {
// TODO Auto-generated constructor stub
if(loginUser.getAccount().equals(loginUser.getPassword())) {
return true;
}
return false;
}
}
⑥重要的action方法——UserAction.java
在这里的setXxx是被自动执行的
execute()中一般来说并没有具体的业务逻辑,而是调用了service中的方法
注意execute()方法无参
package cn.edu.zjut.action;
import cn.edu.zjut.bean.*;
import cn.edu.zjut.service.*;
public class UserAction {
private UserBean loginUser;
public UserBean getLoginUser() {
return loginUser;
}
public void setLoginUser(UserBean loginUser) {
this.loginUser = loginUser;
}
public String execute() {
UserService userServ = new UserService();
if(userServ.login(loginUser)) {
return "success";
}
return "fail";
}
}
还可以使用ModelDriven接收参数,好处在于表单中的用户名name不需要再写成loginUser.username,直接写成username即可
package cn.edu.zjut.action;
import cn.edu.zjut.bean.*;
import cn.edu.zjut.service.*;
public class UserAction implements ModelDriven<UserBean>{
//必须实例化,刚刚是不需要实例化的
private UserBean loginUser = new UserBean();
//不需要get和setLoginUser
//照常
public String execute() {
……
}
//覆写
public UserBean getModel(){
return loginUser;
}
}
⑦非常重要的struts.xml——放在src目录下
<?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">
<!-- 上面这行需要联网环境,没联网需要把http://struts.apache.org/dtds/struts-2.3.dtd对应到本地struts-2.3.dtd文件路径 -->
<!-- 这个配置有助于开发中的提示和检错,对Struts配置没有影响 -->
<struts>
<package name="strutsBean" extends="struts-default" namespace="/">
<action name="login" class="cn.edu.zjut.action.UserAction">
<result name="success">/loginSuccess.jsp</result>
<result name="fail">/loginFail.jsp</result>
</action>
</package>
</struts>
- 这里的action name要和前面表单的action="xxx.action"中的xxx进行对应
- action后面的class是用来处理的完整action类名(带包名)
- result中的name和action类中的execute()方法返回值对应,有几个返回值就要有几个result。如果省略了name属性系统将采用默认的name属性值success。
- 一个struts中可以有多个
<package>
元素,用包机制将功能相似的Action放到同一个package中,因此package的name是自己取的。 - extends是package的可选属性,一般都会继承一个名为“struts-default”的内置包,它配置了Struts2所有的内置类型。继承将会继承父包中的所有配置,包括Action、result等(支持多继承,像这样:extends=“xx,xxx”)
- 默认的命名空间是"",但是struts2.1以后不能使用默认命名空间,所以一般来说namespace="/"
- 关于表单中的name:采用对象.属性的方式。对象就是在action当中实例化出来的名字,属性就是javaBean的属性名,例如在上面的例子里action中实例化出来的叫loginUser,则就是loginUser.account 和 loginUser.password(因为UserBean的属性是account和password)
4.Action搜索顺序
例如我们现在是http://localhost:8080/struts2/login.jsp
然后跳转到了http://localhost:8080/struts2/login.action
我们悄悄地在地址栏作一个修改:http://localhost:8080/struts2/aaa/bbb/ccc/login.action
发现结果依旧可以显示
因为struts2中Action的搜索顺序是这样的:
1.判断包aaa/bbb/ccc/是否存在,不存在则检查包aaa/bbb是否存在,不存在则检查aaa是否存在,又不存在则去默认namespace /
2.若在其中一步检查到包存在,则判断action是否在此包内存在,若不存在则去找默认namespace的package
3.若到了namespace的package都没法找到该Action 则报错
5.指定多个配置文件
在项目比较大的时候可以指定多个配置文件比如说user.xml
然后user.xml中就和原来的struts.xml一样写(一模一样)
而struts.xml只需要
……
<struts>
<include file="user.xml"></include>
<include ...>
....
<constant name="struts.i18n.encoding" value="utf-8"></constant>
</struts>
即可
如果有编码问题 可以在struts.xml中加<constant name="struts.i18n.encoding" value="utf-8"></constant>
6.默认Action
当找不到对应action的时候就会用到它,可以给用户提供较为易懂的报错信息,而不只是一个很不友好的404页面
在struts.xml中:
<struts>
<default-action-ref name="defaultAction"></default-action-ref>
<action name="defaultAction"> <!--这里要和上面的名字对应,上面那个名字是随便取的 -->
<result>/error.jsp</result>
</action>
</struts>
7.struts2后缀——.action变为.do等
访问的都是xxx.action 那么我们想它变成xxx.do而不是.action该怎么办呢?
在struts.xml中:
<struts>
<constant name="struts.action.extension" value="do"></constant>
</struts>
也可以在struts.properties中配置(多个后缀可用逗号隔开):
struts.action.extension=action,do,struts2
还可以在web.xml中进行配置(但不常用)
就是在<filter>
下,即配置struts2核心过滤器的地方加上
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do</param-value>
</init-param>
8.定义result的全局返回值
在struts.xml中:
<struts>
<package name="">
<global-results>
<result name="xxx">/xxx.jsp</result>
<global-results>
</package>
</struts>
result标签下其实是有子元素的,例如:
<result name="false">
<param name="location">/xx.jsp</param>
<param name="parse">false</param>
</result>
location就是要跳转去的地方
parse的false和true指的是是否可以在实际视图名字中使用OGNL表达式
它的默认值是true,即支持OGNL表达式 所以如果写的是true的话就等价于<result name="false">/xx.jsp</result>
没必要写那么复杂
这个一般不太用