Action使用Servlet相关API

目录

 

Action使用Servlet相关API

解耦方式调用API(间接调用  了解)

耦合方式直接调用API

接口注入方式操作Servlet API(了解)

方式一  实现接口,访问Action时完成注入

 通过ServletActionContext类的静态方法直接获取Servlet API(推荐)

方式二 使用ServletActionContext

请求参数的接收机制

Struts2的复杂数据的封装

封装到List集合

封装到Map集合

请求参数的类型转换机制(了解)

内置的转换器

编写注册案例(包含文本、数字、日期、数组)


需要分析:为了简化开发,struts2默认情况下讲servlet API(比如:request对象、response对象,session对象、application对象)都隐藏起来了。但是在某些情况下,外面还需要调用servlet API,比如登录的时候将用户信息保存到session域中。

struts2中提供了3种方式来获取servlet的API

  1. 解耦方式获取,借助ActionContext获取,方便单元测试Junit(这个是struts2官方的推荐的方式,但是不利于理解,所以不推荐)
  2. 接口注入方式操作servlet API(了解)
  3. 通过servletActionContext类的静态方法直接获取servlet API(掌握)

get请求的时候,可能会出现中文乱码问题,可通过servers的server.xml中找到如下:

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

并增加  URIEncoding="UTF-8",如下

<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

解耦方式调用API(间接调用  了解)

  • 耦合的概念:

如使用servlet的时候,调用的doget方法和dopost(HttpServletRequest,HttpServletReponse)方法,代码中直接关联request和response对象,这就是耦合。

  • 解耦的概念:

代码中不直接依赖于request对象和response对象。

Struts2设计思想就是与Servlet API解耦合,Action中不再依赖Servlet的API

  • 如何调用这些API?

struts2为我们提供了一个API,可间接调用servlet API,叫做ActionContext类(Action上下文)。可以理解为该类是一个工具类。

  • 该API提供大量间接操作Servlet API方法
  1. getContext()返回ActionContext实例对象
  2. get(key)相当于HttpServletRequest的getAttribute(String name)方法
  3. put(String Object)相当于HttpServletRequest的setAttribute方法
  4. getApplication()返回一个Map对象,存取ServletContext属性
  5. getSession()返回一个Map对象,存取HttpSession属性
  6. getParameters()类似调用HttpServletRequest的getParameterMap()方法
  7. setAttribute(Map)将该Map实例里key-value保存为ServletContext的属性名、属性值
  8. setSession(Map)将该Map实例里key-value保持为HttpSession的属性名、属性值

编写IndirectServletAPIAction.java

public class IndirectServletAPIAction extends ActionSupport{
	public String execute() throws Exception{
		//接收参数
		ActionContext context=ActionContext.getContext();
		Map<String,Parameter> params=context.getParameters();
		Parameter name=params.get("name");
		System.out.println(name);
		return NONE;
	}
}

编写my.jsp

<body>
<h1>
<a href="${pageContext.request.contextPath}/indirect?name=chen">调用API)</a>
</h1>
</body>

配置struts.xml文件

<action name="indirect" class="struts_01.IndirectServletAPIAction" >
		</action>

测试结果

耦合方式直接调用API

接口注入方式操作Servlet API(了解)

方式一  实现接口,访问Action时完成注入

ServletContextAware

  •     void setServletContext(javax.servlet.ServletContext context)

ServletRequestAware

  •    void setServletRequest(javax.servlet.http.HttpServletRequest request)

ServletResponseAware

  •     void setServletResponse(javax.servlet.http.HttpServletResponse response)

ServeltRequestAware--获取到request对象

ServletResponseAware--获取到response对象

ServletContextAware--获取到ServletContext对象

编写InjectServletAPIAction.java

public class InjectServletAPIAction extends ActionSupport implements ServletRequestAware {
	HttpServletRequest request;
	//自动获取request对象
	@Override
	public void setServletRequest(HttpServletRequest arg0) {
		// TODO Auto-generated method stub
		request=arg0;
	}
	public String execute() throws Exception {
		String name=request.getParameter("name");
		System.out.println(name);
		request.setAttribute("msg", name);
		return SUCCESS;
		
	}

}

struts.xml配置增加action

<!-- 耦合方式直接调用  通过实现接口获取request对象 -->
		<action name="inject" class="struts_01.InjectServletAPIAction" >
		<result name="success">/API1.jsp</result>
		</action>

编写API1.jsp

<body>
${msg}
</body>

测试结果

 通过ServletActionContext类的静态方法直接获取Servlet API(推荐)

方式二 使用ServletActionContext

  • static PageContext getPageContext()
  • static HttpServletRequest getRequest()
  • static HttpServletResponse getResponse()
  • static ServletContext getServletContext()

编写DirectServletAPIAction.java

public class DirectServletAPIAction extends ActionSupport {
	public String execute()throws Exception {
		// TODO Auto-generated constructor stub
		HttpServletRequest request=ServletActionContext.getRequest();
		String name=request.getParameter("name");
		System.out.println(name);
		return NONE;
	}
}

struts.xml增加action方法

<!-- 通过ServletActionContext类的静态方法来获取servlet的API -->
		<action name="direct"
			class="struts_01.DirectServletAPIAction">
		</action>

测试结果

请求参数的接收机制

什么是请求参数?

比如登录、注册功能的时候,客户端需要像服务器提交登录或注册信息,这些信息都是请求参数

Servlet接受参数,request.getParameter("XXX");

方式一 属性接受参数(当属性比较少的时候可以用,不用实现接口)

编写LoginAction1.java

public class LoginAction1 extends ActionSupport {
	// 通过struts2框架自动接受参数
	private String username;
	private String pwd;
	// 通过setter方法进行赋值
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	@Override
	public String toString() {
		return "LoginAction1 [username=" + username + ", pwd=" + pwd + "]";
	}

	public String execute() throws Exception {
		System.out.println(toString());
		return NONE;

	}

}

编写login1.jsp

<body>
	<h1>方式一:Action作为表单模型,提供属性和属性对应的getter方法和setter方法</h1>
	<form action="${pageContext.request.contextPath}/login1.action"
		method="post">
		username:<input type="text" name="username"><br>
		password:<input type="password " name="pwd"><br> <input
			type="submit" value="登录">
	</form>
</body>

struts.xml增加action 方法

<action name="login1" class="struts_01.LoginAction1" >
		</action>

测试结果

方式二 使用JavaBean(耦合性较强,不利于开发)

编写UserInfo.java

public class UserInfo {
private String username;
private String pwd;
public UserInfo() {
	System.out.println("UserInfo构造方法");
}
public String getUsername() {
	System.out.println("getUsername");
	return username;
}
public void setUsername(String username) {
	System.out.println("setUsername");
	this.username = username;
}
public String getPwd() {
	System.out.println("getPwd");
	return pwd;
}
public void setPwd(String pwd) {
	System.out.println("setPwd");
	this.pwd = pwd;
}

}

编写LoginAction2.java

public class LoginAction2 extends ActionSupport {
	private UserInfo userInfo;
	
	public UserInfo getUserInfo() {
		System.out.println("getUserInfo");
		return userInfo;
	}

	public void setUserInfo(UserInfo userInfo) {
		System.out.println("setUserInfo");
		this.userInfo = userInfo;
	}

	public String execute()throws Exception {
		System.out.println(userInfo.getUsername()+"--"+userInfo.getPwd());
		return NONE;
		
	}

}

编写login2.jsp

<body>
	<h1>方式二</h1>
	<form action="${pageContext.request.contextPath}/login2.action"
		method="post">
		username:<input type="text" name="userInfo.username"><br>
		password:<input type="password " name="userInfo.pwd"><br> <input
			type="submit" value="登录">
	</form>
</body>

struts.xml增加action

<action name="login2" class="struts_01.LoginAction2" >
		</action>

测试结果

方式三 模型驱动(弥补第二种的缺陷)

使用ModelDriven接口(模型驱动),对请求的数据进行封装

编写UserInfo.java

public class UserInfo {
private String username;
private String pwd;
public UserInfo() {
	System.out.println("UserInfo构造方法");
}
public String getUsername() {
	System.out.println("getUsername");
	return username;
}
public void setUsername(String username) {
	System.out.println("setUsername");
	this.username = username;
}
public String getPwd() {
	System.out.println("getPwd");
	return pwd;
}
public void setPwd(String pwd) {
	System.out.println("setPwd");
	this.pwd = pwd;
}

}

编写LoginAction3.java

public class LoginAction3 extends ActionSupport implements ModelDriven<UserInfo> {
	//必须手动初始化JavaBean对象
	private UserInfo user = new UserInfo();;
//把页面中的数据接受到Javabean中
	@Override
	public UserInfo getModel() {
		// TODO Auto-generated method stub
		System.out.println(user);
		return user;
	}
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(user.getUsername()+"--"+user.getPwd());
		return NONE;
	}
	

}

编写login3.jsp

<body>
	<h1>方式三</h1>
	<form action="${pageContext.request.contextPath}/login3.action"
		method="post">
		username:<input type="text" name="username"><br>
		password:<input type="password " name="pwd"><br> <input
			type="submit" value="登录">
	</form>
</body>

struts.xml增加action

<action name="login3" class="struts_01.LoginAction3" >
		</action>

测试结果

Struts2的复杂数据的封装

封装到List集合

编写product1.jsp

<body>
<form action="${pageContext.request.contextPath}/product1Action.action" method="post">
	商品名称:<input type="text" name="list[0].name"><br>
	商品价格:<input type="text" name="list[0].price"><br>
	商品名称:<input type="text" name="list[1].name"><br>
	商品价格:<input type="text" name="list[1].price"><br>
	商品名称:<input type="text" name="list[2].name"><br>
	商品价格:<input type="text" name="list[2].price"><br>
	<input type="submit" value="批量导入">
</form>
</body>

编写Product.java

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 + "]";
	}
}

编写ProductAction1.java

public class ProductAction1 extends ActionSupport {
	private List<Product> list;

	public List<Product> getList() {
		return list;
	}

	public void setList(List<Product> list) {
		this.list = list;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		for (Product product : list) {
			System.out.println(product);

		}
		return NONE;
	}

}

struts.xml增加action

<action name="product1Action" class="struts_01.ProductAction1" >
		</action>

结果

封装到Map集合

编写product2.jsp

<body>
<form action="${pageContext.request.contextPath}/product2Action.action" method="post">
	商品名称:<input type="text" name="map['one'].name"><br>
	商品价格:<input type="text" name="map['one'].price"><br>
	商品名称:<input type="text" name="map['two'].name"><br>
	商品价格:<input type="text" name="map['two'].price"><br>
	商品名称:<input type="text" name="map['three'].name"><br>
	商品价格:<input type="text" name="map['three'].price"><br>
	<input type="submit" value="批量导入">
</form>
</body>

编写Product.java

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 + "]";
	}
}

编写ProductAction2.java

public class ProductAction2 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 {
		// TODO Auto-generated method stub
		for (String key:map.keySet()) {
			Product product=map.get(key);
			System.out.println(key+"     "+product);
		}
		return NONE;
	}

}

struts.xml增加action

<action name="product2Action" class="struts_01.ProductAction2" >
		</action>

测试结果

请求参数的类型转换机制(了解)

【问题】从上面的例子就可以看出在Action中使用了int类型接收age属性。页面传递过来的肯定是String类型,但是为什么不需要进行类型转换呢?

【原因】Struts2提供了功能强大的类型转换器,用于将请求数据封装到model对象。对于大部分常用类型,开发者根本无需创建自己的转换器。只有当内置的转换类型不够用的时候,可以自定义参数转换器。

内置的转换器

  • boolean --Boolean
  • char--Character
  • int--Integer
  • long--Long
  • float--Float
  • double--Double
  • Date可以接收yyyy-MM-dd格式字符串
  • 数组 可以将多个同名参数,转换到数组中
  • 集合 支持将数据保存到List或者Map集合

编写注册案例(包含文本、数字、日期、数组)

编写regist.jsp

<body>
	<h1>用户注册--内部类型转换器测试</h1>
	<form action="${pageContext.request.contextPath}/regist.action"
		method="post">
		username:<input type="text" name="username"><br> age:<input
			type="text" name="age"><br>
		<h1>日期格式默认使用yyyy-MM-dd</h1>
		birthday:<input type="text" name="birthday"><br> hobby:<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>

编写RegistAction.java

public class RegistAction extends ActionSupport{
	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 "RegistAction [username=" + username + ", age=" + age + ", birthday=" + birthday + ", hobby="
				+ Arrays.toString(hobby) + "]";
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(toString());
		return NONE;
	}

}

struts.xml增加action

<action name="regist" class="struts_01.RegistAction" >
		</action>

测试结果

注意:struts2日期格式默认使用yyyy-MM-dd,如果要使用其他格式,则必须自定义转换器。然后老师并没有说怎么写自定义类型转换器。一般情况下用默认的即可。

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐