Struts2(2)

一、自定义一个结果类型

1.编写一个类,实现com.opensymphony.xwork2.Result接口。


                          例子  :输出验证码在方法中可以通过ServletAPI请求request response完成功能

//自定义的结果视图类型     输出一副验证码图像
public class CaptchaResult implements Result {
	<span style="color:#3366ff;">//图片的宽高  这里给了set方法           在struts.xml配置文件里面就可以注入属性了</span>
	private int width = 80;
	private int height = 25;

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public void execute(ActionInvocation arg0) throws Exception {

		// 自定义结果需要response 这里通过ServletActionContext获取
		HttpServletResponse response = ServletActionContext.getResponse();
		// 产生由4位数字构成的验证码
		int length = 4;
		String valcode = "";
		Random rd = new Random();
		for (int i = 0; i < length; i++)
			valcode += rd.nextInt(10);
		BufferedImage img = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		// 获取一个Graphics
		Graphics g = img.getGraphics();
		// 填充背景色
		g.setColor(Color.WHITE);
		g.fillRect(1000, 1000, width, height);
		// 填充干扰线200
		for (int i = 0; i < 5000; i++) {
			g.setColor(new Color(rd.nextInt(100) + 155, rd.nextInt(100) + 155,
					rd.nextInt(100) + 155));
			g.drawLine(rd.nextInt(width), rd.nextInt(height),
					rd.nextInt(width), rd.nextInt(height));
		}
		// 绘制边框
		g.setColor(Color.GRAY);
		g.drawRect(0, 0, width - 1, height - 1);
		// 绘制验证码
		Font[] fonts = { new Font("隶书", Font.BOLD, 18),
				new Font("楷体", Font.BOLD, 18), new Font("宋体", Font.BOLD, 18),
				new Font("幼圆", Font.BOLD, 18) };
		for (int i = 0; i < length; i++) {
			g.setColor(new Color(rd.nextInt(150), rd.nextInt(150), rd
					.nextInt(150)));
			g.setFont(fonts[rd.nextInt(fonts.length)]);
			g.drawString(valcode.charAt(i) + "", width / valcode.length() * i
					+ 2, 18);
		}
		// 输出图像
		g.dispose();
		ImageIO.write(img, "jpeg", response.getOutputStream());

	}
                2.在struts.xml中声明自定义结果类型

<package name="<span style="color:#3333ff;">mystruts-default</span>" extends="struts-default">
	<!-- 声明结果类型 -->
		<result-types>
			<result-type name="captcha" class="com.test.result.CaptchaResult"></result-type>
		</result-types>
	</package>
                3.使用        如果自定义结果视图大家都要用时 就可以这样  继承的是声明的包  

<package name="p1" extends="<span style="color:#3333ff;">mystruts-default</span>">
	   <action name="captcha">
	    <result name="success" type="captcha">
	   <span style="color:#ff0000;">  <!-- 注入参数  验证动作里面已有宽高的set方法 -- captcharesult.setheight() 这样></span>
	  <span style="color:#3333ff;">  <param name="height">100</param>
	    <param name="width">100</param>	</span>    
	    </result>
	   </action>
	</package>
 

二、Action接收请求参数 

作为MVC框架  必须要负责解析HTTP请求的参数  然后封装到javaBean   Struts2提供了非常强大的类型转换机制用于请求数据到model对象的封装

       (一)封装请求参数有三种方式   常用第二或三种          

     1.方式一、用动作类作为模型对象  直接封装请求的参数     

注:静态参数注入是由一个名字为staticParams拦截器完成的。

a. 首先一个模型    set   get略了   请求来的参数可以在execute里处理  

public class Person extends ActionSupport {
	private String username;
	private String password;
	private String nickname;
	
	public String execute() throws Exception {
		System.out.println("username:"+username+"password:"+password+"nickname:"+nickname);
		return SUCCESS;
	}
}
              b、注入动态(用户输入)参数

                             jsp:

编写原则:表单的输入域的名称和动作类中的属性名(gettersetter)保持一致。

  <form action="${pageContext.request.contextPath}/act1" method="post">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    呢称:<input type="text" name="nickname"/><br/>
    <input type="submit" value="注册">
   </form>
c、注入静态参数   如果用户没有输入呢称的值    就是自己静态注入的游客

 <action name="act1" class="com.test.action.Person"> 
     <span style="color:#3333ff;"> <!-- 这里注入参数  相当于Person.setNickname("游客") --></span>
          <param name="nickname">游客</param>
      </action>

  2、方式二 动作类和模型对象分离

a. Student模型

public class Student extends ActionSupport {
	private String username;
	private String password;
	private String nickname;

   b.动作

public class StudentAction {
	private Student student=new Student();

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}

	public String save() {<span style="color:#3333ff;">
		//在实际操作中这里就可以实现以下功能
		// 把表单数据封装到模型对象中
		// 调用Service把Student的数据保存到数据库中
</span>		System.out.println(student.getUsername() + student.getPassword()
				+ student.getNickname());
		return "none";
	}
}

  c、struts.xml的配置

<action name="act2" class="com.test.action.StudentAction" method="save"></action>
d、jsp 重要的是name名 是模型的属性 相当于 student.setusername

<span style="color:#3333ff;"> </span><form action="${pageContext.request.contextPath}/act2" method="post">
    用户名:<input type="text" name="<span style="color:#ff0000;">student.username</span>"/><br/>
    密码:<input type="text"  name="student.password"/><br/>
    呢称:<input type="text"  name="student.nickname"/><br/>
    <input type="submit" value="注册"/>
    </form>
总结:框架会探测student这个模型是否为空 如果为空 注入他的实例 分别调用对象的属性 注入值 会调用3次getStudent 来分别注入值 


3、(模型和动作分开) 模型驱动 动作类要实现 ModelDriven

a.模型

public class Customer {
	private String username;
	private String password;
	private String nickname;
b、动作类

public class CustmomerAction implements ModelDriven<Customer> {
	private Customer customer = new Customer();// 模型一定要new出来

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public String save() {
		System.out.println(customer);
		return "success";
	}

	// 调用动作方法前,框架会先调用这个方法
	// 这个方法不会实例化customer
	public Customer getModel() {
		return customer;
	}

c、jsp

 <form action="${pageContext.request.contextPath}/act3" method="post">
   用户名:<input type="text" name="username"/><br/>
   密码:<input type="password" name="password"/><br/>
   呢称:<input type="text" name="nickname"/>
   <input type="submit" value="注册"/>

注:实际上是一个名字为modelDriven拦截器完成的。该拦截器会在调用动作方法前,调用getModel(),得到模型对象,他接着把该模型对象压到了值栈的栈顶。表单的username的值,框架就会调用栈顶对象的setUsername方法。

关键点:实现ModelDriven接口;模型对象要自己实例化;


(二)封装集合或者map(实际开发很少用的)

封装list

name的[]就是代表存在一个集合里

封装map


三、类型转换(开发中几乎不用的 struts自带有 需要理解)

两种情况 1.用户输入的都是字符串 2.显示出的都是字符串 

类型转换一般用于 String转换其他类型(用于存储) 其他类型转换String(用于显示)


Struts2类型转换的继承体系


1.自定义类型转换器

a、编写一个类 继承strutsTypeConverter

//自定义类型转换器:
//String--->java.util.Date   MM/dd/yyyy
//java.util.Date----->String	MM/dd/yyyy
public class MyConvertor extends StrutsTypeConverter {

	// 自己定义date格式
	private DateFormat df = new SimpleDateFormat("MM/dd/yyyy");

	// string----------------------->java.util.Date MM/dd/yyyy 字符串转date
	// values:用户输入的值
	// toClass:目标类型
	public Object convertFromString(Map context, String[] values, Class toClass) {
		if (toClass == Date.class) {//判断请求的值是否date
			if (values != null && values.length > 0) {
				String sdate = values[0];
				try {
					return df.parse(sdate);
				} catch (ParseException e) {
					throw new RuntimeException(e);
				}
			}
		}
		return null;
	}

	// java.util.Date--------------->String
	public String convertToString(Map context, Object o) {
		if(o instanceof Date){
			Date d =(Date)o;
			return df.format(d);
		}
		return null;
	}<span style="color:#3333ff;">
</span>

b、注册类型转换器 类型转换器分2种

b1、局部转换器 给某个动作用的

在动作类所在包下 创建一个 动作类名-conversion-properties的配置文件

指定birthday这个属性转换

b2、全局类型转换器:给所有动作用 在构建路径 src目录下建立名称为xwork-conversion.properties的配置文件,按照自己的目标类型进行转换器的配置

2、转换失败的时的回显和错误提示

前提是 动作类需要继承ActionSupport类

出现转换失败时,由一个名字为conversionError拦截器负责处理的。会把错误信息封装起来,并且转向一个叫做input的逻辑视图(用于回显数据)。

更改默认的提示错误

a、在动作类中建立一个 动作类名-properties的配置文件内容如下



四、数据校验(开发经常写)

校验分种 客户端校验:javaScript完成

服务器端校验:代码

实际开发 是2种校验都需要写

前提:动作类需要继承ActionSupport 验证是由Validation(声明式校验)、workflow(错误提示)完成的

a、编程式校验:动作类中写代码

a.1针对动作类中的所有动作方法进行校验 在动作类中,覆盖掉validate方法

a.2针对动作类中的指定方法进行校验 有2种方式

方式一:比较麻烦

方式二:使用注解,简单

b、声明式校验(推荐):写配置文件

把校验规则和消息提示放到配置文件中。

b.1针对动作类所有方法进行校验

在动作列类所在的包中,建立名字为 动作类名-validation.xml配置文件 内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<!--   方式一: 给一个字段指定多个验证器  type是框架提供的验证器
	<field name="name">
		<field-validator type="requiredstring">
	   <message>名字不能为空</message>
		</field-validator>
	</field>
	  --> 
	  <!-- 方式二   验证器验证字段 还可以验证非字段的验证 -->
	  <validator type="requiredstring">
	    <param name="fieldName">age</param>
	    <message>年龄不能为空</message>
	  </validator>
</validators>

b2、针对指定方法进行效验 

方式一 用 @skipValidation 注解 

方式二 比较麻烦

在动作类的包下新建 动作类名-动作别名(就是struts.xml配置文件 Action动作给方法配的name名-validation.xml 写法跟针对所有方法一样

Struts2框架提供的内置验证器 可以参考Struts2解压出来的xwork.jar包下的

xwork-core-2.3.15.3.jar\com\opensymphony\xwork2\validator\validators\default.xml

例子 验证信息记住:不是字段验证 比如 验证2次密码是否一样 这种需要使用 struts标签 的 actionError

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
	<field name="username">
		<field-validator type="requiredstring">
			<message>名字不能为空</message>
		</field-validator>
		<field-validator type="regex">
			<param name="regex">
				<![CDATA[[a-zA-Z]{3,8}]]>
			</param>
			<message>名字必须由3~8位字母组成</message>
		</field-validator>
	</field>
	<field name="password">
		<field-validator type="requiredstring">
			<message>密码不能为空</message>
		</field-validator>
		<field-validator type="strong">
			<message>密码必须由至少一个大写和小写和数字组成</message>
		</field-validator>
	</field>
	<!-- 非字段验证:要使用s:actionError显示错误 -->
	<validator type="expression">
		<param name="expression">
			repassword==password
		</param>
		<message>两次密码必须一致</message>
	</validator>

	<field name="email">
		<field-validator type="email">
			<message>输入正确的邮箱</message>
		</field-validator>
	</field>
	<field name="birthday">
		<field-validator type="date">
			<param name="min">2000-01-01</param>
			<param name="max">2010-12-31</param>
			<message>请输入正确的日期</message>
		</field-validator>
	</field>
	<field name="netaddress">
		<field-validator type="url">
			<message>请输入正确的地址:协议_主机_资源地址</message>
		</field-validator>
	</field>
</validators>

jsp:

<!-- 非字段验证:要使用s:actionError显示错误 -->
     <s:actionerror/>
	<s:form action="act3">
		<s:textfield name="username" label="用户名"></s:textfield>
		<s:textfield name="password" label="密码"></s:textfield>
		<s:textfield name="repassword" label="重复密码"></s:textfield>
		<s:textfield name="email" label="邮箱"></s:textfield>
		<s:textfield name="birthday" label="出生日期(MM/dd/yyyy)"></s:textfield>
		<s:textfield name="netaddress" label="地址"></s:textfield>
		<s:submit value="注册"></s:submit>
	</s:form>

自定义声明式校验

a.编写一个类,继承FieldValidatorSupport 定义一个基于字段的验证器

import org.apache.commons.lang3.StringUtils;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

//验证密码强度
public class StrongPasswordValidator extends FieldValidatorSupport {
	// object:实际上就是动作类
	public void validate(Object object) throws ValidationException {
		String fieldName = getFieldName();// 得到要验证的字段名
		String fieldValue = (String) getFieldValue(fieldName, object);
		if (StringUtils.isNotEmpty(fieldValue)) {
			// 有值时再做强度验证
			if (!isPasswordStrong(fieldValue)) {
				// 不满足条件就添加回显信息
				addFieldError(fieldName, object);
			}
		}
	}

	private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz";
	private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	private static final String GROUP3 = "0123456789";

	protected boolean isPasswordStrong(String password) {
		boolean ok1 = false;// 有一个小写字母就为true
		boolean ok2 = false;// 有一个大写字母就为true
		boolean ok3 = false;// 有一个数字就为true
		int length = password.length();
		for (int i = 0; i < length; i++) {
			if (ok1 && ok2 && ok3)
				break;
			String character = password.substring(i, i + 1);
			if (GROUP1.contains(character)) {
				ok1 = true;
				continue;
			}
			if (GROUP2.contains(character)) {
				ok2 = true;
				continue;
			}
			if (GROUP3.contains(character)) {
				ok3 = true;
				continue;
			}
		}
		return ok1 && ok2 && ok3;
	}
}
在src下建立一个validation.xml的配置文件 写法 可以参考Struts2解压出来的xwork.jar包下的

xwork-core-2.3.15.3.jar\com\opensymphony\xwork2\validator\validators\default.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator Definition 1.0//EN"
        "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
<validators>
  <validator name="strong" class="com.test.validation.StrongPasswordValidator"></validator>
</validators>
然后就可以直接在验证中使用了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值