第一天
Struts2入门:
能够独立搭建struts2的开发环境
能够使用struts2+hibernate实现客户列表的查询
1、三层架构
表现层:接收和处理请求---MVC模型
业务层:处理程序业务需求
持久层:操作数据库
2、MVC模型
M:Model 模型 作用是封装数据的。目前就是实体类作为模型。
V:View 视图 作用是展示数据的。JSP/HTML
C:Controller 控制器 作用是控制程序流转的。Servlet/Filter
3、Servlet和Filter
共同点:
都有3个常用方法:初始化、销毁、核心方法(service,doFilter)
它们的核心方法都有request和response
它们都是单例对象,即一个应用只有一个对象。
区别:
创建时间点不一样:
Servlet:请求第一次到达时(默认情况下)
Filter:应用一加载就创建
Filter不是一个资源,不能通过地址栏访问
Servlet是一个资源,可以通过地址栏访问
Struts2是一种基于MVC模式的轻量级Web框架。Struts2采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开。
1、Struts2环境搭建
- jar包下载地址:
https://struts.apache.org/
- 创建web项目并导jar包:
struts-2.3.24-all\struts-2.3.24\apps\struts2-blank\WEB-INF\lib
-
修改
web.xml
配置文件<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>02.Struts2HelloAction</display-name> <!-- 配置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> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
-
在src下创建
struts.xml
配置文件,导约束:在struts2-core
核心包下找struts-2.3.dtd
在eclipse中配置dtd:
windows->preferences->xml catalog
中add<?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> </struts>
2、Struts2入门案例
-
在
WebContent
下创建index.jsp,success.jsp
index.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>Struts2的入门案例</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/helloAction">访问第一个struts2应用</a>
</body>
</html>
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>执行结果页面</title>
</head>
<body>
执行成功!
</body>
</html>
-
在src中创建
HelloAction.java
package com.zwd.web.action; /** * 我们的第一个动作类 * 动作类: * 它就是一个概念。它就是struts2框架中用于处理请求的类。 * 我们以后处理请求都写动作类。 * @author Administrator * */ public class HelloAction { /** * 我们的第一个动作类方法 * 动作方法:处理请求的方法 * 动作方法有编写规范: * 1、访问修饰符都是public的 * 2、方法的返回值一般都是String(但是可以是void) * 3、方法都没有参数 * * @return */ public String sayHello(){ System.out.println("HelloAction 的 sayHello方法执行了....."); return "success"; } }
-
在
struts.xml
中配置:<?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> <package name="p1" extends="struts-default"> <action name="helloAction" class="com.zwd.web.action.HelloAction" method="sayHello"> <result name="success" type="dispatcher">/success.jsp</result> </action> </package> </struts>
-
部署,浏览。
http://localhost:8080/02.Struts2HelloAction/
-
需要注意的地方:
**1、struts.xml文件的名称以及位置:现目前名称不可变、位置必须在类的根路径下(例如src)。当项目部署在tomcat上之后 struts.xml文件在
WEB-INF\classes
根路径下。 **2、创建
index.jsp,success.jsp
必须在WebContent
下创建或者在下面另外创建文件夹创建,不能创建到WEB-INF
下。
3、Struts2的六个配置文件
default.properties
struts-default.xml
, struts2-core-2.3.24.jar的根目录下。主要配置了一些拦截器struts-plugin.xml
struts.xml
struts.properties
web.xml
4、Struts2的struts.xml文件配置
package标签
<!--开启开发者模式:修改struts2的配置文件不需要重启tomcat服务器 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 设定访问后缀为.do。在default.properties中的配置为action,,。当我们配置为do后将会覆盖先加载-->
<constant name="struts.action.extension" value="do"></constant>
<!-- package标签:
作用:给访问的action进行分包管理。把配置文件按照面向对象的思想来管理。
属性:
name:指定包的名称,必须写,并且必须唯一。
extends:指定当前包的父类。子包自动具备父包所定义的配置。我们的包一般都需要继承 struts-default包。
abstract:把当前包声明为抽象包。抽象包就是用来被继承的。里面定义的一般都是公共的配 置。
只有没有action标签的包,才能定义为抽象包。
namespace:指定当前包的名称空间。它可以让我们的访问URL模块化。当我们指定了该属性,访问URL就变成了:名称空间+/actionName
名称空间的写法:第一个字符必须是'/',后面紧跟的字符必须是一个字母。其余内容可以是字母,也可以是数字。
例如:我们访问客户:
/user/addUser.action
名称空间有默认值:默认值为:""(空字符串)
-->
<package name="p1" extends="struts-default" namespace="n1"></package>
action标签
-
action标签的三种创建方式
<!-- action标签: 作用:建立动作名称,动作类和动作方法的对应关系 属性: name:指定动作名称 class:指定动作类的全限定类名 method:指定动作方法名称 action的三种创建方式: 第一种:无入侵式的 实际开发中不用 例如:HelloAction 第二种:实现Action接口 例如:Hello2Action 默认动作方法:当我们要是执行的是execute方法时,method属性可以不写 第三种:继承ActionSupport 我们使用这个 例如:Hello3Action 默认动作类(在struts-default.xml可查看):在action只写name时,会默认执行ActionSupport的execute方法 例如:hello4 --> <action name="hello" class="com.zwd.web.action.HelloAction" method="sayHello"> <result name="success" type="dispatcher">/success.jsp</result> </action> <!-- 如果不指定method,则默认执行execute方法 --> <action name="hello2" class="com.zwd.web.action.Hello2Action" method="execute"> <result name="success" type="dispatcher">/success.jsp</result> </action> <action name="hello3" class="com.zwd.web.action.Hello3Action" method="execute"> <result name="success" type="dispatcher">/success.jsp</result> </action> <!-- 默认动作类 ActionSupport--> <action name="hello4"> <result name="success" type="dispatcher">/success.jsp</result> </action>
HelloAction.java
package com.zwd.web.action; /** * 我们的第一个动作类 * 动作类: * 它就是一个概念。它就是struts2框架中用于处理请求的类。 * 我们以后处理请求都写动作类。 * @author Administrator * */ public class HelloAction { /** * 我们的第一个动作类方法 * 动作方法:处理请求的方法 * 动作方法有编写规范: * 1、访问修饰符都是public的 * 2、方法的返回值一般都是String(但是可以是void) * 3、方法都没有参数 * * @return */ public String sayHello(){ System.out.println("HelloAction 的 sayHello方法执行了....."); return "success"; } }
Hello2Action.java
package com.zwd.web.action; import com.opensymphony.xwork2.Action; /** * action的第二种创建方式:实现Action接口 * @author Administrator * */ public class Hello2Action implements Action{ @Override public String execute() throws Exception { System.out.println("Helle2Action 的 execute的方法执行了..."); return SUCCESS; } }
Hello3Action.java
package com.zwd.web.action; import com.opensymphony.xwork2.ActionSupport; /** * action的第二种创建方式:实现Action接口 * @author Administrator * */ public class Hello3Action extends ActionSupport{ }
-
action的三种访问方式
-
第一种:全匹配方式
<%--第一种:全匹配配置方式 --%> <a href="${pageContext.request.contextPath}/addUser">添加用户</a> <hr/> <a href="${pageContext.request.contextPath}/updateUser">更新用户</a> <hr/> <a href="${pageContext.request.contextPath}/deleteUser">删除用户</a> <hr/> <a href="${pageContext.request.contextPath}/findUser">查询用户</a>
-
```xml
<action name="addUser" class="com.zwd.web.action.UserAction" method="addUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="updateUser" class="com.zwd.web.action.UserAction" method="updateUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="deleteUser" class="com.zwd.web.action.UserAction" method="deleteUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="findUser" class="com.zwd.web.action.UserAction" method="findUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>-->
```
-
第二种:通配符匹配方式。
<%--第二种:使用通配符方式:高级用法 --%> <a href="${pageContext.request.contextPath}/add_User">添加用户</a> <hr/> <a href="${pageContext.request.contextPath}/update_User">更新用户</a> <hr/> <a href="${pageContext.request.contextPath}/delete_User">删除用户</a> <hr/> <a href="${pageContext.request.contextPath}/find_User">查询用户</a>
<!-- 第二种:使用通配符方式。通配符:*;{1}:表示第一个*--> <!-- 通配符的基本用法 --> <action name="*" class="com.zwd.web.action.UserAction" method="{1}"> <result name="success" type="dispatcher">/success.jsp</result> </action> <!-- 通配符的高级用法 --> <action name="*_*" class="com.zwd.web.action.{2}Action" method="{1}{2}"> <result name="success" type="dispatcher">/success.jsp</result> </action>
-
第三种方式:使用动态方法调用的方式 。
需要将是否开启动态方法调用设置为true
<!-- 开启动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
```jsp
<%--第三种:使用动态方法调用的方式:感叹号后面是要调用的方法 --%>
<a href="${pageContext.request.contextPath}/user!addUser">添加用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!updateUser">更新用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!deleteUser">删除用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!findUser">查询用户</a>
```
```xml
<!--第三种: 使用动态方法调用的方式
需要将是否开启动态方法调用设置为true
struts.enable.DynamicMethodInvocation = true-->
<action name="user" class="com.zwd.web.action.UserAction">
<result name="success" type="dispatcher">/success.jsp</result>
</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的配置文件不需要重启tomcat服务器 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 设定访问后缀为.do。在default.properties中的配置为action,,。当我们配置为do后将会覆盖先加载
<constant name="struts.action.extension" value="do"></constant>-->
<!-- 开启动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<!-- package标签:
作用:给访问的action进行分包管理。把配置文件按照面向对象的思想来管理。
属性:
name:指定包的名称,必须写,并且必须唯一。
extends:指定当前包的父类。子包自动具备父包所定义的配置。我们的包一般都需要继承struts-default包。
abstract:把当前包声明为抽象包。抽象包就是用来被继承的。里面定义的一般都是公共的配置。
只有没有action标签的包,才能定义为抽象包。
namespace:指定当前包的名称空间。它可以让我们的访问URL模块化。当我们指定了该属性,访问URL就变成了:名称空间+/actionName
名称空间的写法:第一个字符必须是'/',后面紧跟的字符必须是一个字母。其余内容可以是字母,也可以是数字。
例如:我们访问客户:
/user/addUser.action
名称空间有默认值:默认值为:""(空字符串)
-->
<package name="p1" extends="struts-default">
<!-- action标签:
作用:建立动作名称,动作类和动作方法的对应关系
属性:
name:指定动作名称
class:指定动作类的全限定类名
method:指定动作方法名称
action的三种创建方式:
第一种:无入侵式的 实际开发中不用
例如:HelloAction
第二种:实现Action接口
例如:Hello2Action
默认动作方法:当我们要是执行的是execute方法时,method属性可以不写
第三种:继承ActionSupport 我们使用这个
例如:Hello3Action
默认动作类(在struts-default.xml可查看):在action只写name时,会默认执行ActionSupport的execute方法
例如:hello4
-->
<action name="hello" class="com.zwd.web.action.HelloAction" method="sayHello">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<!-- 如果不指定method,则默认执行execute方法 -->
<action name="hello2" class="com.zwd.web.action.Hello2Action" method="execute">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="hello3" class="com.zwd.web.action.Hello3Action" method="execute">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<!-- 默认动作类 ActionSupport-->
<action name="hello4">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
</package>
<!-- action的三种访问方式
-->
<package name="user" extends="struts-default">
<!-- 第一种:全匹配配置方式
<action name="addUser" class="com.zwd.web.action.UserAction" method="addUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="updateUser" class="com.zwd.web.action.UserAction" method="updateUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="deleteUser" class="com.zwd.web.action.UserAction" method="deleteUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="findUser" class="com.zwd.web.action.UserAction" method="findUser">
<result name="success" type="dispatcher">/success.jsp</result>
</action>-->
<!-- 第二种:使用通配符方式。通配符:*;{1}:表示第一个*-->
<!-- 通配符的基本用法 -->
<action name="*" class="com.zwd.web.action.UserAction" method="{1}">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<!-- 通配符的高级用法 -->
<action name="*_*" class="com.zwd.web.action.{2}Action" method="{1}{2}">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<!--第三种: 使用动态方法调用的方式
需要将是否开启动态方法调用设置为true
struts.enable.DynamicMethodInvocation = true-->
<action name="user" class="com.zwd.web.action.UserAction">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
</package>
</struts>
<%@ 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>Struts2的入门案例</title>
</head>
<body>
<%--第一种:全匹配配置方式 --%>
<%-- <a href="${pageContext.request.contextPath}/addUser">添加用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/updateUser">更新用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/deleteUser">删除用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/findUser">查询用户</a> --%>
<%--第二种:使用通配符方式:高级用法 --%>
<%-- <a href="${pageContext.request.contextPath}/add_User">添加用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/update_User">更新用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/delete_User">删除用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/find_User">查询用户</a> --%>
<%--第三种:使用动态方法调用的方式 --%>
<a href="${pageContext.request.contextPath}/user!addUser">添加用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!updateUser">更新用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!deleteUser">删除用户</a>
<hr/>
<a href="${pageContext.request.contextPath}/user!findUser">查询用户</a>
</body>
</html>
5、案例:查询客户列表
- 创建数据库,创建数据库表
- 搭建Hibernate的环境:
-
创建web项目,导入hibernate的jar包:
required + jpa-metamodel-generator + c3p0 + 数据库连接驱动
-
在src下创建
hibernate.cfg.xml
文件<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 第一部分:连接的数据库信息 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <!-- 第二部分:可选配置 --> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> <property name="hibernate.current_session_context_class">thread</property> <!-- 第三部分:映射文件 --> <mapping class="com.zwd.domain.Customer"/> </session-factory> </hibernate-configuration>
-
创建hibernate的工具类:
HibernateUtil.java
package com.zwd.utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * hibernate工具类 * @author Administrator * */ public class HibernateUtil { private static SessionFactory factory; static{ Configuration cfg = new Configuration(); cfg.configure(); factory = cfg.buildSessionFactory(); } public static Session getCurrentSession(){ return factory.getCurrentSession(); } }
-
创建dao、service
package com.zwd.dao; import java.util.List; import com.zwd.domain.Customer; /** * 客户的持久层接口 * @author Administrator * */ public interface ICustomerDao { /** * 查询所有客户 * @return */ List<Customer> findAllCustomer(); }
package com.zwd.dao.impl; import java.util.List; import com.zwd.dao.ICustomerDao; import com.zwd.domain.Customer; import com.zwd.utils.HibernateUtil; /** * 客户的持久层实现类 * @author Administrator * */ public class CustomerDaoImpl implements ICustomerDao { @Override public List<Customer> findAllCustomer() { return HibernateUtil.getCurrentSession().createQuery("from Customer").list(); } }
package com.zwd.service; import java.util.List; import com.zwd.domain.Customer; /** * 客户的业务层接口 * @author Administrator * */ public interface ICustomerService { public List<Customer> findAllCustomer(); }
package com.zwd.service.impl; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import com.zwd.dao.ICustomerDao; import com.zwd.dao.impl.CustomerDaoImpl; import com.zwd.domain.Customer; import com.zwd.service.ICustomerService; import com.zwd.utils.HibernateUtil; /** * 客户的业务层实现类 */ public class CustomerServiceImpl implements ICustomerService { private ICustomerDao customerDao = new CustomerDaoImpl(); /** * 获取所有客户 */ @Override public List<Customer> findAllCustomer() { Session s = null; Transaction tx = null; try{ //1、获取session s = HibernateUtil.getCurrentSession(); //2、获取并开启事务 tx = s.beginTransaction(); //3、执行操作 List<Customer> customers = customerDao.findAllCustomer(); //4、提交事务 tx.commit(); //5、返回结果 return customers; }catch(Exception e){ //回滚事务 tx.rollback(); throw new RuntimeException(e); } } }
测试持久层和业务层
package com.zwd.test; import java.util.List; import org.junit.Test; import com.zwd.domain.Customer; import com.zwd.service.ICustomerService; import com.zwd.service.impl.CustomerServiceImpl; /** * 测试客户的业务层和持久层 * @author Administrator * */ public class CustomerDaoTest { @Test public void testFindAllCustomer() { //测试业务层 ICustomerService customerService = new CustomerServiceImpl(); List<Customer> list = customerService.findAllCustomer(); for (Customer customer : list) { System.out.println(customer); } } }
-
创建实体类:
Customer.java
,使用JPA注解package com.zwd.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /******************************************************************************* * javaBeans * cst_customer --> CstCustomer * <table explanation> * @author 2019-08-22 12:31:29 * */ @Entity @Table(name="cst_customer") public class Customer implements java.io.Serializable { @Id @Column(name="cust_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private int custId; @Column(name="cust_address") private String custAddress; @Column(name="cust_indestry") private String custIndestry; @Column(name="cust_level") private String custLevel; @Column(name="cust_name") private String custName; @Column(name="cust_phone") private String custPhone; @Column(name="cust_source") private String custSource; @Column(name="cust_industry") private String custIndustry; public int getCustId() { return custId; } public void setCustId(int custId) { this.custId = custId; } public String getCustAddress() { return custAddress; } public void setCustAddress(String custAddress) { this.custAddress = custAddress; } public String getCustIndestry() { return custIndestry; } public void setCustIndestry(String custIndestry) { this.custIndestry = custIndestry; } public String getCustLevel() { return custLevel; } public void setCustLevel(String custLevel) { this.custLevel = custLevel; } public String getCustName() { return custName; } public void setCustName(String custName) { this.custName = custName; } public String getCustPhone() { return custPhone; } public void setCustPhone(String custPhone) { this.custPhone = custPhone; } public String getCustSource() { return custSource; } public void setCustSource(String custSource) { this.custSource = custSource; } public String getCustIndustry() { return custIndustry; } public void setCustIndustry(String custIndustry) { this.custIndustry = custIndustry; } //override toString Method public String toString() { StringBuffer sb=new StringBuffer(); sb.append("{"); sb.append("'custId':'"+this.getCustId()+"',"); sb.append("'custAddress':'"+this.getCustAddress()+"',"); sb.append("'custIndestry':'"+this.getCustIndestry()+"',"); sb.append("'custLevel':'"+this.getCustLevel()+"',"); sb.append("'custName':'"+this.getCustName()+"',"); sb.append("'custPhone':'"+this.getCustPhone()+"',"); sb.append("'custSource':'"+this.getCustSource()+"',"); sb.append("'custIndustry':'"+this.getCustIndustry()+"'"); sb.append("}"); return sb.toString(); }
3、搭建Struts2环境
-
创建前端页面
-
导包:
struts-2.3.24-all\struts-2.3.24\apps\struts2-blank\WEB-INF\lib
-
配置
web.xml
文件:<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>04.truts2CRM</display-name> <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> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
-
在src下创建
struts.xml
-
创建动作类:
CustomerAction.java
package com.zwd.web.action; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.zwd.domain.Customer; import com.zwd.service.ICustomerService; import com.zwd.service.impl.CustomerServiceImpl; /** * 客户的动作类 * @author Administrator * */ public class CustomerAction extends ActionSupport{ private ICustomerService customerService = new CustomerServiceImpl(); /** * 查询所有客户 * @return */ public String findAllCustomer(){ //1、调用service查询客户 List<Customer> allCustomer = customerService.findAllCustomer(); //2、获取request对象 HttpServletRequest request = ServletActionContext.getRequest(); //3、把查询的结果存入请求域中 request.setAttribute("customers", allCustomer); //4、返回 return SUCCESS; } }
-
配置
struts.xml
第二天
Struts2中的请求参数封装
struts2中使用原始ServletAPI对象的方式
原始ServletAPI对象:HttpServletRequest
HttpServletResponse
HttpSession
ServletContext
Struts2提供的请求参数封装
1、result标签
作用及属性
结果视图分类(全局结果视图/局部结果视图)
2、访问ServletAPI的两种方式(三种?一种?)
ServletAPI:
HttpServletRequest
HttpServletResponse
HttpSession
ServletContext
3、Struts2中的请求参数封装
三种封装方式
属性驱动-没有实体类
属性驱动-有实体
模型驱动
复杂数据类型的封装(集合类型List/Map)
4、案例:使用Struts2实现客户的保存
5、请求参数封装失败后的处理办法
1、result标签详解
result标签:
作用:用于配置结果视图(结果视图可以是一个jsp/html,也可以是一个action)
属性:
name:指定逻辑结果视图。作用就是和动作方法的返回值进行比较,当一致时,前往配置的页面或者action.
type:指定前往结果视图的方式。以何种方式前往。
type取值都是来源于struts-default.xml文件中package名称是struts-default包中定义的类型。
常用的结果类型:
dispatcher:请求转发(默认值)
redirect:重定向 (也可以重定向到动作)
redirectAction:重定向到另外一个动作(会根据我们的配置的后缀添加动作的后缀)
请求转发和重定向的区别:
请求转发: 一次请求 地址栏不变 请求域中数据不丢失 服务器行为 只能是在当前应用中转发
重定向: 两次请求 地址栏改变 请求域中数据丢失 浏览器行为 可以定向到当前应用的外部
响应浏览器的三种方式:
请求转发、重定向、使用流输出(如果只有一种方式,那就是此种方式)-->
<package name="p1" extends="struts-default">
<action name="demo1" class="com.zwd.web.action.demo1Action" method="demo1">
<result name="success" type="redirect">demo2</result>
</action>
<action name="demo2">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
</package>
全局结果视图和局部结果视图
可以定义在action标签之外,使用global-results定义
优先级:先找局部再找全局
<!--让其他包继承该包即可-->
<package name="myDefault" extends="struts-default" abstract="true">
<global-results>
<result name="login" type="dispatcher">/login.jsp</result>
</global-results>
</package>
2、访问ServletAPI的两种方式
-
第一种访问方式:
package com.zwd.web.action; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * 访问ServletAPI: * 第一种方式: * 使用struts2框架提供的一个工具类ServletActionContext,该类中包含了相应的静态方法,可以直接获取 * 工具类是我们实际开发中用的最多的方式 * @author Administrator * */ public class demo1Action extends ActionSupport { HttpServletRequest request ; HttpServletResponse response; HttpSession session; ServletContext application; public String demo1(){ request = ServletActionContext.getRequest(); response = ServletActionContext.getResponse(); session = request.getSession(); application = ServletActionContext.getServletContext(); System.out.println(request); System.out.println(response); System.out.println(session); System.out.println(application); return SUCCESS; } }
-
第二种访问方式:实现相应的接口在
struts-default.xml
对拦截器的配置有<interceptor-ref name="servletConfig"/>
,在执行动作方法会执行这个拦截器。所以set方法会在动作方法之前执行。package com.zwd.web.action; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionSupport; /** * 访问ServletAPI: * 第二种方式: * 通过实现不同的接口,获取不同的对象。 * 要想使用request,需要实现ServletRequestAware * 要想使用response,需要实现ServletResponseAware * 要想使用servletContext,需要实现ServletContextAware * @author Administrator * */ public class demo2Action extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{ HttpServletRequest request ; HttpServletResponse response; HttpSession session; ServletContext application; public String demo1(){ System.out.println(request); System.out.println(response); System.out.println(application); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } @Override public void setServletResponse(HttpServletResponse response) { this.response = response; } @Override public void setServletContext(ServletContext application) { this.application = application; } }
3、Struts2中的请求参数封装
第一种方式:属性驱动,没有实体类
* 请求参数封装
* 第一种方式:属性驱动,没有实体类
* 表单数据的接收都定义在动作类中,所以称为动作类和模型数据写在一起。
* 要想封装成功,需要按照要求书写。
* 要求是:表单元素的name属性取值,必须和动作类中成员get/set方法后面的部分保持一致
* 细节:
* 1、struts2框架会为我们解决post请求中的中文乱码问题,但是get请求不解决。
* 2、struts2框架会自动为我们转换数据类型:
* 基本数据类型自动转换
* 字符串数组会按照 逗号+空格的方式拼接成字符串(吃饭, 睡觉, 写代码)
* 日期类型会按照本地各式转成日期对象。
* 本地格式:yyyy-MM-dd
* 1997/12/04:这种格式会报错
* 执行参数封装,是一个名称为params的拦截器实现的。
* 封装的规则只有一个,它要去指定位置找属性,找到之后调用set方法赋值。
-
表单:
index.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> <%--请求参数封装:第一种情况:属性驱动-没有实体类 --%> <form action="${pageContext.request.contextPath}/demo1.action" method = "post"> 姓名:<input type="text" name="username"/><br/> 年龄:<input type="text" name="age"/><br/> 生日:<input type="text" name="birthday"/><br/> 爱好:<input type="checkbox" name="hobby" value="吃饭"/>吃饭 <input type="checkbox" name="hobby" value="睡觉"/>睡觉 <input type="checkbox" name="hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form> </body> </html>
-
action
package com.zwd.web.action; import java.util.Date; import com.opensymphony.xwork2.ActionSupport; /** * 请求参数封装 * 第一种方式:属性驱动,没有实体类 * 表单数据的接收都定义在动作类中,所以称为动作类和模型数据写在一起。 * 要想封装成功,需要按照要求书写。 * 要求是:表单元素的name属性取值,必须和动作类中成员get/set方法后面的部分保持一致 * 细节: * 1、struts2框架会为我们解决post请求中的中文乱码问题,但是get请求不解决。 * 2、struts2框架会自动为我们转换数据类型: * 基本数据类型自动转换 * 字符串数组会按照 逗号+空格的方式拼接成字符串(吃饭, 睡觉, 写代码) * 日期类型会按照本地各式转成日期对象。 * 本地格式:yyyy-MM-dd * 1997/12/04:这种格式会报错 * 执行参数封装,是一个名称为params的拦截器实现的。 * 封装的规则只有一个,它要去指定位置找属性,找到之后调用set方法赋值。 * @author Administrator * */ public class demo1Action extends ActionSupport { private String username; private int age; private Date birthday; private String hobby; public String demo1(){ System.out.println(username + "=="+age+"=="+birthday+"=="+hobby); return SUCCESS; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } }
-
struts.xml
配置<?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> <!-- 开启开发者模式 --> <constant name="struts.devMode" value="true"></constant> <!-- <constant name="struts.action.extension" value="do"></constant> --> <package name="p1" extends="struts-default"> <action name="demo1" class="com.zwd.web.action.demo1Action" method="demo1"> <result name="success" type="dispatcher">/success.jsp</result> </action> </package> </struts>
第二种方式:属性驱动,有实体类
* 请求参数封装
* 第二种方式:属性驱动,有实体类
* 表单数据的接收都定义在实体类中,把实体类定义在动作类中。
* 要想封装成功,需要按照要求书写。
* 要求是:
* 此时需要使用OGNL表达式来指定表单元素的name取值
* OGNL表达式全称:Object Granphic Nacigation Language
* 对象 图 导航 语言
* 写法:
* user.username user.age
*
* 执行参数封装,是一个名称为params的拦截器实现的。
* 封装的规则只有一个,它要去指定位置找属性,找到之后调用set方法赋值。
-
创建实体类
User.java
package com.zwd.domain; import java.io.Serializable; import java.util.Date; public class User implements Serializable { private String username; private int age; private Date birthday; private String hobby; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } @Override public String toString() { return "User [username=" + username + ", age=" + age + ", birthday=" + birthday + ", hobby=" + hobby + "]"; } }
-
action
package com.zwd.web.action; import com.opensymphony.xwork2.ActionSupport; import com.zwd.domain.User; /** * 请求参数封装 * 第二种方式:属性驱动,有实体类 * 表单数据的接收都定义在实体类中,把实体类定义在动作类中。 * 要想封装成功,需要按照要求书写。 * 要求是: * 此时需要使用OGNL表达式来指定表单元素的name取值 * OGNL表达式全称:Object Granphic Nacigation Language * 对象 图 导航 语言 * 写法: * user.username user.age * * 执行参数封装,是一个名称为params的拦截器实现的。 * 封装的规则只有一个,它要去指定位置找属性,找到之后调用set方法赋值。 */ public class demo2Action extends ActionSupport{ private User user; public String demo2(){ System.out.println(user); return SUCCESS; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
-
struts.xml配置
<?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> <!-- 开启开发者模式 --> <constant name="struts.devMode" value="true"></constant> <!-- <constant name="struts.action.extension" value="do"></constant> --> <package name="p1" extends="struts-default"> <action name="demo1" class="com.zwd.web.action.demo1Action" method="demo1"> <result name="success" type="dispatcher">/success.jsp</result> </action> <action name="demo2" class="com.zwd.web.action.demo2Action" method="demo2"> <result name="success" type="dispatcher">/success.jsp</result> </action> </package> </struts>
-
表单:
index.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> <%--请求参数封装:第一种情况:属性驱动-没有实体类 --%> <form action="${pageContext.request.contextPath}/demo1.action" method = "post"> 姓名:<input type="text" name="username"/><br/> 年龄:<input type="text" name="age"/><br/> 生日:<input type="text" name="birthday"/><br/> 爱好:<input type="checkbox" name="hobby" value="吃饭"/>吃饭 <input type="checkbox" name="hobby" value="睡觉"/>睡觉 <input type="checkbox" name="hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form> <%--请求参数封装:第二种情况:属性驱动-有实体类 --%> <form action="${pageContext.request.contextPath}/demo2.action" method = "post"> 姓名:<input type="text" name="user.username"/><br/> 年龄:<input type="text" name="user.age"/><br/> 生日:<input type="text" name="user.birthday"/><br/> 爱好:<input type="checkbox" name="user.hobby" value="吃饭"/>吃饭 <input type="checkbox" name="user.hobby" value="睡觉"/>睡觉 <input type="checkbox" name="user.hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form> </body> </html>
第三种方式:模型驱动
* 请求参数封装
* 第三种方式:模型驱动
* 要想封装成功,需要按照要求书写。
* 要求是:
* 1、动作类必须实现ModelDriven接口
* 2、动作类中需要定义模型,并且必须实例化出来
* 3、提供接口抽象方法的实现,返回值必须是模型对象
* 执行参数封装,是一个名称为params的拦截器实现的。
* 模型驱动的实现,除了params拦截器之外,还需要一个叫modelDriven的拦截器配合。
-
action
package com.zwd.web.action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import com.zwd.domain.User; /** * 请求参数封装 * 第三种方式:模型驱动 * 要想封装成功,需要按照要求书写。 * 要求是: * 1、动作类必须实现ModelDriven接口 * 2、动作类中需要定义模型,并且必须实例化出来 * 3、提供接口抽象方法的实现,返回值必须是模型对象 * 执行参数封装,是一个名称为params的拦截器实现的。 * 模型驱动的实现,除了params拦截器之外,还需要一个叫modelDriven的拦截器配合。 */ public class demo3Action extends ActionSupport implements ModelDriven<User>{ private User user = new User(); public String demo3(){ System.out.println(user); return SUCCESS; } @Override public User getModel() { return user; } }
-
struts.xml
配置<action name="demo3" class="com.zwd.web.action.demo3Action" method="demo3"> <result name="success" type="dispatcher">/success.jsp</result> </action>
-
表单
<%--请求参数封装:第三种情况:模型驱动 --%> <form action="${pageContext.request.contextPath}/demo3.action" method = "post"> 姓名:<input type="text" name="username"/><br/> 年龄:<input type="text" name="age"/><br/> 生日:<input type="text" name="birthday"/><br/> 爱好:<input type="checkbox" name="hobby" value="吃饭"/>吃饭 <input type="checkbox" name="hobby" value="睡觉"/>睡觉 <input type="checkbox" name="hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form>
复杂类型的封装
List集合的封装
-
action:
package com.zwd.web.action; import java.util.List; import com.opensymphony.xwork2.ActionSupport; import com.zwd.domain.User; /** * 请求参数封装 * 复杂类型的封装:List集合 */ public class demo4Action extends ActionSupport{ private List<User> users; public String demo4(){ System.out.println(users); return SUCCESS; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } }
-
struts.xml
文件配置<action name="demo4" class="com.zwd.web.action.demo4Action" method="demo4"> <result name="success" type="dispatcher">/success.jsp</result> </action>
-
index.jsp
<%--复杂类型的封装:List集合 --%> <form action="${pageContext.request.contextPath}/demo4.action" method = "post"> 姓名:<input type="text" name="users[0].username"/><br/> 年龄:<input type="text" name="users[0].age"/><br/> 生日:<input type="text" name="users[0].birthday"/><br/> 爱好:<input type="checkbox" name="users[0].hobby" value="吃饭"/>吃饭 <input type="checkbox" name="users[0].hobby" value="睡觉"/>睡觉 <input type="checkbox" name="users[0].hobby" value="写代码"/>写代码 <br/> 姓名:<input type="text" name="users[1].username"/><br/> 年龄:<input type="text" name="users[1].age"/><br/> 生日:<input type="text" name="users[1].birthday"/><br/> 爱好:<input type="checkbox" name="users[1].hobby" value="吃饭"/>吃饭 <input type="checkbox" name="users[1].hobby" value="睡觉"/>睡觉 <input type="checkbox" name="users[1].hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form>
map集合封装
-
action
package com.zwd.web.action; import java.util.List; import java.util.Map; import com.opensymphony.xwork2.ActionSupport; import com.zwd.domain.User; /** * 请求参数封装 * 复杂类型的封装:List集合 */ public class demo5Action extends ActionSupport{ private Map<String,User> users; public String demo5(){ System.out.println(users); return SUCCESS; } public Map<String,User> getUsers() { return users; } public void setUsers(Map<String,User> users) { this.users = users; } }
-
struts.xml
<action name="demo5" class="com.zwd.web.action.demo5Action" method="demo5"> <result name="success" type="dispatcher">/success.jsp</result> </action>
-
index.jsp
<%--复杂类型的封装:Map集合 --%> <form action="${pageContext.request.contextPath}/demo5.action" method = "post"> 姓名:<input type="text" name="users['key1'].username"/><br/> 年龄:<input type="text" name="users['key1'].age"/><br/> 生日:<input type="text" name="users['key1'].birthday"/><br/> 爱好:<input type="checkbox" name="users['key1'].hobby" value="吃饭"/>吃饭 <input type="checkbox" name="users['key1'].hobby" value="睡觉"/>睡觉 <input type="checkbox" name="users['key1'].hobby" value="写代码"/>写代码 <br/> 姓名:<input type="text" name="users['key2'].username"/><br/> 年龄:<input type="text" name="users['key2'].age"/><br/> 生日:<input type="text" name="users['key2'].birthday"/><br/> 爱好:<input type="checkbox" name="users['key2'].hobby" value="吃饭"/>吃饭 <input type="checkbox" name="users['key2'].hobby" value="睡觉"/>睡觉 <input type="checkbox" name="users['key2'].hobby" value="写代码"/>写代码 <br/> <input type="submit" value="提交"/> </form>
有问题的表单数据的回显:
1、配置结果视图 input
<action name="demo1" class="com.zwd.web.action.demo1Action" method="demo1">
<result name="success" type="dispatcher">/success.jsp</result>
<!-- 输入格式错误,从哪来回哪去 -->
<result name="input">/user.jsp</result>
</action>
2、提示错误信息
3、把提交的错误信息回显回来
<%--导入struts2的标签库 --%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%-- 在html中使用s:fielderror标签来提示错误字段 --%>
<form action="${pageContext.request.contextPath}/demo1.action" method = "post">
姓名:<input type="text" name="username"/> <s:fielderror fieldName="username"></s:fielderror><br/>
年龄:<input type="text" name="age"/><s:fielderror fieldName="age"></s:fielderror><br/>
生日:<input type="text" name="birthday"/><s:fielderror fieldName="birthday"></s:fielderror><br/>
爱好:<input type="checkbox" name="hobby" value="吃饭"/>吃饭
<input type="checkbox" name="hobby" value="睡觉"/>睡觉
<input type="checkbox" name="hobby" value="写代码"/>写代码
<s:fielderror fieldName="hobby"></s:fielderror><br/>
<input type="submit" value="提交"/>
</form>
<%-- 直接使用struts2的form标签 --%>
<s:form action="demo1">
<s:textfield name="username" label="姓名"></s:textfield>
<s:textfield name="age" label="年龄"></s:textfield>
<s:textfield name="birthday" label="生日"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--导入struts2的标签库 --%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>
<%--在html中使用s:fielderror标签来提示错误字段 --%>
<form action="${pageContext.request.contextPath}/demo1.action" method = "post">
姓名:<input type="text" name="username"/> <s:fielderror fieldName="username"></s:fielderror><br/>
年龄:<input type="text" name="age"/><s:fielderror fieldName="age"></s:fielderror><br/>
生日:<input type="text" name="birthday"/><s:fielderror fieldName="birthday"></s:fielderror><br/>
爱好:<input type="checkbox" name="hobby" value="吃饭"/>吃饭
<input type="checkbox" name="hobby" value="睡觉"/>睡觉
<input type="checkbox" name="hobby" value="写代码"/>写代码
<s:fielderror fieldName="hobby"></s:fielderror><br/>
<input type="submit" value="提交"/>
</form>
<%--直接使用struts2的form标签 --%>
<s:form action="demo1">
<s:textfield name="username" label="姓名"></s:textfield>
<s:textfield name="age" label="年龄"></s:textfield>
<s:textfield name="birthday" label="生日"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
第三天
OGNL表达式和OGNL上下文
能够使用OGNL表达式获取数据
能够明白OGNL上下文中封装着什么数据,是什么结构
1、OGNL表达式的简单使用
2、OGNL上下文-ContextMap
3、ActionContext以及它和ContextMap的关系
4、ValueStack对象的使用
5、Struts2中EL表达式的使用
6、案例:使用OGNL表达式获取客户列表展示
1、OGNL表达式的简单使用
OGNL:对象图导航语言
作用:存取java对象的任意属性、调用Java对象的方法,同时能够自动实现必要的类型转换。
使用OGNL表达式获取数据,使我们在开发中经常用的。
使用OGNL表达式实现给对象的赋值,是struts2框架做的。
要想使用OGNL表达式获取数据,此时需要借助struts2的标签库
今天使用s:property标签实现把数据输出到浏览器上
<s:property value=""/>
value属性的取值是一个OGNL表达式
标签会把value属性取值所对应的内容输出到浏览器上
如果没有任何对应内容,则什么都不显示
1、要想使用OGNL表达式获取数据,此时需要借助struts2的标签库
今天使用s:property标签实现把数据输出到浏览器上
<s:property value=""/>
value属性的取值是一个OGNL表达式
标签会把value属性取值所对应的内容输出到浏览器上
如果没有任何对应内容,则什么都不显示
OGNL的最基本用法:<s:property value="OGNLExpression"/><br>
2、OGNL表达式和字符串的转换
表达式转成字符串
%{''} / %{""}
可以把%{}去掉
字符串转成表达式
%{}把字符串套起来
可以把%{}去掉
OGNL转成一个普通的字符串:<s:property value="%{'OGNLExpression1'}"/><br>
OGNL转成一个普通的字符串:<s:property value='%{"OGNLExpression2"}'/><br>
OGNL转成一个普通的字符串:<s:property value="'OGNLExpression3'"/><br>
OGNL转成一个普通的字符串:<s:property value='"OGNLExpression4"'/><br>
字符串转为一个OGNL表达式:<s:property value="%{OGNLExpression}"/>
3、OGNL表达式访问对象的方法
调用字符串长度的方法:<s:property value="'OGNLString'.length()"/><br>
调用字符串转换大写的方法:<s:property value="'OGNLString'.toUpperCase()"/>
<hr/>
4、OGNL表达式访问静态属性
访问静态属性需要按照固定的书写规范来写。
规范是:
@包名.包名...类名@静态属性名称
4、OGNL表达式访问静态方法
访问静态属性需要按照固定的书写规范来写。
规范是:
@包名.包名...类名@静态属性方法
OGNL表达式访问静态属性:<s:property value="@java.lang.Integer@MAX_VALUE"/>
OGNL表达式访问静态方法:<s:property value="@java.lang.Math@random()"/>
5、OGNL表达式操作list,map集合
s:radio标签的list取值就是一个OGNL表达式
{}就表示创建了一个List集合 {'男','女'}
#{}就表示创建了一个Map集合 #{'male':'男','female':'女'}
HTML的单选按钮:<br/>
性别:
<input type="radio" name="gender1" value="男">男
<input type="radio" name="gender1" value="女">女
<br/>
Struts2的单选按钮(List):<br/>
<s:radio list="{'男','女'}" name="gender2" label="性别"></s:radio>
<br/>
Struts2的单选按钮(Map):<br/>
<s:radio list="#{'male':'男','female':'女'}" name="gender3" label="性别"></s:radio>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>OGNL的基本用法</title>
</head>
<body>
<%--1、要想使用OGNL表达式获取数据,此时需要借助struts2的标签库
今天使用s:property标签实现把数据输出到浏览器上
<s:property value=""/>
value属性的取值是一个OGNL表达式
标签会把value属性取值所对应的内容输出到浏览器上
如果没有任何对应内容,则什么都不显示
--%>
OGNL的最基本用法:<s:property value="OGNLExpression"/><br>
<%--2、OGNL表达式和字符串的转换
表达式转成字符串
%{''} / %{""}
可以把%{}去掉
字符串转成表达式
%{}把字符串套起来
--%>
OGNL转成一个普通的字符串:<s:property value="%{'OGNLExpression1'}"/><br>
OGNL转成一个普通的字符串:<s:property value='%{"OGNLExpression2"}'/><br>
OGNL转成一个普通的字符串:<s:property value="'OGNLExpression3'"/><br>
OGNL转成一个普通的字符串:<s:property value='"OGNLExpression4"'/><br>
字符串转为一个OGNL表达式:<s:property value="%{OGNLExpression}"/>
<hr/>
<%--3、OGNL表达式访问对象的方法 --%>
调用字符串长度的方法:<s:property value="'OGNLString'.length()"/><br>
调用字符串转换大写的方法:<s:property value="'OGNLString'.toUpperCase()"/>
<hr/>
<%--4、OGNL表达式访问静态属性
访问静态属性需要按照固定的书写规范来写。
规范是:
@包名.包名...类名@静态属性名称
--%>
OGNL表达式访问静态属性:<s:property value="@java.lang.Integer@MAX_VALUE"/>
<hr/>
<%--4、OGNL表达式访问静态方法
访问静态属性需要按照固定的书写规范来写。
规范是:
@包名.包名...类名@静态属性方法
--%>
OGNL表达式访问静态方法:<s:property value="@java.lang.Math@random()"/>
<hr/>
<%--5、OGNL表达式操作list,map集合
s:radio标签的list取值就是一个OGNL表达式
{}就表示创建了一个List集合 {'男','女'}
#{}就表示创建了一个Map集合 #{'male':'男','female':'女'}
--%>
HTML的单选按钮:<br/>
性别:
<input type="radio" name="gender1" value="男">男
<input type="radio" name="gender1" value="女">女
<br/>
Struts2的单选按钮(List):<br/>
<s:radio list="{'男','女'}" name="gender2" label="性别"></s:radio>
<br/>
Struts2的单选按钮(Map):<br/>
<s:radio list="#{'male':'男','female':'女'}" name="gender3" label="性别"></s:radio>
</body>
</html>
2、OGNL上下文-ContextMap
它是Struts2框架中封装数据最大的容器,封装了我们一次请求可能会用到的所有数据。
它是一个Map结构。Map的key是String类型,Map的vlaue是Object类型。
里面内容包括但不限于如下内容:
|
|--application 它是一个Map,里面存的是应用域中的所有数据
|
|--session 它是一个Map,里面存的是会话域中的所有数据
context map---|
|--request 它是一个Map,里面存的是请求域中的所有数据
|
|--value stack(root) 它是一个对象,List结构
|
|--action (the current action) 它是一个对象,表示的是当前执行的Action对象
|
|--parameters 它是一个Map,里面存的是请求参数。
|
|--attr (searches page, request, session, then application scopes)
| 它是一个Map,里面存的是四大域中的数据,并且查找是按照由小到大的顺序找
3、ActionContext以及它和ContextMap的关系
它是一个工具类,提供了便捷操作ContextMap的方法。
ActionContext的创建时间点:每次请求都会创建新的。放在了Struts2的核心过滤器中的doFilter方法,由于java ee 应用是多线程的,它通过把ActionContext绑定到ThreadLocal上实现了线程同步。
我们通过代码得知,要想获取该对象,需要调用ActionContext的静态方法getContext()从当前线程上获取。
通过ActionContext存入数据
ActionContext context = ActionContext.getContext();//从当前线程上获取
Map<String,Object> applicationMap = context.getApplication();
applicationMap.put("applicationMap", "hello applicationMap");
Map<String, Object> sessionMap = context.getSession();
sessionMap.put("sessionMap","hello sessionMap");
package com.zwd.web.domain;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo1Action extends ActionSupport{
/**
* 1、通过ActionContext往ContextMap中存入数据
* (contextMap,hello ContextMap)
* 2、往应用域中存入数据:两种方式
* (applicationAttr,hello applicationAttr)
* (applicationMap,hello applicationMap)
* 3、往会话域中存入数据:两种方式
* (sessionAttr,hello sessionAttr)
* (sessionMap,hello sessionMap)
* @return
*/
public String demo1(){
//1、获取ActionContext
ActionContext context = ActionContext.getContext();//从当前线程上获取
//2、存入数据
context.put("contextMap", "hello ContextMap");
//3、往应用域中存入数据
//第一种方式:使用原始ServletAPI对象ServletContext
ServletContext application = ServletActionContext.getServletContext();
application.setAttribute("applicationAttr", "hello applicationAttr");
//第二种方式:根据key从ActionContext中获取应用域中的map,往map中存入数据
Map<String,Object> applicationMap = context.getApplication();
applicationMap.put("applicationMap", "hello applicationMap");
//4、往会话域中存入数据
//第一种:使用ServletAPI的HttpSession
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("sessionAttr", "hello sessionAttr");
//第二种:获取key为session的map
Map<String, Object> sessionMap = context.getSession();
sessionMap.put("sessionMap","hello sessionMap");
return SUCCESS;
}
}
demo1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>ActionContext的数据存取</title>
</head>
<body>
<s:debug></s:debug>
</body>
</html>
使用OGNL表达式获取ActionContext中的数据
借助struts2的s:property标签和ognl表达式获取ActionContext存入的数据
我们现在获取的数据,都是在map中
获取Map中的数据,OGNL表达式的写法:
#key
如果还想继续向下获取,使用.key的方式
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>ActionContext的数据存取</title>
</head>
<body>
<%--借助struts2的s:property标签和ognl表达式获取ActionContext存入的数据
我们现在获取的数据,都是在map中
获取Map中的数据,OGNL表达式的写法:
#key
如果还想继续向下获取,使用.key的方式 --%>
<s:property value="#contextMap"/> <br/>
<s:property value="#application.applicationAttr"/> <br/>
<s:property value="#session.sessionMap"/> <br/>
<%--借助struts2的标签来查看ConetxtMap中的所有内容 --%>
<s:debug></s:debug>
</body>
</html>
向值栈中存入数据
要存入的数据对象的类型Student.java
package com.zwd.web.domain;
import java.io.Serializable;
public class Student implements Serializable{
private String name;
private Integer age;
private String sex;
public Student(String name, Integer age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
action
package com.zwd.web.domain;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class Demo2Action extends ActionSupport{
/**
* ValueStack(值栈)的数据存入
* @return
*/
public String demo2(){
//1、获取ActionContext
ActionContext context = ActionContext.getContext();//从当前线程上获取
//2、获取值栈对象
ValueStack valueStack = context.getValueStack();
//3、向值栈中存入数据
Student s = new Student("赵文迪",21,"female");
valueStack.push(s);
return SUCCESS;
}
}
struts.xml
配置
<action name="demo2" class="com.zwd.web.domain.Demo2Action" method="demo2">
<result name="success">/demo2.jsp</result>
</action>
demo2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>ValueStack的数据存取</title>
</head>
<body>
<%--借助struts2的标签来查看ConetxtMap中的所有内容 --%>
<s:debug></s:debug>
</body>
</html>
http://localhost:8080/09.Struts2ContextMap/demo2.action
Property Name显示的是get×××中的后面部分(×××)
获取值栈中的数据
<%--获取值栈的数据也需要借助struts2的标签库
使用s:property获取
OGNL表达式的找法,是从栈顶逐个属性名称开始查找,只要找到之后,就不再继续查找,而是返回结果 --%>
姓名:<s:property value="name"/><br/>
年龄:<s:property value="age"/><br/>
性别:<s:property value="sex"/><br/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>ValueStack的数据存取</title>
</head>
<body>
<%--获取值栈的数据也需要借助struts2的标签库
使用s:property获取
OGNL表达式的找法,是从栈顶逐个属性名称开始查找,只要找到之后,就不再继续查找,而是返回结果 --%>
姓名:<s:property value="name"/><br/>
年龄:<s:property value="age"/><br/>
性别:<s:property value="sex"/><br/>
<%--借助struts2的标签来查看ConetxtMap中的所有内容 --%>
<s:debug></s:debug>
</body>
</html>
各种符号的总结
%:
1、把OGNL表达式转成普通字符串 %{""}
2、把字符串转成OGNL表达式 %{}
#:
1、获取ContextMap中的数据:#key
2、在页面中可以创建Map集合。#{}
$:
1、EL表达式使用
2、可以在struts2的配置中使用OGNL表达式(配置可以使xml文件,也可以是注解)${}
第四天
Struts2中自定义拦截器和基于注解的配置方式
能够编写自定义拦截器
能够使用注解配置Struts