一、OGNL概述:OGNL是一种表达式
(1)在struts2中操作值栈数据。
(2)一般把ognl在struts2中操作,和struts2标签一起使用操作值栈。
(3)ognl不是strut2的一部分,是单独的项目,经常和struts2一起使用。
(4)使用ognl的时候首先要导入jar包。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!-- 引入struts2标签 -->
<%@ 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>ognl案例</title>
</head>
<body>
<!-- ognl+struts2实现计算字符串长度 -->
<!-- value值:ognl表达式 -->
<s:property value="'这是一个字符串'.length()"/>
</body>
</html>
二、值栈:
1、概述:
(1)值栈是struts2提供的一种存储机制,类似于域对象,可以存值和取值。
(2)Servlet和Action的区别:
Servlet:默认在第一次访问时创建,只创建一次,单实例对象。
Action:访问时候创建,每次访问action的时候,都会创建action对象,创建多次,多实例对象。
(3)值栈存储位置:
在每个action对象里面都会有一个值栈对象(只有一个)
2、获取值栈对象:
(1)获取值栈对象有多种方式,常用方式是:使用ActionContext类里面的方法得到值栈对象。
(2)每个action对象中只有一个值栈对象。
public class StackDemoAction extends ActionSupport {
public String execute(){
//1.获取ActionContext类的对象
ActionContext context=ActionContext.getContext();
//调用方法获取值栈对象:
ValueStack stack1=context.getValueStack();
ValueStack stack2=context.getValueStack();
System.out.println(stack1==stack2);//输入结果为true
return NONE;
}
}
3、值栈内部结构:
(1)值栈一般分为两部分:
第一部分是root,结构是list集合,一般操作都是root里面的数据。
第二部分是context,结构是map集合。
(2)struts2里面标签<s:debug>,使用这个标签可以查看值栈结构和存储值:
访问action,执行action的方法有返回值,配置返回到jsp页面中,在jsp页面中使用这个标签:
(3)action对象里面有值栈对象,值栈对象里面有action引用。
在action没有做任何操作,栈顶元素默认是action的引用。
4、向值栈放数据的三种方式:
(1)第一种:Set方法:HashMap类型(重新分配空间)
//向值栈放数据的三种方式:
public class SaveStackDemoAction extends ActionSupport {
public String execute(){
//获取ActionContext对象,调用方法获取值栈对象
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
//第一种:set方法:
stack.set("stackobject", "第一个对象");
return "test";
}
}
(2)第二种:Push方法:String类型(重新分配空间):
//向值栈放数据的三种方式:
public class SaveStackDemoAction extends ActionSupport {
public String execute(){
//获取ActionContext对象,调用方法获取值栈对象
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
//第二种:push方法:
stack.push("第二个对象");
return "test";
}
}
(3)第三种(常用):在action中定义常量,生成变量的get方法。(不用重新分配空间)
//向值栈放数据的三种方式:
public class SaveStackDemoAction2 extends ActionSupport {
//第三种方式:
//在action中定义变量,生成变量的get方法
private String object;
public String getObject() {
return object;
}
public String execute(){
object="第三个对象";
return "test";
}
}
5、向值栈放对象:
实现步骤:
(1)第一步:在action中定义对象变量;
(2)第二步:生成变量的get方法;
(3)第三步:在执行的方法里面,给对象设置值;
//向值栈放对象:
public class SaveStackDemoAction3 extends ActionSupport {
//在action中定义对象变量,生成对象的get方法
private User user;
public User getUser() {
return user;
}
public String execute(){
//在执行的方法里面,给对象设置值。
user=new User();
user.setUid(1);
user.setUsername("张三");
user.setPassword("123456");
user.setAddress("中国");
return "test";
}
}
6、向值栈放List集合:
实现步骤:
(1)第一步:在action中,定义list集合;
(2)第二步:生成list集合的get方法;
(3)第三步:在执行的方法里面,给集合设置值。
//向值栈放list集合:
public class SaveStackDemoAction4 extends ActionSupport {
//在action中定义list集合,生成对象的get方法
private List<User> list=new ArrayList<User>();
public List<User> getList() {
return list;
}
public String execute(){
//在执行的方法里面,给list集合设置值。
User user1=new User();
user1.setUsername("张三");
user1.setPassword("123456");
user1.setAddress("中国");
User user2=new User();
user2.setUsername("李四");
user2.setPassword("654321");
user2.setAddress("北京");
list.add(user1);
list.add(user2);
return "test";
}
}
7、从值栈中获取数据:
使用struts2的标签+ognl表达式获取值栈数据:
<s:property value=”ognl表达式”/>
例子:获取字符串;获取对象;获取list集合;取出set方法存取的数据;取出push方法存取的数据;
//在action中存放数据:
public class ReadStackDemoAction extends ActionSupport {
//设置字符串
private String username;
public String getUsername() {
return username;
}
//设置对象
private User user=new User();
public User getUser() {
return user;
}
//设置list集合
private List<User> list=new ArrayList<User>();
public List<User> getList() {
return list;
}
public String execute(){
username="这是一个字符串";
user.setUsername("这是一个对象");
user.setPassword("123456");
user.setAddress("china");
User user1=new User();
User user2=new User();
user1.setUsername("张三");
user1.setPassword("123456");
user1.setAddress("china");
user2.setUsername("李四");
user2.setPassword("123456");
user2.setAddress("English");
list.add(user1);
list.add(user2);
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
//使用set方法存数据:
stack.set("set", "set方法存的数据");
//使用push方法存数据:
stack.push("push方法存的数据");
return "test";
}
}
<%@ 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>
<s:debug></s:debug>
<!-- 在jsp中获取字符串 -->
获取值栈的字符串:<br/>
<s:property value="username"/><br/>
<br/>
获取值栈的对象:<br/>
<s:property value="user.name"/>
<s:property value="user.password"/>
<s:property value="user.address"/><br/><br/>
获取值栈的list集合:<br/>
第一种方式:<br/>
<s:property value="list[0].name"/>
<s:property value="list[0].password"/>
<s:property value="list[0].address"/><br/>
<s:property value="list[1].name"/>
<s:property value="list[1].password"/>
<s:property value="list[1].address"/><br/><br/>
第二种方式(常用):<br/>
<!-- 使用s:iterator:遍历值栈的list集合 -->
<s:iterator value="list">
<s:property value="name"/>
<s:property value="password"/>
<s:property value="address"/><br/>
</s:iterator>
<br/>
第三种方式(最常用):<br/>
<s:iterator value="list" var="user">
<!-- 遍历值栈list集合,得到每个user对象
机制:把每次遍历出来的user对象放到context中
获取context里面数据的特点:写ognl表达式
使用特殊符号# -->
<s:property value="#user.name"/>
<s:property value="#user.password"/>
<s:property value="#user.address"/><br/>
</s:iterator><br/>
<!-- 取出set方法存取的数据,根据名称获取值 -->
<s:property value="set"/>
<br/><br/>
<!-- 取出push方法存取的数据-->
<!-- (1)使用push方法设置值,没有名称,只有设置的值
(2)向值栈放数据,会把向值栈放的数据存到数组里面,
数值名称为top,根据数据获取值 -->
<s:property value="[0].top"/>
</body>
</html>
8、EL表达式怎么获取值栈数据:
(1)EL表达式获取域对象值;
(2)向域对象里面放值使用setAttribute方法,获取值使用getAttribute方法。
(3)底层增强request对象里面的getAttribute方法:
–如果从request域获取值,如果获取到,则直接返回;
–如果从request域获取不到值,到值域中把值获取出来,把值放到域对象里面。
9、#和%的使用:
(1)#的使用:获取context里面的数据;
(2)%的使用:在struts2标签里面使用ognl表达式,如果直接在struts2表单标签里面使用ognl表达式会发生不识别,只有在%之后才会识别。
三、拦截器:
1、struts2拦截器的介绍:
(1)struts2是框架,封装了很多的功能,struts2里面封装的功能很多都是在拦截器里面。
(2)struts2有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器
(3)默认拦截器的位置:struts2-core的jar包下面的struts-default.xml文件:
以下是默认的拦截器:
<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="datetime"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
(4)拦截器在action对象创建之后,action的方法执行之前执行。
(5)拦截器底层使用两个原理:
第一个:aop思想:AOP是面向切面的编程,不改变源代码,就可以增加功能;
第二个:责任链模式;
(6)aop思想和责任链模式如何应用到拦截器里面?
①拦截器在action对象创建之后,action的方法执行之前执行。
②在action方法执行之前执行默认拦截器,执行过程使用aop思想,在action没有直接调用拦截器的方法,使用配置文件方式进行操作。
③ 在执行拦截器的时候,会执行很多的拦截器,这个过程使用到责任链模式:
–假如执行三个拦截器,执行拦截器1,执行拦截器1之后做放行操作,执行拦截器2,执行拦截器2之后做放行操作,执行拦截器3,执行拦截器3之后做放行,执行action方法。
2、拦截器的执行过程:
3、过滤器和拦截器的区别:
(1)过滤器:理论上可以拦截任意内容,比如html,jsp,servlet,图片路径。
(2)拦截器:拦截器值拦截action。
4、servlet和action的区别:
(1)servlet:第一次访问的时候创建,创建一次,单实例对象。
(2)action:每次访问的时候都会创建,多实例对象。
5、自定义拦截器:
(1)首先,我们查看源代码看拦截器的结构:
(2)在接口里面有三个方法:
void init();//初始化操作
void destroy();//销毁操作
String intercept(ActionInvocation invocation);//拦截逻辑的操作
(3)在实际开发中,建议使用另外一种方式开发:
①创建类,继承MethodFilterInterceptor类实现;
②重写里面的doIntercept方法,拦截器逻辑写在方法体里面。
6、举例:登陆拦截器:
(1)判断是否登陆:判断session里面是否有名称是username的值;
(2)拦截器实现过程:
第一步:创建类,继承MethodFilterInterceptor类;
第二步:重写MethodFilterInceptor类里面的方法,方法里面写拦截器逻辑;
//创建拦截器类:继承MethodFilterInterceptor类
public class myIntercept extends MethodFilterInterceptor {
//重写里面的doIntercept方法,拦截器逻辑写在方法体里面
@Override
protected String doIntercept(ActionInvocation arg0) throws Exception {
//取得username的值
HttpServletRequest request=ServletActionContext.getRequest();
Object obj=request.getSession().getAttribute("username");
System.out.println(obj);
if(obj!=null){
//已经登陆,拦截器做类似于放行的操作
return arg0.invoke();
}
else{
//没有登陆,不执行action里面的方法,返回登陆界面
//回到result标签里面寻找到fail的值,到相应的配置路径中去
return "fail";
}
}
}
第三步:注册拦截器,配置action和拦截器的关系:
<!-- 登陆拦截器配置: -->
<!-- 1.首先在package标签中声明要使用的拦截器 -->
<interceptors>
<interceptor name="logininterceptor" class="com.zwp.intercept.myIntercept"></interceptor>
</interceptors>
<action name="customer_*" class="com.zwp.action.login.loginAction" method="{1}">
<!-- 2.在action里使用自定义拦截器-->
<interceptor-ref name="logininterceptor">
<!-- 配置action里面的某些方法不进行拦截 :name:excludeMethods;值:action不拦截方法的名称 -->
<param name="excludeMethods">login</param>
</interceptor-ref>
<!-- 3.当使用了自定义拦截器的时候,系统将不加载默认拦截器,需要手动配置一次 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/main.jsp</result>
<result name="fail">/login.jsp</result>
</action>
四、Struts2标签:
1、Struts2标签使用在jsp页面中:
<s:property>:和ognl表达式在jsp页面中获取值栈数据
<s:iterator> :获取值栈list集合数据,表示list集合
<s:debug>:查看值栈结构和数据。
2、常用的Html表单标签:
3、在struts2里面对应的html表单标签大部分都有:
<%@ 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>struts常用表单标签</title>
</head>
<body>
<!-- 1.普通输入域 -->
<s:textfield name="username" label="username"></s:textfield><br/>
<!-- 2.密码输入域 -->
<s:password name="password" label="password"></s:password><br/>
<!-- 3.单选框 -->
<!-- value和显示值一样 -->
<s:radio list="{'男','女'}" name="sex" label="性别"></s:radio><br/>
<!-- value和显示值不一样 -->
<s:radio list="#{'nan':'男','nv':'女'}" name="sex1" label="性别"></s:radio>
<!-- 4. 复选框-->
<s:checkboxlist list="{'java','android','jsp','lunix'}" name="hobit" lable="爱好"></s:checkboxlist><br/>
<!-- 5.下拉框 -->
<s:select list="{'初中','高中','大学','博士'}" name="college" label="学历"></s:select><br/>
<!-- 6.文件上传项 -->
<s:file name="file" label="上传文件"></s:file><br/>
<!-- 7.隐藏项 -->
<s:hidden name="hide" value="abcd"></s:hidden><br/>
<!-- 8.文本域 -->
<s:textarea rows="10" cols="10" name="resume" label="简历"></s:textarea><br/>
<!-- 9.提交按钮 -->
<s:submit value="提交"></s:submit><br/>
<!-- 10.重置按钮 -->
<s:submit value="重置"></s:submit><br/>
</body>
</html>
五、Struts2实现文件上传:
之前web阶段实现上传,使用组件FileUpload,使用struts2实现文件上传,struts2对之前的FileUpload进行封装。
1、如何对上传进行封装:
2、使用struts2框架方便实现文件上传:
步骤:
(1)导入所需的jar包:
(2)页面中的配置:
第一个要求:表单提交方式 post;
第二个要求:form标签里面有属性 enctype属性值,修改为 multipart/form-data
第三个要求:在表单里面有文件上传项,有name属性 <input type= “file” name=“”/>
(3)action中的配置:
①在action直接得到上传文件名称和上传文件;
②在action定义成员变量,生成变量set和get方法;
(4)文件上传的逻辑实现:
①在具体的action的方法里面写上传逻辑;
②在服务器里面创建文件;
③把本地文件复制服务器文件里面;
(5)出现的问题:
①如果上传的文件超过2M,出现异常:
②页面中出现提示:没有input结果定义:
(6)解决方法:在struts2.xml文件中配置:
①使用struts2做文件上传大小默认有限制的,默认2M;
②可以设置允许上传文件的大小:
–struts2里面有常量:
③页面中Input处理:
input是struts2里面错误处理机制,如果上传文件超过设置的大小之后,自动返回结果,结果名称是input。
解决:配置input结果,到错误页面。
④当struts2自动返回input结果,出现错误,在配置input的页面中可以查看错误信息。
–在配置的错误页面中,使用struts2标签可以查看到错误的信息。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114719.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...