框架-Struts2

第一天

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、案例:查询客户列表

  1. 创建数据库,创建数据库表
  2. 搭建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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值