Struts2的框架是应用在web层的框架-显示层
Struts2是在struts1和webwork之上发展的全新的框架
Struts可以解决的问题:
图。
Strut2的版本:
Web层常见的框架:
直接到apps下的实例程序中找jar包
package com.pshdhx.action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport{ public String execute() throws Exception { return "ok"; } } |
DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="helloDemo" extends="struts-default" namespace="/">
<action name="hello" class="com.pshdhx.action.HelloAction">
<result name="ok">/hello.jspresult> action> package> struts> |
访问路径:
http://localhost/struts2_day01/hello.action 404不能访问
配置文件的过程由过滤器做,需要配置过滤器
<filter> <filter-name>struts2filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class> filter>
<filter-mapping> <filter-name>struts2filter-name> <url-pattern>/*url-pattern>过滤所有页面--> filter-mapping> |
Servlet默认是第一次访问时创建
过滤器是启动服务器时创建
过滤器操作:
Class clazz = Class.forName(“action全路径”); //得到的方法是execute Method method = clazz.getMethod(“execute”); //方法执行 Object obj = method.invoke(); |
过滤器源代码:
Init(),过滤器服务器启动时创建,执行init方法
Default.properties Struts-default.xml Struts-plugin.xml Struts.xml :配置action和常量 Struts.properties :配置常量 Web.xml :配置核心过滤器和常量 |
名称和位置固定 :src下的struts2.xml
Package:
类似于代码中的包,区分不同的action,要配置action,必须先写package标签,在package里边才能配置action。
Name:属性值和其本身的功能没有关系,类似于id,在一个配置文件中可以写多个package标签,但是name属性值不能相同。
Extends:属性值固定为 struts-default。写了这个属性之后,在package里边配置的类,就有了action的功能。
Namespace:属性值和action标签里的name属性值构成访问的路径 / hello.action,默认是/,可以不写。
Action:
配置action的访问的路径
Name属性:与namespace的属性值构成访问路径
Class属性:action类的全路径
Method属性:默认执行的是execute方法,让action里的多个方法进行执行,可使用method方法进行定义。
Result:
根据返回值到不同的路径中去。不仅是页面,有可能是action
Name属性:和你方法的返回值一样
Type属性:配置如何到路径中去。默认值是转发的操作,还有可以是重定向的操作。转发操作:启动一次,地址栏不变。
在struts.xml文件中定义
<constant name="struts.i18n.encoding" value="UTF-8">constant> |
在struts.properties文件中配置
struts.i18n.encoding=UTF-8 |
表单提交到action里边,在action可以获取表单的提交数据
表单提交数据有中文,有乱码问题,解决
Post提交直接设置编码
Get提交做编码转换
如果在action获取表单通过post提交中文,中文的乱码方式解决了,不需要自己处理乱码问题。
在web.xml文件中进行配置
每个人都可以写配置文件,把写的配置文件引入到struts.xml文件中
<struts>
<include file="cn/pshdhx/action/hello.xml">include> struts> |
<action name="book_*" class="com.pshdhx.action.HelloAction" method="{1}">action> |
3.动态访问实现
<package name="local" extends="struts-default" namespace="/">
<global-results> <result name="success">/hello.jspresult> global-results> <action name="hello" class="com.pshdhx.action.HelloAction">action> <action name="others" class="com.pshdhx.action.OthersAction">action> package> |
既配置了全局页面,也有局部页面,以局部页面为准。
Type属性是如何到路径去
默认值:做转发操作,dispatch【一次请求,地址栏不发生改变】
重定向操作:redirect【两次请求,地址栏发生变化为*.jsp】
Chain:转发到action,一般因为缓存问题不用
RedirectAction:重定向到action。用处:添加之后到列表页面。
<result name="success" type="redirectAction">others.actionresult> |
之前在web阶段,提交表单到servlet里边,在servlet里边使用request对象获取到表单属性值,getParameter getParameterMap
表达提交到action,但是action没有request对象,不能直接使用request对象。
1、使用ActionContext类获取
Map
|
因为方法不是静态的方法,需要创建ActionContext对象 这个ActionContext对象不是new出来的 |
Static ActionContext getContext();获取当前线程的ActionContext对象 |
静态的所以ActionContext.method(); |
public String execute() throws Exception{ //第一种方式使用AcitonContext类获取 //获取ActionContext对象 ActionContext context = ActionContext.getContext(); //调用方法得到表单数据 //key是表单中的name值,value是输入的值 Map Set for(String key:keys) { //根据key得到value //数组方式:因为输入项里边可能有复选框情况 Object[] obj = (Object[]) map.get(key); System.out.println(Arrays.toString(obj)); } return NONE; } |
2、使用ServletActionContext类获取
Static HttpServletRequest getRequest(); 获取web应用的HttpServletRequest对象 |
Static HttpServletRequest getResponse(); 获取web应用的HttpServletResponse对象 |
Static ServletContext getServletContext(); 获取web应用的ServletContext对象 |
Static pageContext getPageContext(); 获取web应用的PageContext对象 |
静态方法的最大好处:类名可以直接调用;
public String execute() throws Exception{ //使用ServletActionContext类获取表单数据 HttpServletRequest request = ServletActionContext.getRequest(); String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username+" "+password); return NONE; } |
3、使用接口注入方式获取:
让action实现接口,为了得到request对象
public class FormAction3 extends ActionSupport implements ServletRequestAware{ //使用接口方式得到servletrequest对象 private HttpServletRequest request; @Override public void setServletRequest(HttpServletRequest request) { // TODO Auto-generated method stub this.request = request; } public String execute() throws Exception{ String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username+" "+password); return NONE; } } |
HttpServletRequest request = ServletActionContext.getRequest(); Request.setAttribute(“req”,”reqValue”); |
HttpSession session = request.getSession(); Session.setAttribute(“sess”,”sessValue”); |
ServletContext context = ServletActionContext.getServletContext(); Context.setAttribute(“contextName”,”contextValue”); |
1、属性封装
使用最原始的方式获取表单元素封装到实体类对象
public String execute() throws Exception{ HttpServletRequest request = ServletActionContext.getRequest(); String username = request.getParameter("username"); String password = request.getParameter("password"); User user = new User(); user.setUsername(username); user.setPassword(password); System.out.println(user); return NONE; } |
直接把表达提交属性封装到action属性中
2、模型驱动封装【重点】
可以直接把表单数据封装到实体类对象中去
public class FormAction5 extends ActionSupport implements ModelDriven private User user = new User();//实体类对象必须实例化,否则会得到null @Override public User getModel() { // TODO Auto-generated method stub return user; } public String execute() throws Exception{ System.out.println(user); return NONE; } } |
使用模型驱动和属性封装注意的问题:不能同时使用两个封装来封装一个表单对象,如果同时使用,那么执行的是模型驱动的方法,属性封装的内容为null。
5、比较表达式封装和模型驱动封装:
1、使用模型驱动只能把数据封装到一个实体类中。
2、使用表达式封装可以把数据封装到不同的实体类对象中去。
1、封装到list集合
1、在action声明List集合
2、生成list的set和get方法
3、在表单输入项里边写表达式封装的方法
<form action="${pageContext.request.contextPath}/list.action" method="post"> 用户名:<input type="text" name="list[0].username" />br> 密 码:<input type="password" name="list[0].password"/>br><br>
用户名:<input type="text" name="list[1].username" />br> 密 码:<input type="password" name="list[1].password"/>br><br> <input type="submit" value="提交"/> form> |
2、封装到map集合
1、声明map集合
2、生成set和get方法
3、在表单输入项的name属性写表达式
<form action="${pageContext.request.contextPath}/map.action" method="post"> 用户名:<input type="text" name="map[0].username" />br> 密 码:<input type="password" name="map[0].password"/>br><br>
用户名:<input type="text" name="map[1].username" />br> 密 码:<input type="password" name="map[1].password"/>br><br> <input type="submit" value="提交"/> form> |
public class FormMapAction extends ActionSupport{ private Map public Map return map; } public void setMap(Map this.map = map; } public String execute() throws Exception{ System.out.println(map); return NONE; } }
|
在web阶段学习过表达式EL:只能用在jsp中获取域对象里边的值。
也是一种表达式:功能更加强大,在struts2里边操作值栈数据,一般把ognl放在struts2里边进行操作;和struts2标签一起使用操作值栈,但它不是struts2的一部分,是一个单独的项目:
支持静态方法调用;调用objNamemethodName().
支持静态方法调用和值访问;@类全名@方法名(值).
支持赋值操作和表达式串联
访问ognl上下文和ActionContext
操作集合对象
1、导入jar包,在struts2里边有jar包
使用struts2标签的时候,在jsp中引入struts2的标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title heretitle> head> <body> body> html> |
在web阶段,在servlet里边进行操作,把数据放到域对象里边,在页面中使用el表达式获取到,域对象在一定范围之内,可以存放值和取值。
在struts之中,本身有存储机制,类似于域对象,可以存取数据。
在action之中,把数据放到值栈之中,在页面中取得值栈数据。
Servlet和action的区别:
每次访问action的时候,都会产生一个action对象
在每个action对象里边都会有一个值栈对象,只有一个
ActionContext context = ActionContext.getContext(); ValueStack stack = context.getValueStack(); |
第一部分root,结构是list集合
一般的操作都是root里边的数据
第二部分context,结构是map集合
Context处打断点,服务器debug执行,得到如下画面:
向值栈中放数据:
|
|
List[0].username; |
|
遍历list集合,得到每个user对象 机制:把每次遍历出来的user对象放到Context里边 获取context里边数据特点:写ognl表达式,使用#获取数据对象。 |
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> |
<c:forEach items="${list}" var="user"> ${user.username } ${user.password } c:forEach> |
EL表达式获取域对象的值
向域对象里边放值使用setAttribute方法,获取值使getAttribute方法;
底层增强request对象里边的方法,getAttribute方法
首先从request域里边获取值,获取到,直接返回;
如果从request域里边获取不到值,到值栈中把值获取出来,把值方法域对象里边去;
查看源代码:
增强request方法,有多种模式,有动态代理,继承。
Class StrutsRequestWrapper extends HttpServletRequestWrapper |
Public Object getAttribute(String key) |
#的使用:值栈的context里边的数据
获取request对象的值:
|
%的使用:在struts2标签里边使用ognl表达式,如果直接再struts2表单标签里边使用ognl表达式不识别,只有在%之后才识别。
普通: |
Ognl: |
只是struts2的概念,把框架的功能都是封装在拦截器中。
Struts2里边有很多的拦截器,不是每次所有拦截器都执行,只会执行一些默认的拦截器。
Struts2里边默认的拦截器的位置:默认的常量在core包中的default.property里边。默认的拦截器在struts-default.xml文件中。
拦截器在什么时候执行:
拦截器在action对象创建之后和action的方法执行之前
Aop思想和责任链模式如何应用到拦截器里边
拦截器在action创建之后,在action方法执行之前执行。
在action方法执行之前使用使用拦截器,执行过程中使用使用aop思想。在action里边没有直接调用拦截器的方法,使用配置文件的方式进行操作。在struts-default.xml文件中。
在拦截器执行的时候,执行很多的拦截器,这个过程使用责任链模式。
执行action
Execute.executeAction(request,reponse,mapping); |
创建action对象,使用动态代理模式
ActionProxy proxy = getContainer.getInstance(ActionProxyFactory.class).createActionProxy( Namespace,name,method,extraContext,true,false); |
执行很多的拦截器,遍历执行,放行。
If(interceptor.hasNext()) |
执行action的方法
Proxy.execute(); Return invocation.invoke(); |
过滤器:它可以过滤jsp,html,servlet,图片等路劲。
拦截器:它只会拦截action中的方法。
Class ModelDrivenInterceptor extends AbstractInterceptor implements Interceptor |
Void init(); Void destory(); String interceptor(ActionInvocation invocation); |
开发中建议使用继承MethodFilterInterceptor类实现 可以让action中的某个方法不进行拦截。 |
拦截器和action的关系 不是在action中调用拦截器的方法,而是通过配置文件的方式进行操作。 |
需求:在项目中,有很多action的超链接,实现只有是在登录的时候,才能点击点击action的超链接实现功能,如果不是登录状态,返回登录的界面。
使用session的域对象判断登录的状态:判断session里边是否有值。
Request.getSession().setAttribute(“username”,username); |
|
对action方法不进行拦截:
同一行: