第一天 Struts2概述、入门、常见配置,Action编写
一、struts2的概述
Struts2 是一个基于MVC设计模式的web层的框架。Struts2相对于Struts1内核已经发生了很大的变化。常见的web层的框架有:struts2、struts1、bebwork、springMVC
二、Struts2的入门小案例
2.1解压Struts2的开发包会得到:
①apps:Struts2提供的应用,war文件:web项目打包成war包,可以直接放到tomcat
②docs:Struts2 的开发文档和API
③lib:Struts2开发的jar包
④src:Struts2的源码
2.2创建项目,引入jar包
在apps中找到struts2-blank.war解压得到里面的jar包
2.3创建一个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>
<h1>Struts2的入门</h1>
<h3><a href="${pageContext.request.contextPath }/hello.action">Struts2的入门</a></h3>
</body>
</html>
2.4编写Action类
package com.itheima.struts.demo1;
/**
* Struts2的入门案例类
* @author Administrator
*
*/
public class HelloAction {
/**
* 提供一个方法
* 方法名是固定的,公有的,返回值是String类型,方法名是execute,在这个方法中不能传递参数
*/
public String execute(){
System.out.println("HelloAction执行了。。。。。 ");
return null;
}
}
2.5对Action进行配置
<?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>
<!-- Struts2为了Action配置,通过包进行管理 -->
<!-- 配置Struts的包 -->
<package name="demo1" extends="struts-default" namespace="/">
<!-- 配置Action -->
<action name="hello" class="com.itheima.struts.demo1.HelloAction"></action>
</package>
</struts>
2.6配置前端控制器(核心过滤器)
<!-- 配置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>
2.7修改Action中的返回值
package com.itheima.struts.demo1;
/**
* Struts2的入门案例类
* @author Administrator
*
*/
public class HelloAction {
/**
* 提供一个方法
* 方法名是固定的,公有的,返回值是String类型,方法名是execute,在这个方法中不能传递参数
*/
public String execute(){
System.out.println("HelloAction执行了。。。。。 ");
return “success”;
}
}
2.8配置Struts.xml里面的页面跳转
2.9编写success.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>
<h1>跳转成功页面!!!!!</h1>
</body>
</html>
三、Action的配置
3.1packa相关的配置
①package标签称为包,这个包与Java包的概念不一样,这个包是为了更好的管理action的配置
②【package标签的属性】
name | 包的名称,只有在一个项目中不重名即可 |
extends | 继承哪个包,通常值为struts-default |
namespace | 名称空间,与action标签中的name属性共同决定访问路径:名称空间有三种写法:1带名称的名称空间:namespace="/aaa";根名称空间:namespace="/";默认名称空间:namespace="" |
abstract | 抽象的,用于其他包的继承 |
3.2action相关的配置
①action标签配置action类
②【action标签的属性】
name | 与namespace属性共同决定访问路径 |
class | Action类的全路径 |
method | 执行action中的哪个方法的方法名,默认值是execute |
converter | 用于设置类型转换器 |
3.3常量的配置
在Struts2中提供了很多的常量(在default.properties)
在Struts2中有三个地方可以修改常量的值:
①struts.xml中进行修改
②在struts.properties中修改
struts.action.extension=action
③web.xml中配置
<init-param>
<param-name>struts.action.extendsion</param-name>
<param-value>xyz</param-value>
</init-param>
3.4分模块开发的配置
四、Action类的写法
4.1Action类是POJO类
public class HelloAction {
/**
* 提供一个方法
* 方法名是固定的,公有的,返回值是String类型,方法名是execute,在这个方法中不能传递参数
*/
public String execute(){
System.out.println("HelloAction执行了。。。。。 ");
return "success";
}
}
4.2Action实现了一个Action的接口
实现接口的方式提供了五个常量(五个逻辑视图的名称)
SUCCESS 成功
ERROR 失败
LOGIN 登录出错页面跳转
INPUT 表单校验的时候出错
NONE 不跳转
public class ActionDemo2 implements Action{
@Override
public String execute() throws Exception {
System.out.println("ActionDemo2执行了");
return NONE;
}
4.3继承ActionSupport类
public class ActionDemo3 extends ActionSupport{
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("ActionDemo3执行了");
return NONE;
}
}
推荐使用第三种:继承ActionSupport类,这个类提供了数据校验与国际化等操作方法
五、Action的访问
一般就是使用通配符的方式:
<action name="product_*" class="com.itheima.struts.demo3.ProductAction" method="{1}"></action>
第二天
一、servlet的API的访问
在使用Struts2的框架的过程中,发现Struts2 和Servlet的API是解耦合的。在实际开发中,经常使用到servlet的API,比如进行登录,将用户的信息保存到Session中,有的时候需要向页面输出一些内容,用到response对象。涉及到servlet的API的访问。
1.1完全解耦合的方式
public class RequestDemo1 extends ActionSupport{
@Override
public String execute() throws Exception {
//1 接受参数
//利用struts里面的对象ActionContext
ActionContext context = ActionContext.getContext();
//调用ActionContext中的方法
Map<String, Object> map = context.getParameters();
for (String key : map.keySet()) {
String [] value = (String[])map.get(key);
System.out.println(key + "...." + Arrays.toString(value));
}
//2向域对象中存入数据
context.put("reqName", "reqValue");
context.getSession().put("sessName", "sessValue");
context.getApplication().put("appName", "appValue");
return "success";
}
}
注意:这种方式只能获得代表request、session、application的数据的map集合,不能操作这些对象本身的方法。
1.2使用servlet的API原生方式
public class RequestDemo2 extends ActionSupport {
@Override
public String execute() throws Exception {
//一、接受数据
//直接获得request对象,通过ServletActionContext
HttpServletRequest request = ServletActionContext.getRequest();
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) {
String[] values = map.get(key);
System.out.println(key + "=====" + Arrays.toString(values));
}
//二、向域对象中保存数据
//向request中保存数据
request.setAttribute("reqName", "小豹子是笨蛋");
//向session中保存数据
request.getSession().setAttribute("sessName", "小煤球是傻瓜");
//向application中保存数据
ServletActionContext.getServletContext().setAttribute("appName", "小茗子是蛋瓜");
return SUCCESS;
}
}
注意:这种方式可以操作域对象的数据,同时也可以获取到对象的方法
此外还有接口注入的方式。
二、结果页面的配置
2.1全局结果页面的配置
全局结果页面:在包中只需要配置一次,其他在这个包中的所有action只要返回了这个值,都可以跳转到这个页面。
2.2局部结果页面的配置
局部结果页面:只能在当前的action中的配置有效。
2.3result标签的配置
result标签用于配置页面的跳转,在result标签上有两个属性。
name:逻辑视图的名称,默认值SUCCESS
type:页面跳转的类型:`
dispatcher | 默认值,请求转发(action转发JSP) |
redirect | 重定向(action重定向JSP) |
chain | 转发(action转发action) |
redirectAction | 重定向(action重定向action) |
stream | Struts2提供下载功能 |
三、 数据封装
3.1属性驱动:提供属性set方法的方式(不常用)
/**
* 数据封装的方式一:提供属性set方法的方式
* @author Administrator
*
*/
public class UserAction1 extends ActionSupport {
//提供对应的属性
private String username;
private String password;
private Integer age;
private Date birthday;
private Double salary;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String execute() throws Exception {
// 接收数据
System.out.println(username);
System.out.println(password);
System.out.println(age);
System.out.println(birthday);
System.out.println(salary);
//封装数据
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setAge(age);
user.setBirthday(birthday);
user.setSalary(salary);
return NONE;
}
}
3.2属性驱动:页面提供表达式
public class UserAction2 extends ActionSupport {
//提供一个user对象
private User user;
//提供set与get方法
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
3.3模型驱动的方式(最常用的方式)
public class UserAction3 extends ActionSupport implements ModelDriven<User>{
private User user = new User();
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return NONE;
}
@Override
public User getModel() {
// TODO Auto-generated method stub
System.out.println(user);
return user;
}
}
模型驱动方式只能同时向一个对象中封装数据。
使用第二种可以同时向多个对象中封装数据
3.4封装数据到list集合中
public class ProductAction1 extends ActionSupport {
private List<Product> products;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
@Override
public String execute() throws Exception {
for (Product product : products) {
System.out.println(product);
}
return NONE;
}
}
3.5封装数据到map集合中
public class ProductAction2 extends ActionSupport {
private Map<String,Product> map ;
public Map<String, Product> getMap() {
return map;
}
public void setMap(Map<String, Product> map) {
this.map = map;
}
@Override
public String execute() throws Exception {
for (String key : map.keySet()) {
Product product = map.get(key);
System.out.println(key + " " + product);
}
return NONE;
}
}
第三天
一、OGNL
OGNL:对象导航语言,比EL表达式强大很多倍的语言。
EL:从域对象中获取数据,从EL的11个对象中获取${name} ${pageContext.request.contextPath}
OGNl:调用对象的方法。获取Struts2值栈的数据,OGNL其实是第三方的表达式语言
1.1调用对象的方法
public void demo1() throws OgnlException{
OgnlContext context = new OgnlContext();
Object root = context.getRoot();
Object obj = Ognl.getValue("'hello'.length()", context, root);
System.out.println(obj);
}
1.2调用对象的静态方法
public void demo2() throws OgnlException{
OgnlContext context = new OgnlContext();
Object root = context.getRoot();
Object obj = Ognl.getValue("@java.lang.Math@random()", context, root);
System.out.println(obj);
}
执行表达式:@类名@方法名
1.3获取root中的数据(不需要加#)
public void demo3() throws OgnlException{
OgnlContext context = new OgnlContext();
context.setRoot(new User("aaa","123"));
Object root = context.getRoot();
Object username = Ognl.getValue("username", context, root);
Object password = Ognl.getValue("password", context, root);
System.out.println(username + " " + password);
}
1.4获取context中的数据(需要加#)
public void demo4() throws OgnlException{
OgnlContext context = new OgnlContext();
Object root = context.getRoot();
context.put("name", "小豹子");
Object name = Ognl.getValue("#name", context, root);
System.out.println(name);
}
二、值栈
2.1什么是值栈
值栈:valuestack:类似于一个数据中转站(Struts2中的数据都保存在值栈中)
valuestack接口,实现类OgnlValueStack对象
ValueStack贯穿整个action的生命周期,(action一旦创建了,框架就会创建一个valueStack对象)
2.2值栈的内部结构
值栈有两个主要的区域:
root区域:其实就是一个ArrayList。里面一般放对象。过去root数据不需要加#。
context区域:其实就是一个map。里面放的是web开发的常用的对象数据的引用。获取context数据需要加#。
我们所说的操作值栈通常是操作root区域。
2.3值栈与actioncontext的关系
servletContext servlet的上下文
actionContext action的上下文
①通过源码,当请求过来的时候,执行过滤器的doFilter方法,在这个方法中创建actioncontext,在创建actioncontext过程中,创建valuestack对象,将valuestack对象传递给actioncontext对象,所以可以通过actioncontext对象获取值栈对象。
②actioncontext对象之所以可以访问servlet的API(访问域对象的数据),因为在其内部有值栈的引用。
2.4值栈的获取
ValueStack valueStack = ActionContext.getContext().getValueStack();
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
一个action实例只有一个值栈对象
2.5操作值栈——向值栈中存入数据
①在action中提供属性的get方法的方式
②使用valuestack的本身的方法push
public class ValueStackDemo5 extends ActionSupport {
@Override
public String execute() throws Exception {
User user = new User("赵洪","1323");
ActionContext.getContext().getValueStack().push(user);
List<User> list = new ArrayList<User>();
list.add(new User("aaa","111"));
list.add(new User("bbb","222"));
list.add(new User("ccc","333"));
ActionContext.getContext().getValueStack().set("list", list);
ServletActionContext.getRequest().setAttribute("name", "李兵R");
ServletActionContext.getRequest().getSession().setAttribute("name", "s赵洪");
ServletActionContext.getServletContext().setAttribute("name", "a邓志龙");
return super.execute();
}
}
<h1>查看值栈的内部结构</h1>
<s:debug></s:debug>
<s:property value="username"/>
<s:property value="password"/>
<br>
<!-- 获取集合种的数据 -->
<s:property value="list[0].username"/>
<s:property value="list[0].password"/>
<s:property value="list[1].username"/>
<s:property value="list[1].password"/>
<s:property value="list[2].username"/>
<s:property value="list[2].password"/>
<!-- 获取context中的数据 -->
<s:property value="#request.name"/>
<s:property value="#session.name"/>
<s:property value="#application.name"/>
<s:property value="#attr.name"/>
<s:property value="#request.name"/>
第四天
一、拦截器
1.1什么是拦截器
拦截器:interceptor,起到拦截action的作用。
filter:过滤器,过滤从客户端向服务器发送的请求
拦截器:拦截客户端对action的访问。更细致的拦截。拦截action中具体的方法
Struts2核心的功能都是依赖拦截器来实现
1.2Struts2的执行流程
客户端向服务器发送一个action请求,执行核心过滤器(dofilter)方法。在这个方法中,调用executeAction()方法,在这个方法内部调用dispatcher.serviceAction();在这个方法内部创建一个action代理,最终执行的是action代理中的execute(),在代理中执行execute方法中调用Actioninvocation的invoke方法。这个方法内部递归执行一组拦截器(完成部分功能),如果没有下一个拦截器,就会执行目标action,根据acting返回的结果进行页面跳转。
二、 拦截器入门
2.1编写拦截器类
public class InterceptorDemo1 extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("InterceptorDemo1执行了。。。。。");
String obj = invocation.invoke();
System.out.println("InterceptorDemo1执行完毕了。。。");
return obj;
}
}
2.2配置拦截器
<struts>
<constant name="struts.action.extension" value="action"/>
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<package name="demo1" extends="struts-default" namespace="/">
<interceptors>
<interceptor name="interceptorDemo1" class="com.itheima.web.interceptor.InterceptorDemo1"></interceptor>
<interceptor name="interceptorDemo2" class="com.itheima.web.interceptor.InterceptorDemo2"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="interceptorDemo1"/>
<interceptor-ref name="interceptorDemo2"/>
</interceptor-stack>
</interceptors>
<action name="actionDemo1" class="com.itheima.web.action.ActionDemo1">
<result>/demo1/demo1.jsp</result>
<interceptor-ref name="myStack"/>
</action>
</package>
</struts>