Struts2 快速笔记1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28666193/article/details/85714317

路线:

  1. Struts2的概述、Struts2的入门、Struts2常见的配置、Struts2的Action的编写
  2. Struts2的数据的封装、结果页面配置
  3. Struts2的值栈和OGNL表达式
  4. Struts2的标签库

基础

定义:基于MVC的模式的WEB层框架,Struts2和Struts1的架构完全不同。

常见的Web层框架:Struts2、WebWork、SpringMVC等。

从Servlet到框架的变化:传统的请求处理是对每一个请求进行相应的Servlet的处理,会产生许多的Servlet;WEB层的框架是基于前端控制器模型对请求进行处理的分发(过滤器)来设计的。

img

环境

下载:https://struts.apache.org/ 练习版本:2.3.34

Struts2解压目录

  • apps:Struts提供的应用案例,几个WAR包
  • docs:开发文档,API
  • lib:开发框架的JAR包
  • src:源码

使用:创建WEB项目,引入JAR包,配置

执行过程的顺序:当用户访问某一个Action的时候,先经过核心过滤器,在核心过滤器中执行一组拦截器(这组拦截器实现部分功能),执行目标Action,根据Action的返回值,进行页面跳转。

img

Struts配置文件的加载顺序:

  • init_DefaultProperties() ----加载default.properties

  • init_TraditionalXmlConfigurations(); ----加载struts-default.xml、struts-plugin.xml、struts.xml

  • init_LegacyStrutsProperties(); ----加载struts.properties

  • init_CustomConfigurationProviders(); ----加载配置提供类

  • init_FilterInitParameters() ; // [6] ----加载web.xml中过滤器初始化参数

  • init_AliasStandardObjects() ; // [7] ----加载Bean对象

  • 加载顺序

    • default.properties

    • struts-default.xml

    • struts-plugin.xml

    • struts.xml

    • struts.properties

    • web.xml

    注意:后配置的常量的值会覆盖先配置的常量的值。

配置

  1. Package包,Struts中的包,为了更好地管理

    • name
    • extends:一般继承自struts-default,实现更多功能
    • namespace:命名空间,与action标签中的name共同标记为访问路径,先查找有名称的如“aaa”,再找“/”,最后查找默认的“ ”;
    • abstract:为true即可被继承
  2. action

    • name:访问的名,相当于Servlet的名字,和namespace决定请求访问路径
    • class:对应执行的类
    • method:class类中执行的方法,默认为execute
    • converter:用于设置某些类型转换器
  3. 常量:在Struts2的框架中,提供了非常多的常量:default.properties中。

    • struts.i18n.encoding=UTF-8 ----Struts2中所有的post请求的中文乱码不用处理。

    • struts.action.extension=action, ----Struts2请求的默认的扩展名。默认扩展名是.action或者什么都不写。

    • 在Struts中可以在Struts.xml,Struts.properties,web.xml三个地方修改常量配置。
      1546417771859

  4. action的三种编写方式

    • POJO类:普通的一个Java类,写一个public的execute方法,返回一个string的值
    • 实现Action接口,Action接口提供execute方法和5个返回常量,如SUCCESS/ERROR/LOGIN等
    • 继承ActionSupport类:推荐,同样实现了Action的接口,还实现了一类验证等其他功能的接口
  5. action的三种访问方式

    • 通过method访问

      1546437949481

    • 使用通配符访问

      1546437965281

    • 动态访问

      1546437928235

总结:Struts的执行过程:请求API----核心过滤器(StrutsPrepareAndExecuteFilter)-----执行一组拦截器(完成部分的功能)-----Action-------Result.


Struts2 常见API

Struts2的Servlet的API访问

struts中的action中,没有Servlet的request和response对象,可视作是解耦的。实际开发中,经常使用到Servlet的API,如session,response等对象。

Servlet是单例的,多个程序访问同一个Servlet只会创建一个Servlet的实例。Action是多例的,一次请求,创建一个Action的实例(不会出现线程安全的问题)

三种方式

  1. 完全解耦方式:这种方式只能获得代表request、session、application的数据的Map集合,不能操作这些对象的本身的方法。

    // 获取Servlet的API
        ActionContext actionContext = ActionContext.getContext();
        Map<String, Object> map = actionContext.getParameters(); // 类似于request.getParametersMap(),返回一个map
        for (String key : map.keySet()) {
            String[] values = (String[]) map.get(key);
            System.out.println(key + " ... " + Arrays.toString(values));
        }
        // 二、向域对象中存入数据
        actionContext.put("reqName", "reqValue22");// 相当于request.setAttribute();
        actionContext.getSession().put("sessName", "sessValue22"); // 相当于session.setAttribute();
        actionContext.getApplication().put("appName", "appValue22"); // 相当于application.setAttribute();
    
        return "demo1Success";
    
  2. 原生API:注意:这种方式可以操作域对象的数据,同时也可以获得对象的方法。

    // 获取Servlet的API
        HttpServletRequest request = ServletActionContext.getRequest();
        Map<String, String[]> map = request.getParameterMap(); 
        for (String key : map.keySet()) {
            String[] values = (String[]) map.get(key);
            System.out.println(key + " ... " + Arrays.toString(values));
        }
        // 二、向域对象中存入数据
        request.setAttribute("reqName", "reqValue22");
        request.setAttribute("sessName", "sessValue22"); 
        ServletActionContext.getServletContext().setAttribute("appName", "appValue22"); 
        return "demo1Success";
    
  3. 接口注入方式:

    public class RequestDemo2 extends ActionSupport implements ServletRequestAware, ServletContextAware{
    	private ServletContext context;
    	private HttpServletRequest request;
    	
    	//action是多例的,所以成员变量不会存在线程安全问题
    	@Override	
    	public String execute() {
    		
    		Map<String, String[]> map = request.getParameterMap(); 
    		
    		
    		for (String key : map.keySet()) {
    			String[] values = (String[]) map.get(key);
    			System.out.println(key + " ... " + Arrays.toString(values));
    		}
    		// 二、向域对象中存入数据
    		request.setAttribute("reqName", "reqValue33");
    		request.setAttribute("sessName", "sessValue33"); 
    		context.setAttribute("appName", "appValue332"); 
    		
    		return "demo1Success";
    	}
    
    	@Override
    	public void setServletContext(ServletContext context) {
    		this.context = context;
    	}
    
    	@Override
    	public void setServletRequest(HttpServletRequest request) {
    		this.request = request;
    	}
    	
    }
    

Struts的数据——结果页面的转发

  1. 全局结果页面:对当前包(xml下的package)中的所有action均有效,只要返回相应的result,则可以跳转。

    <!-- 配置Struts2的常量 -->
    <constant name="struts.action.extension" value="action"/>
    <package name="demo1" extends="struts-default" namespace="/">
        <global-results>
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </global-results>
    
        <action name="requestDemo1" class="com.leehao.struts_servlet.demo1.RequestDemo1">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
        <!-- 原生Servlet API -->
        <action name="requestDemo2" class="com.leehao.struts_servlet.demo1.RequestDemo2">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
    
        <!--接口注入 -->
        <action name="requestDemo3" class="com.leehao.struts_servlet.demo1.RequestDemo3">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
    </package>
    
  2. 局部结果页面:只针对当前action生效,相同配置下,局部的先生效

  3. result的属性配置

    • name属性 :逻辑视图的名称。默认值:success
    • type属性 :页面跳转的类型。
      • dispatcher :默认值,请求转发。(Action转发到JSP)
      • redirect :重定向。(Action定向到JSP)
      • chain :转发。(Action转发到Action)
      • redirectAction :重定向。(Action重定向到Action)
      • stream :Struts2中提供文件下载的功能。

Struts2的数据封装

Struts2框架是一个web层框架,web层框架(框架:软件的半成品,完成一部分功能)。Struts2提供了数据封装的功能。

在struts中,请求经过核心过滤器时,需要在初始化时,执行许多默认的初始拦截器来处理数据。其中,就有params/modelDriven/conversionError等,来实现参数的校验,类型转化和封装等功能。

  1. 属性驱动:提供属性set方法的方式(不常用)

    1546499419673

1546499802552

  1. 属性驱动:页面中提供表达式方式。

    public class UserAction2 extends ActionSupport {
    	//一个私有的对象,名字和页面相同,表示直接将数据注入到该对象中
    	//struts生成一个User的对象,封装数据,将值赋给当前action的对象属性中,必须有getUser方法,否则只能生成一个属性的对象。
    	private User user;	
    	public User getUser() {
    		return user;
    	}
    	public void setUser(User user) {
    		this.user = user;
    	}
    	@Override
    	public String execute() throws Exception {		
    		System.out.println(user);		
    		return NONE;
    	}	
    }
    
    --------------------------------jsp-----------------------------------------
    <h3>方式二:属性驱动,通过页面表达式</h3>
    <form action="${pageContext.request.contextPath }/userAction2.action" method="post">
    	姓名:<input name="user.username" type="text"><br/>
    	密码:<input name="user.password" type="password"><br/>
    	生日:<input name="user.birthday" type="text"><br/>
    	年龄:<input name="user.age" type="text"><br/>
    	工资:<input name="user.salary" type="text"><br/>
    	<input type="submit" value="提交"><br/>
    </form>
    
  2. 模型驱动

    模型驱动方式最常用的方式:

    • 缺点:只能同时向一个对象中封装数据。

    • 使用第二种可以向多个对象中同时封装数据

    public class UserAction3 extends ActionSupport implements ModelDriven<User>{	
    	private User user = new User();  //必须手动初始化	
    	//模型驱动的方法
    	@Override
    	public User getModel() {		
    		return user;
    	}
    	@Override
    	public String execute() throws Exception {			
    		System.out.println(user);		
    		return NONE;
    	}	
    }
    ----------------------------jsp------------------------------
    <h3>方式三:模型驱动方法</h3>
    <form action="${pageContext.request.contextPath }/userAction3.action" method="post">
    	姓名:<input name="username" type="text"><br/>
    	密码:<input name="password" type="password"><br/>
    	生日:<input name="birthday" type="text"><br/>
    	年龄:<input name="age" type="text"><br/>
    	工资:<input name="salary" type="text"><br/>
    	<input type="submit" value="提交"><br/>
    </form>
    
  3. Input逻辑视图错误

    INPUT的逻辑视图的配置,Action接口中提供了五个逻辑视图的名称:

    • SUCCESS
    • ERROR
    • LOGIN
    • INPUT :input****在某些拦截器中会使用。
    • NONE

    示例图:![图一 INPUT逻辑视图的配置](assets/图一 INPUT逻辑视图的配置.bmp)

    Struts复杂数据模型的封装

    在实际开发中,有可能遇到批量向数据库中插入记录,需要在页面中将数据封装到集合中。

    1. 向集合List中封装

      public class ProductAction1 extends ActionSupport {	
      	private List<Product> products;
      	//必须设置set,get方法
      	public List<Product> getProducts() {
      		return products;
      	}
      	public void setProducts(List<Product> products) {
      		this.products = products;
      	}
      	@Override
      	public String execute() throws Exception {
      		for (Product product : products) {
      			System.out.println(product);
      		}
      		return NONE;
      	}
      }
      ---------------------jsp------------------------------------------
      <h3>一:List类型数据集合</h3>
      <form action="${pageContext.request.contextPath }/productAction1.action" method="post">
      	名称:<input name="products[0].pname" type="text">
      	价格:<input name="products[0].price" type="text"><br/>
      	名称:<input name="products[1].pname" type="text">
      	价格:<input name="products[1].price" type="text"><br/>
      	名称:<input name="products[2].pname" type="text">
      	价格:<input name="products[2].price" type="text"><br/>
      	<input type="submit" value="提交"><br/>
      </form>
      
    2. 向Map中封装

      public class ProductAction2 extends ActionSupport {	
      	private Map<String, Product> map;
      	//必须设置set,get方法	
      	public Map<String, Product> getMap() {
      		return map;
      	}
      	public void setMap(Map<String, Product> map) {
      		this.map = map;
      	}
      	@Override
      	public String execute() throws Exception {
      		for (Entry<String, Product> entry : map.entrySet()) {
      			System.out.println(entry.getKey() + " " + entry.getValue());
      		}
      		return NONE;
      	}
      }
      -----------------------------JSP------------------------------------------
      <h3>二:MAP类型数据集合</h3>
      <form action="${pageContext.request.contextPath }/productAction2.action" method="post">
      	名称:<input name="map['one'].pname" type="text">
      	价格:<input name="map['one'].price" type="text"><br/>
      	名称:<input name="map['two'].pname" type="text">
      	价格:<input name="map['two'].price" type="text"><br/>
      	名称:<input name="map['three'].pname" type="text">
      	价格:<input name="map['three'].price" type="text"><br/>
      	<input type="submit" value="提交"><br/>
      </form>
      

猜你喜欢

转载自blog.csdn.net/qq_28666193/article/details/85714317