Struts2学习笔记02 Struts的封装方法、注入方式详解
访问Servlet的API的方式
在使用Struts2的框架过程中,发现Strusts和Servlet的API是解耦合的,在实际开发过程中,会经常使用到Servlet的API,例如登录,将用户信息保存到Session中,有时想页面输出一些内容,用到response对象,涉及Sservet的API的访问
完全解耦合
这种方式只能获取request、session、application的数据的Map集合,无法操作这些对象的本身的方法。
代码:
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login.action" method="post">
用户名:<input type="text" name = "userName"/><br>
密码:<input type="password" name = "password"/><br>
<input type="submit" value="登录">
</form>
</body>
</html>
编写核心过滤器(web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置核心过滤器-->
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Login.Class
package net.zjitc;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
/**
* 完全解耦合的方式访问Servlet的API
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport {
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象。
//利用Strusts中的对象ActionContext对象
ActionContext context = ActionContext.getContext();
//调用AcionContext中的方法
Map<String, Object> map = context.getParameters();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
return NONE;
}
}
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="login" extends="struts-default" namespace="/">
<action name="login" class="net.zjitc.Login">
</action>
</package>
</struts>
向域中的对象保存数据
Action类的编写
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Arrays;
import java.util.Map;
/**
* 完全解耦合的方式访问Servlet的API
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport{
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象的。
//获取ActionContext的实例
ActionContext context = ActionContext.getContext();
//调用AcionContext中的getParameters()方法,类似与request的getParameterMap()方法
Map<String, Object> map = context.getParameters();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
//向域对象保存数据
//相当于request.setArrribute();
context.put("reqName","reqValue");
//相当于session.setArribute();
context.getSession().put("sessName","sessValue");
//相当于Applicateion.setArribute();
context.getApplication().put("appName","appValue");
return SUCCESS;
}
}
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>数据:</h1>
${reqName}
${sessName}
${appName}
</body>
</html>
原生(推荐使用)
这种方式可以获取request、session、application的数据的Map集合,也可以操作这些对象的本身的方法。
Action类的编写
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;
/**
* 原生的方式访问Servlet的API
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport{
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象的。
//通过ServletActionContext获取request对象。
HttpServletRequest request = ServletActionContext.getRequest();
Map<String, String[]> map = request.getParameterMap();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
return NONE;
}
}
向域对象中保存数据
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;
/**
* 原生的方式访问Servlet的API
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport{
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象的。
//通过ServletActionContext获取request对象。
HttpServletRequest request = ServletActionContext.getRequest();
Map<String, String[]> map = request.getParameterMap();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
//向域对象中保存数据
//向request中保存数据
request.setAttribute("reqName","reqValue");
//向Session中保存数据
request.getSession().setAttribute("sessName","sessValue");
//向Application中保存数据
ServletActionContext.getServletContext().setAttribute("appName","appValue");
return SUCCESS;
}
接口注入
Action类的编写
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;
/**
* 接口注入的方式访问Servlet的API,首先要你的Action类实现ServletRequestAware接口
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象的。
//通过ServletActionContext获取request对象。
Map<String, String[]> map = request.getParameterMap();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
return super.execute();
}
@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.request = request;
}
}
向域中对象保存数据
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.util.ServletContextAware;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;
/**
* 接口注入的方式访问Servlet的API,首先要你的Action类实现ServletRequestAware接口
* @version 1.0
* @autho ban
* @date 2019/4/15 12:26
*/
public class Login extends ActionSupport implements ServletRequestAware, ServletContextAware {
private HttpServletRequest request;
private ServletContext context;
@Override
public String execute() throws Exception{
//接收参数,完全解耦合的方式是看不到request对象的。
//通过ServletActionContext获取request对象。
Map<String, String[]> map = request.getParameterMap();
//通过map获取数据
for ( String key : map.keySet()){
String [] values = (String[]) map.get(key);
System.out.println(key + ":" + Arrays.toString(values));
}
//向域对象中保存数据
//向request中保存数据
request.setAttribute("reqName","reqValue");
//向Session中保存数据
request.getSession().setAttribute("sessName","sessValue");
//向Application中保存数据,需要这个类实现ServletContextAware接口
context.setAttribute("appName","appValue");
return super.execute();
}
@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.request = request;
}
@Override
public void setServletContext(ServletContext context) {
this.context = context;
}
}
Servlet是单例的,多个程序访问同一个Servelt只会创建一个Servlet实例。Action是多例的,不存在线程安全问题。
结果页面的配置
全局结果页面
- 什么是全局结果页面
一个包(package)下的所有Action的页面跳转都有效 - 全局结果页面的配置(< global-results>标签)
<?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="login" extends="struts-default" namespace="/">
<global-results>
<result>/hello.jsp</result>
</global-results>
<action name="login" class="net.zjitc.Login"></action>
</package>
</struts>
局部结果页面
- 什么是局部结果页面
只在当前Action中的页面跳转有效 - 局部结果页面的配置(在< action>标签下配置)
<action name="login" class="net.zjitc.Login">
<result>/hello.jsp</result>
</action>
关于result标签
result标签用于配置页面的跳转,
属性名 | 作用 |
---|---|
name | 逻辑视图的名称,默认值为“success" |
type | 页面跳转的类型 |
有哪些页面跳转的类型呢?
你可以在struts的jar包中的根目录下的default.properties文件中找到<package name="struts-default" abstract="true">
下的<result-types>
标签。这个标签定义了页面跳转的类型。
数据封装
User.java
import java.util.Date;
public class User {
private String username;
private String password;
private Date birthday;
private int age;
//创建每个属性的get和set方法
}
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="user" extends="struts-default" namespace="/">
<action name="userAction" class="net.zjitc.action.UserAction"></action>
</package>
</struts>
属性驱动
提供属性set方法
这种方法在修改单个属性数据时可能会使用到,一般情况下不常用。
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${ pageContext.request.contextPath }/userAction.action" method="post">
用户名:<input type="text" name = "username"/><br>
密码:<input type="password" name = "password"/><br>
出生日期:<input type="date" name="birthday"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
userAction.java
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;
public class UserAction extends ActionSupport {
private String username;
private String password;
private Date birthday;
private int age;
@Override
public String execute() throws Exception {
//接收数据
System.out.println(username);
System.out.println(password);
System.out.println(birthday);
System.out.println(age);
//封装数据
return NONE;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void setAge(int age) {
this.age = age;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
页面中提供表达式
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${ pageContext.request.contextPath }/userAction.action" method="post">
用户名:<input type="text" name="user.username"/><br>
密码:<input type="password" name="user.password"/><br>
出生日期:<input type="date" name="user.birthday"><br>
年龄:<input type="text" name="user.age"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
userAction.java
public class UserAction extends ActionSupport {
//提供一个对象,并提供该对象的set和get方法,其中必须要有get方法
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;
}
}
这种封装方法,是由拦截器来完成数据的封装,拦截器需要创建一个对象,通过get方法获得同一个对象,将获得的对象封装到创建的对象中,这也是为什么必须要提供对象的get方法。
这种封装方法,可以同时向多个对象封装数据。
注意:jsp中的<inpu>标签的name的格式是固定的 对象名.属性名 对象名代表的是我们提供的对象,属性名则是对象中存在的属性,这些要一一对应
模型驱动
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${ pageContext.request.contextPath }/userAction.action" method="post">
用户名:<input type="text" name = "username"/><br>
密码:<input type="password" name = "password"/><br>
出生日期:<input type="date" name="birthday"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
UserAction.java
public class UserAction extends ActionSupport implements ModelDriven<User> {
//提供对象
private User user;
//实例化对象
public UserAction() {
user = new User();
}
//模型驱动需要使用的方法
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
这种方法,只要实现一个ModelDriven接口就行可以了,但只能向一个对象封装数据。在实际开发中这种中方式最常用。
复杂数据的封装
封装到List集合中
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/productAction.action" method="post">
物品名称:<input type="text" name="products[0].name">
物品价格:<input type="text" name="products[0].price"><br>
物品名称:<input type="text" name="products[1].name">
物品价格:<input type="text" name="products[1].price"><br>
物品名称:<input type="text" name="products[2].name">
物品价格:<input type="text" name="products[2].price"><br>
物品名称:<input type="text" name="products[3].name">
物品价格:<input type="text" name="products[3].price"><br>
物品名称:<input type="text" name="products[4].name">
物品价格:<input type="text" name="products[4].price"><br>
<input type="submit" value="提交">
</form>
</body>
</htm
<input>的name属性名格式是固定的 List名称[组序号].属性名 "组序号”必须是数字,"List名称"要与Action类中提供的List名一致
<struts>
<package name="product" extends="struts-default" namespace="/">
<action name="productAction" class="action.ProductAction"></action>
</package>
</struts>
Product.java
/**
* 商品实体类
* @version 1.0
* @autho ban
* @date 2019/4/16 9:45
*/
public class Product {
private String name;
private Double price;
public String getName() {return name;}
public void setName(String name) { this.name = name;}
public double getPrice() {return price; }
public void setPrice(double price) {this.price = price;}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
ProductAction.java
import com.opensymphony.xwork2.ActionSupport;
import domain.Product;
import java.util.List;
/**
* 将数据封装到List集合中
* @version 1.0
* @autho ban
* @date 2019/4/16 9:43
*/
public class ProductAction extends ActionSupport {
private List<Product> products;
// 提供集合的set和get方法:
public void setProducts(List<Product> products) {this.products = products;}
public List<Product> getProducts() {return products;}
@Override
public String execute() throws Exception {
if (products.isEmpty()){
System.out.println("Sorry,products list is Null!");
}else {
for (Product product : products) {
System.out.println(product);
}
System.out.println("OK,No error!");
}
return NONE;
}
}
封装到Map集合中
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/productAction.action" method="post">
物品名称:<input type="text" name="map['one'].name">
物品价格:<input type="text" name="map['one'].price"><br>
物品名称:<input type="text" name="map['two'].name">
物品价格:<input type="text" name="map['two'].price"><br>
物品名称:<input type="text" name="map['three'].name">
物品价格:<input type="text" name="map['three'].price"><br>
物品名称:<input type="text" name="map['four'].name">
物品价格:<input type="text" name="map['four'].price"><br>
物品名称:<input type="text" name="map['five'].name">
物品价格:<input type="text" name="map['five'].price"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
ProductAcion.java
import com.opensymphony.xwork2.ActionSupport;
import domain.Product;
import java.util.Map;
/**
* 将数据封装到Map集合中
* @version 1.0
* @autho ban
* @date 2019/4/16 9:43
*/
public class ProductAction extends ActionSupport {
private Map<String,Product> map;
public Map<String, Product> getMap() {return map;}
public void setMap(Map<String, Product> map) {this.map = map;}
@Override
public String execute() throws Exception {
if (map.isEmpty()){
System.out.println("Sorry,map is Null!");
}else {
for (String key : map.keySet()) {
Product product = map.get(key);
System.out.println(key + ":" + product);
}
System.out.println("OK,No error!");
}
return NONE;
}
}
注意:无论是LIst还是Map都需要set和get方法