目录
struts2笔记
struts2概述
1.struts框架应用javaee三层结构中web层框架
2.struts2框架在struts1和webwork基础之上发展全新的框架
struts2解决问题
web层常见框架
- springMVC
- struts
struts2框架入门
第一步:设置maven依赖
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.16</version>
</dependency>
第二步:创建action
package action;
public class HelloAction{
//一.每次访问servlet时候,都会执行service
// 1.继承HttpServlet,重写类里面的方法
// 2.在web.xml中配置servlet访问路径
//二.每次访问action,默认执行execute方法
// 1.配置action访问路径
public String execute(){
return "ok";
}
}
第三步:配置action类访问路径
1.创建struts2核心配置文件(struts.xml)
2.引入dtd约束
3.action基本配置
4.配置struts2过滤器
<?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>
<package name="helloDemo" extends="struts-default" namespace="/">
<!-- name:访问名称-->
<action name="hello" class="action.HelloAction">
<!-- 配置方法的返回值到页面-->
<result name="ok">/hello.jsp</result>
</action>
</package>
</struts>
web.xml
<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>
hello.jsp
<%--
Created by IntelliJ IDEA.
User: MY
Date: 2020/4/13
Time: 14:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
<h1>hello struts</h1>
</body>
</html>
访问路径:http://127.0.0.1/端口号/项目访问路径/hello.action
Struts2执行过程
查看源代码
package org.apache.struts2.dispatcher.ng.filter;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
protected PrepareOperations prepare;
protected ExecuteOperations execute;
protected List<Pattern> excludedPatterns = null;
public StrutsPrepareAndExecuteFilter() {
}
//过滤器在服务器启动时候创建,创建过滤器时候执行init方法
//加载配置文件(包含自己创建的配置文件和struts2自带配置文件)
// *struts.xml
// *web.xml
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
this.prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
this.execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
this.postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
try {
if (this.excludedPatterns != null && this.prepare.isUrlExcluded(request, this.excludedPatterns)) {
chain.doFilter(request, response);
} else {
this.prepare.setEncodingAndLocale(request, response);
this.prepare.createActionContext(request, response);
this.prepare.assignDispatcherToThread();
request = this.prepare.wrapRequest(request);
ActionMapping mapping = this.prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = this.execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
this.execute.executeAction(request, response, mapping);
}
}
} finally {
this.prepare.cleanupRequest(request);
}
}
public void destroy() {
this.prepare.cleanupDispatcher();
}
}
Struts2的核心配置文件
1.名称和位置固定的
2.在配置文件中主要三个标签package,action,result
- package
类似于代码包,区别不同的action,要配置action,必须首先写package,在package里面才能配置- (1)name属性
- name属性值功能本身没有关系的,在一个配置文件中可以写多个package标签,name属性__不可以相同__
- (2)extends属性
- 这个属性值固定的,struts-default
- 写了这个属性之后,在package里面配置的类具有action功能
- (3)namespace属性
- namespace属性值和action标签里面的name属性构成访问路径
- (1)name属性
- action
action标签配置action访问路径- action标签属性
- name属性:namespace属性值和action标签里面的name属性构成访问路径,在package标签里面写多个action标签,但是action的name属性值__不能相同的__
- class属性:action全路径
- method属性:在action里面默认执行execute方法,但是在action里面可以写其他的方法,使用method进行配置
- action标签属性
- reslut
根据action的方法返回值,配置到不同的路径里面
result标签属性- (1)name属性:和方法返回值一样
- (2)type属性:配置如何到路径中(转发或者重定向),默认为转发
struts2默认常量值
修改struts2默认常量
(1)常用的方式
在struts2.xml中进行配置
<constant name="struts.i18n.encoding" value="utf-8"/>
(2)还有两种方式(了解)
在src下面创建struts.properties,进行修改
在web.xml进行配置
最常用常量
struts.i18n.encoding=UTF-8
(1)表单提交数据到action里面,在action可以获取表单提交数据
(2)表单提交数据有中文,有乱码问题,解决
-post提交直接设置编码
-get提交做编码转换
(3)如果在action获取表单通过post提交中文,中文乱码问题帮解决了,不需要自己处理问题
分模块开发
1.单独写配置文件,把配置文件引入到核心配置文件中
<include file=""></include>
Action编写方式
1.action编写方式有三种方式
第一种:创建普通类,这个不继承任何类,不实现任何接口
第二种:创建类,实现接口Action
import com.opensymphony.xwork2.Action;
public class UserAction implements Action {
@Override
public String execute() throws Exception {
return null;
}
}
第三种:创建类,继承类ActionSupport(一般使用)
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
@Override
public String execute() throws Exception {
return super.execute();
}
}
访问action的方法
- 第一种:使用action标签的method属性,在这个属性里面写执行的action方法(action少)
缺陷:action每个方法都需要配置,如果action里面有多个方法,配置需要很多的action
import com.opensymphony.xwork2.ActionSupport;
//修改
public class HelloAction extends ActionSupport {
public String add() {
System.out.println("add...");
return NONE;
}
//更新
public String update() {
System.out.println("update...");
return NONE;
}
}
- 第二种:使用通配符方法实现(action多)
name属性值里面的*号
*匹配任意内容
<action name="*" class="action.HelloAction" method="{1}"> </action>
- 第三种:动态访问实现(不用)
错误示例
(1)如果action方法有返回值,在配置文件中没有配置,出现错误
<result name="not ok">/hello.jsp</result>
public String execute(){
return "ok";
}
报错:HTTP Status 404 - No result defined for action action.HelloAction and result ok
(2)在action里面的方法有返回值,如果有返回值类型必须是__String__
(3)action里面的方法可以没有返回值,没有返回值时候,在result标签不需要配置
1.把方法返回值设置为void
public class HelloAction {
public void execute() {
}
}
2.让返回值,返回“none”
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {
public String execute() {
return Action.NONE;
}
}
小案例,结合之前学的hibernate,显示全部地址到前端
dao层
public class AddressDao {
public List<Address> finAll() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到sessionFactory
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.getCurrentSession();
//开启事务
tx = session.beginTransaction();
//查询所有记录
Criteria criteria = session.createCriteria(Address.class);
// criteria.add(Restrictions.eq(propertyName, value))
List<Address> list = criteria.list();
//提交事务
tx.commit();
return list;
} catch (Exception e) {
tx.rollback();
return null;
}
}
service层
public class AddressService {
public List<Address> findAll() {
AddressDao addressDao = new AddressDao();
return addressDao.finAll();
}
}
Action
public class HelloAction extends ActionSupport {
public String add() {
System.out.println("add...");
return NONE;
}
public String update() {
System.out.println("update...");
return NONE;
}
public String list() {
AddressService addressService = new AddressService();
List<Address> list = addressService.findAll();
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("list", list);
return "list";
}
}
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.i18n.encoding" value="utf-8"/>
<package name="helloDemo" extends="struts-default" namespace="/">
<action name="address_*" class="action.HelloAction" method="{1}">
<result name="list">/list.jsp</result>
</action>
</package>
</struts>
结果页面配置
(1)全局结果页面
如果有多个action,方法里面返回值相同,到的页面也是相同的,这个时候可以使用全局结果页面配置
<action name="book" class="action.BookAction">
<result name="success">/hello.jsp</result>
</action>
<action name="orders" class="action.OrderAction">
<result name="success">/hello.jsp</result>
</action>
<global-results>
<result name="success">/hello.jsp</result>
</global-results>
<action name="book" class="action.BookAction">
<!-- <result name="success">/hello.jsp</result>-->
</action>
<action name="orders" class="action.OrderAction">
<!-- <result name="success">/hello.jsp</result>-->
</action>
(2)局部结果页面
<action name="book" class="action.BookAction">
<result name="success">/hello.jsp</result>
</action>
如果全局和局部都配置了,以局部为准
(3)result标签type属性
type:如何到路径里面(转发还是重定向)
- type属性值
- dispatcher,默认值,转发(type=“dispatcher”)
- redirect,重定向(type=“redirect”)
- chain:转发到action,一般不用,缓存问题
- redirectAction:重定向到action
在action获取表单提交数据
(1)使用ActionContext类获取
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>form01</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/form01.action" method="post">
username:<input type="text" name="username"/>
<br/>
password:<input type="text" name="password"/>
<br/>
address:<input type="text" name="address"/>
<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
<package name="demo02" extends="struts-default" namespace="/">
<action name="form01" class="action.form01Action" method="execute">
</action>
</package>
public class form01Action extends ActionSupport {
@Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Map map = actionContext.getParameters();
Set<String> keys = map.keySet();
for (String key : keys) {
Object[] obj = (Object[]) map.get(key);
System.out.println(Arrays.toString(obj));
}
return NONE;
}
}
结果
(2)使用ServletActionContext类获取
public String execute() throws Exception {
HttpServletRequest httpServletRequest = ServletActionContext.getRequest();
String username = httpServletRequest.getParameter("username");
String password = httpServletRequest.getParameter("password");
String address = httpServletRequest.getParameter("address");
System.out.println(username + password + address);
return NONE;
}
(3)使用接口注入方式获取
public class form01Action extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
@Override
public String execute() throws Exception {
request.getParameter("username");
request.getParameter("password");
request.getParameter("address");
return NONE;
}
@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.request = httpServletRequest;
}
}
在action操作域对象
request,session,servletContext
使用ServletActionContext类操作
// request域对象
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("req", "reqValue");
// session域对象
HttpSession session = request.getSession();
session.setAttribute("sess", "sessValue");
// ServletContext域对象
ServletContext context = ServletActionContext.getServletContext();
context.setAttribute("context", "contextValue");
struts封装获取表单数据方式
(1)属性封装
1.在action员工变量位置定义变量,变量名称和表单输入项的name属性值__一样__
2.生成变量的set方法
public class form01Action extends ActionSupport {
private String username;
private String password;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String execute() throws Exception {
System.out.println(username+password+address);
return NONE;
}
}
(2)模型驱动封装
1.使用模型驱动方法,可以直接把表单数据封装到实体类对象里面
2.实现步骤
- action实现接口ModelDriven
- 实现接口里面的方法getModel方法
- 在action里面创建实体类对象
public class form01Action extends ActionSupport implements ModelDriven<loginUser> {
private loginUser user = new loginUser();
@Override
public String execute() throws Exception {
System.out.println(user.toString());
return NONE;
}
@Override
public loginUser getModel() {
return user;
}
}
在一个action中,获取表单数据可以属性封装,使用模型封装,不能同时使用属性封装和模型驱动封装获取同一个表单数据,如果同时使用,只会执行模型驱动
(3)表达式封装
1.第一步:在action里面声明实体类
2.第二步:生成实体类变量的set和get方法
3.第三步:在表单输入项的name属性值里面写表达式形式
public class form01Action extends ActionSupport {
private loginUser loginUser;
public domain.loginUser getLoginUser() {
return loginUser;
}
public void setLoginUser(domain.loginUser loginUser) {
this.loginUser = loginUser;
}
@Override
public String execute() throws Exception {
System.out.println(loginUser.toString());
return NONE;
}
}
<form action="${pageContext.request.contextPath}/form01.action" method="post">
username:<input type="text" name="loginUser.username"/>
<br/>
password:<input type="text" name="loginUser.password"/>
<br/>
address:<input type="text" name="loginUser.address"/>
<br/>
<input type="submit" value="提交">
表达式封装和模型驱动比较
1.使用表达式封装和模型驱动封装都可以把数据封装到实体类对象中
2.不同点:
- 使用模型驱动只能把数据封装到一个实体类对象里面
- 使用表达式封装可以把数据封装到不同的实体类对象里面
<form action="${pageContext.request.contextPath}/form01.action" method="post">
username:<input type="text" name="loginUser.username"/>
<br/>
password:<input type="text" name="loginUser.password"/>
<br/>
address:<input type="text" name="loginUser.address"/>
<br/>
bookName:<input type="text" name="book.name"/>
<br/>
<input type="submit" value="提交">
</form>
public class form01Action extends ActionSupport {
private loginUser loginUser;
private Book book;
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public domain.loginUser getLoginUser() {
return loginUser;
}
public void setLoginUser(domain.loginUser loginUser) {
this.loginUser = loginUser;
}
@Override
public String execute() throws Exception {
System.out.println(loginUser.toString()+book.getName());
return NONE;
}
}
struts2获取数据封装到集合中
(1)List集合
- 第一步:在action声明List
- 第二步:生成list变量的get和set方法
- 第三步:在表单输入项里面写表达式
<form action="${pageContext.request.contextPath}/form01.action" method="post">
username:<input type="text" name="list[0].username"/>
<br/>
password:<input type="text" name="list[0].password"/>
<br/>
address:<input type="text" name="list[0].address"/>
<br/>
username:<input type="text" name="list[1].username"/>
<br/>
password:<input type="text" name="list[1].password"/>
<br/>
address:<input type="text" name="list[1].address"/>
<br/>
<input type="submit" value="提交">
</form>
private List<loginUser> list;
public List<loginUser> getList() {
return list;
}
public void setList(List<loginUser> list) {
this.list = list;
}
(2)map集合
<form action="${pageContext.request.contextPath}/form01.action" method="post">
username:<input type="text" name="map['one'].username"/>
<br/>
password:<input type="text" name="map['one'].password"/>
<br/>
address:<input type="text" name="map['one'].address"/>
<br/>
username:<input type="text" name="map['two'].username"/>
<br/>
password:<input type="text" name="map['two'].password"/>
<br/>
address:<input type="text" name="map['two'].address"/>
<br/>
<input type="submit" value="提交">
public class form01Action extends ActionSupport {
private Map<String,loginUser> map;
public Map<String, loginUser> getMap() {
return map;
}
public void setMap(Map<String, loginUser> map) {
this.map = map;
}
小案例:添加地址结合hibernate框架
struts的核心配置文件
<?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>
<package name="helloDemo" extends="struts-default" namespace="/">
<action name="address_list" class="action.formAction" method="list">
<result name="success">/list.jsp</result>
</action>
<action name="address_add" class="action.formAction" method="execute">
<result name="success">/add.jsp</result>
</action>
<action name="address_addToList" class="action.formAction" method="add_ToList">
<result name="success" type="redirect">/address_list</result>
</action>
</package>
</struts>
添加城市的表单页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>add</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/address_addToList.action" method="post">
城市名称:<input type="text" name="city_name">
城市描述:<input type="text" name="city_description">
<input type="submit" value="提交">
</form>
</body>
</html>
处理操作的action
package action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import domain.Address;
import org.apache.struts2.ServletActionContext;
import service.AddressService;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
public class formAction extends ActionSupport implements ModelDriven<Address> {
private Address address = new Address();
public String list() {
AddressService addressService = new AddressService();
HttpServletRequest request = ServletActionContext.getRequest();
List<Address> list = addressService.findAll();
request.setAttribute("list", list);
return "success";
}
public String add_ToList() {
AddressService addressService = new AddressService();
addressService.add(address);
return SUCCESS;
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
@Override
public Address getModel() {
return address;
}
}
service层(需要的一些功能)
package service;
import dao.AddressDao;
import domain.Address;
import java.util.List;
public class AddressService {
public List<Address> findAll() {
AddressDao addressDao = new AddressDao();
return addressDao.finAll();
}
public void add(Address address) {
AddressDao addressDao = new AddressDao();
addressDao.add(address);
}
}
dao层(操作数据库的原子操作)
import java.util.List;
public class AddressDao {
public List<Address> finAll() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到sessionFactory
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.getCurrentSession();
//开启事务
tx = session.beginTransaction();
//查询所有记录
Criteria criteria = session.createCriteria(Address.class);
// criteria.add(Restrictions.eq(propertyName, value))
List<Address> list = criteria.list();
//提交事务
tx.commit();
return list;
} catch (Exception e) {
tx.rollback();
}
return null;
}
public void add(Address address) {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到sessionFactory
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.getCurrentSession();
//开启事务
tx = session.beginTransaction();
session.save(address);
//提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
}
}
}
显示全部地址的页面
<%--
Created by IntelliJ IDEA.
User: MY
Date: 2020/4/15
Time: 19:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>list</title>
</head>
<body>
<c:if test="${!empty(list)}">
<table border="1px">
<td>编号</td>
<td>城市名字</td>
<td>城市简介</td>
</th>
<c:forEach items="${list}" var="list">
<tr>
<td>${list.city_id}</td>
<td>${list.city_name}</td>
<td>${list.city_description}</td>
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
值栈
- 之前在web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到,域对象在一定范围内,存值和取值
- 在struts2里面提供本身一种存储机制,类似于域对象,是值栈,可以存值和取值
- 在action里面把数据放到值栈里面, 在页面中获取到值栈数据
- servlet和action区别
- Servlet:默认在第一次访问时候创建,创建一次,单实例对象
- Action:访问时候创建, 每次访问action时候,都会创建action对象,创建多次,多实例对象
- 值栈存储位置
- 每次访问action时候,都会创建action对象
- 在每个action对象里面都会有一个值栈对象
获取值栈对象
- 获取值栈对象有多种方式
- 常用:AtionContext类里面的方法得到值栈对象
值栈的内部结构
栈:后进先出
第一部分__root__,结构式list集合,一般操作都是root里面数据
第二部分__context__,结构map集合
向值栈放数据
(1)s:debug标签
- 使用这个标签可以查看值栈结构和存储值
- 访问action,执行action的方法有返回值,配置返回值到jsp页面中,在jsp页面中使用这个标签(因为值栈在action中创建)
在页面中显示[Debug],点击超链接看到值栈结构 - 在action没有任何操作,栈顶元素就是action引用,action对象里面有值栈对象,值栈对象里面有action引用
(2)向值栈中放数据 - 第一种:获取值栈对象,调用值栈对象里面的set方法
public String getValueStack() {
ActionContext actionContext = ActionContext.getContext();
ValueStack valueStack = actionContext.getValueStack();
valueStack.set("username","张三");
return SUCCESS;
}
- 第二种:获取值栈对象,调用值栈对象里面的push方法
public String getValueStack() {
ActionContext actionContext = ActionContext.getContext();
ValueStack valueStack = actionContext.getValueStack();
valueStack.set("username","张三");
valueStack.push("李四");
return SUCCESS;
}
- 第三种:在action定义变量,生成定义变量,生成变量的get方法
private String name;
public String getName() {
return this.name;
}
public String findValueStack() {
name="张三";
return SUCCESS;
}
向值栈放对象
1.第一步:定义对象
2.第二步:生成变量的get方法
3.第三步:在执行的方法里面设置对象的值
private Address address = new Address();
public Address getAddress() {
return address;
}
public String findValueStack() {
address.setCity_name("南通");
address.setCity_description("美女很多。。");
return SUCCESS;
}
向值栈放list对象
1.第一步:定义list集合变量
2.第二步:生成变量的get方法
3.第三步:在执行的方法里面向list集合设置值
private List<Address> list = new ArrayList<Address>();
public List<Address> getList() {
return list;
}
public String findValueStack() {
Address address=new Address();
address.setCity_name("东京");
address.setCity_description("东京热~~");
Address address1=new Address();
address1.setCity_name("墨西哥");
address1.setCity_description("墨西哥黑帮");
list.add(address);
list.add(address1);
return SUCCESS;
}
从值栈获取数据
使用struts2的标签+ognl表达式获取值栈数据
<s:property value=""></s:property>
- 获取字符串
<s:property value="username"/>
- 获取对象
<s:property value="address.city_name"/>
<s:property value="address.city_description"/>
- 获取list集合
<s:property value="list[0].city_description"/>
<s:property value="list[0].city_name"/>
<s:iterator value="list">
<s:property value="city_description"/>
<s:property value="city_name"/>
</s:iterator>
<s:iterator value="list" var="address">
<s:property value="#address.city_description"/>
<s:property value="#address.city_name"/>
</s:iterator>
- 其他操作
(1)使用set方法向值栈放数据,获取
<s:property value="username"/>
(2)使用push方法向值栈放数据,获取
<s:property value="[0].top"/>
el表达式为什么也可以获取值栈数据?
<c:forEach items="${list}" var="address">
${address.city_name}
${address.city_description}
<br/>
</c:forEach>
- EL表达式获取值栈数据
2.向域对象里面放值使用setAttribute方法,获取值使用getSttribute方法
3.底层增强request对象里面的方法getAttribute方法
(1)首先从request域获取值,如果获取到,直接返回
(2)如果从request域获取不到值,到值栈中把值获取出来,把值放到域对象里面
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
.
.
.
public Object getAttribute(String key) {}
.
.
.
OGNL的#,%作用
在值栈中获取request域中数据
HttpServletRequest request=ServletActionContext.getRequest();
request.setAttribute("req","hello word");
<s:property value="#request.req"/>
在struts2表单标签中显示request域数据
<s:textfield name="username" value="%{#request.req}"> </s:textfield>
Struts2拦截器概述
1.struts2是框架,封装了很多的功能,struts2里面封装的功能都是在拦截器里面
2.struts2里面封装了很多的功能,有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器
3.struts2里面默认拦截器位置
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
...
4.拦截器在什么时候执行?
(1)在action对象创建之后,action的方法执行之前
拦截器底层原理
- AOP思想
AOP是面向切面编程。如果要扩展功能,不通过修改源代码方式扩展功能
- 责任链模式
(1)在java中有很多的设计模式
(2)责任链模式和过滤链很相似的
过滤链:一个请求可以有多个过滤器进行过滤,每个过滤器只有放行才能到下一个过滤器
责任链模式:要执行多个操作,有添加,修改,删除三个操作。首先执行添加操作,添加操作执行之后做类似于放行的操作,修改操作执行之后做类似放行操作,执行删除操作
aop思想和责任链模式如何应用到拦截器里面
(1)文字描述:
- 拦截器在action对象创建之后,action的方法执行之前
- 在action方法执行之前只执行默认拦截器,执行过程使用aop思想,在action里面没有直接调用拦截器的方法,使用配置文件方式进行操作
- 在执行拦截器时候,执行很多的拦截器,这个过程使用责任链模式
- 假如执行三个拦截器,执行拦截器1,执行拦截器1之后做放行操作,执行拦截器2,以此类推,然后执行action的方法
(2)画图分析:
n
过滤器和拦截器
(1)过滤器:过滤器理论上可以过滤任意内容,html,jsp,servlet,图片路径
(2)拦截器:拦截器可以拦截action
Servlet和action区别
(1)servlet默认第一次访问时候创建,创建依次,单实例对象
(2)action每次访问时候创建,创建多次,多实例对象
自定义拦截器
(1)在struts2里面有很多的拦截器,这些拦截器是struts2封装的功能,但是在实际开发中,struts2里面的拦截器中没有要使用的功能,这个时候需要自己写拦截器实现
public interface Interceptor extends Serializable {
void destroy();//销毁
void init();//初始化操作
String intercept(ActionInvocation var1) throws Exception;//拦截逻辑的操作
}
(2)开发中,建议使用另外一种方式
- 写类,继承MethodFilterInterceptor类实现
- 让action里面的某个方法不进行拦截
(3)让拦截器和action有关系 - 不是在action调用拦截器方法,而是通过配置文件方式建立关系
自定义登陆拦截器
第一步 创建类,继承__MethodFilterInterceptor__类
public class LoginInterceptor extends MethodFilterInterceptor {
第二步重写MethodFilterInterceptor类里面的方法写拦截器逻辑
@Override
protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
Object obj = request.getSession().getAttribute("user");
if (obj != null) {
return actionInvocation.invoke();
} else {
return "error";
}
}
第三步配置action和拦截器关系(注册拦截器)
(1)在要拦截的action标签所在的package标签里面声明拦截器
<interceptors>
<interceptor name="logininterceptor" class="interceptor.LoginInterceptor"></interceptor>
</interceptors>
(2)在具体的action标签里面使用声明的拦截器
<interceptor-ref name="login"></interceptor-ref>
(3)struts里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,问题:默认的拦截器都不会执行了。
解决:把默认拦截器手动使用一次
<interceptor-ref name="defaultStack"></interceptor-ref>
但是登陆的action不能拦截,不然永远不能登陆
解决:在声明的拦截器中添加
<param name="excludeMethods">login</param>
* 让action里面的某个方法不进行拦截
(3)让拦截器和action有关系
* 不是在action调用拦截器方法,而是通过配置文件方式建立关系
#### 自定义登陆拦截器
第一步 创建类,继承__MethodFilterInterceptor__类
```java
public class LoginInterceptor extends MethodFilterInterceptor {
第二步重写MethodFilterInterceptor类里面的方法写拦截器逻辑
@Override
protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
Object obj = request.getSession().getAttribute("user");
if (obj != null) {
return actionInvocation.invoke();
} else {
return "error";
}
}
第三步配置action和拦截器关系(注册拦截器)
(1)在要拦截的action标签所在的package标签里面声明拦截器
<interceptors>
<interceptor name="logininterceptor" class="interceptor.LoginInterceptor"></interceptor>
</interceptors>
(2)在具体的action标签里面使用声明的拦截器
<interceptor-ref name="login"></interceptor-ref>
(3)struts里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,问题:默认的拦截器都不会执行了。
解决:把默认拦截器手动使用一次
<interceptor-ref name="defaultStack"></interceptor-ref>
但是登陆的action不能拦截,不然永远不能登陆
解决:在声明的拦截器中添加
<param name="excludeMethods">login</param>