eclipse学习(第二章:初识ssh)——17.Struts2注释(包含struts的大部分注释说明以及注解的扫描规则)

前言

本文是参考自以下的网站后自己实践后写的一些笔记
https://www.w3cschool.cn/struts_2/struts_annotations.html

使用到的注解说明

@ParentPackage,这个注解对应了xml文件中的package节点,它只有一个属性叫value,其实就是package的name属性;
@Namespace,命名空间,也就是xml文件中<package>的namespace属性;
@Action,这个注解对应<action>节点。这个注解可以应用于action类上,也可以应用于方法上。这个注解中有几个属性:
	value(),表示action的URL,也就是<action>节点中的name属性;
	results(),表示action的多个result;这个属性是一个数组属性,因此可以定义多个Result;
	interceptorRefs(),表示action的多个拦截器。这个属性也是一个数组属性,因此可以定义多个拦截器;
	params(),这是一个String类型的数组,它按照name/value的形式组织,是传给action的参数;
	exceptionMappings(),这是异常属性,它是一个ExceptionMapping的数组属性,表示action的异常,在使用时必须引用相应的拦截器;
	
@Result,这个注解对应了<result>节点。这个注解只能应用于action类上。这个注解中也有几个属性:
	name(),表示action方法的返回值,也就是<result>节点的name属性,默认情况下是【success】;
	location(),表示view层文件的位置,可以是相对路径,也可以是绝对路径;
	type(),是action的类型,比如redirect;
		dispatcher:它代表的是请求转发,也是默认值。它一般用于从action跳转到页面。
		chain:它也相当于请求转发。它一般情况下用于从一个action跳转到另一个action。
		redirect:它代表的是重定向  它一般用于从action跳转到页面
		redirectAction: 它代表的是重定向  它一般用于从action跳转另一个action。
		stream:代表的是服务器端返回的是一个流,一般用于下载。
		freemarker(了解即可): 一种模板技术,通过以流向模板页面输入数据,而得到我们想要的页面

	params(),是一个String数组。也是以name/value形式传送给result的参数;

项目搭建

1、初始化项目及jar包拉取

使用注解开发需要使用到的相关jar包,其中最重要的是struts2-convention-plugin,这个是使用注解的最重要的包

在这里插入图片描述

2、修改web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ssh_learn_annotation</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  	<init-param>
  		<param-name>struts.devMode</param-name>
  		<param-value>true</param-value>
  	</init-param>
  </filter>
  
  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

3、创建PlayAction

该文件必须放在指定文件夹内,详细可以去看下面那个中途出现的异常。

package com.czx.annotation.action;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator;
import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;

@ParentPackage(value = "struts-default")
//命名空间,也可说是在访问路径中加入的内容
@Namespace(value = "/user")
//全局定义action
//@Actions({
//	@Action(value = "actionA",results = {
//			@Result(name = "success",location = "/success.jsp"),
//			@Result(name = "error",location = "/error.jsp")
//	}),
//	@Action(value="actionB",results = {
//			@Result(name = "success",location = "/success.jsp"),
//			@Result(name = "error",location = "/error.jsp")
//	})
//})
//全局定义result
//@Results({
//	@Result(name = "success",location = "/success.jsp"),
//	@Result(name = "input",location = "/index.jsp")
//})
public class PlayAction extends ActionSupport {
	
	public String getName() {
		return name;
	}

	@RequiredStringValidator(message = "名称不能为空")
	public void setName(String name) {
		this.name = name;
	}

	@RequiredFieldValidator(message = "年龄不能为空")
	@IntRangeFieldValidator(message = "年龄必须在18-60岁之间",max = "60",min = "18")
	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	private String name;
	private Integer age;

	@Action(//访问路径
			value="actionA",
			//返回结果集处理器
			results = {
					@Result(name = "success",location = "/success.jsp",type = "dispatcher"),
					@Result(name = "input",location = "/index.jsp",type = "dispatcher")
					},
			//拦截器
			interceptorRefs = {
					@InterceptorRef(value = "defaultStack"),
//					@InterceptorRef(value = "params"),
//					@InterceptorRef(value = "validation"),
					@InterceptorRef(value = "timer")
					},
			//出现异常怎么处理
			exceptionMappings = {
					@ExceptionMapping(exception = "java.null.Exception",result = "error.jsp"),
					@ExceptionMapping(exception = " java.lang.ArrayIndexOutOfBoundsException",result = "error.jsp")
					}
			)
	public String login() {
		System.out.println(name+":"+age);
		return "success";
	}
	
}

4、创建前端页面

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<s:form action="actionA" method="post" namespace="/user">
		<s:textfield name="name" label="名称" size="20"></s:textfield>
		<s:textfield name="age" label="年龄" size="20"></s:textfield>
		<s:submit value="提交" align="center"></s:submit>
	</s:form>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	成功返回获得的内容
</body>
</html>

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	获取内容失败
</body>
</html>

5、测试

访问http://localhost:8080/ssh_learn_annotation/
在这里插入图片描述
直接点击提交是这样的
在这里插入图片描述
输入名称且年龄在18-60之间再点击提交,就访问成功了
在这里插入图片描述

关于注解位置的部分说明

action可以在类上面写也可以在方法上面写,如果在一个类中,类上面写了,方法也写了。action名称一致但是目的地不一致,这个时候跳转的会选择类上面的那个。
action里面可以写result,如果result写在类上面,方法上面有action且action内部带有result,以方法上面那个action为准。
如果在类上面定义了result和action且action内有定义result,那么以action内的为准。
经过这个测试,可以得知同样的内容,以类上面的为优先。如果是action里面的内容的话,不管它位置以action的为准。

中途遇到的异常

1、HTTP Status 404 - There is no Action mapped for namespace [/] and action name [loginValidator] associated with context path [/ssh_learn_annotation].

这里很麻烦,因为我看是可以不写struts.xml内部的action来实现注解开发的,struts.xml一般是配置struts环境配置。但是这个问题似乎又跟不写struts.xml有关,所以很麻烦。这个问题的意思是找不到对应的action。
所以说这里需要进行包扫描,那么框架本身应该是存在默认的规则的,你找到了规则那么就能解决这个问题。当然你也可以自己写struts.xml自己定义位置。我这里是通过将目标action类移至action文件夹下解决的。

规则如下

1、Struts 2 Annotation概念
Struts 2注解是由Struts 2 convention plugin所支持的。因此,我们必须理解“扫描方式”和“命名转换”机制背后的东西。

1.1 Struts 2对注解的扫描顺序
Struts 2 只扫描名为struts、struts2、action或actions的特定目录。 扫描的工作顺序如下:

  • 先扫描位于名为“struts、struts2、action或actions”的包中的注解类;
  • 接下来,扫描匹配如下条件的文件:
    • 实现com.opensymphony.xwork2.Action接口;
    • 继承自com.opensymphony.xwork2.ActionSupport类;
    • 文件名以Action结尾(比如UserAction、LoginAction)

1.2 命名转换
Struts 2 convention插件将所有的注解action文件名称转换为特定的格式。 例如:LoginAction.java

  • 首先,移除文件名末尾的”Action”单词,如果存在的话;
  • 接下来,将文件名的第一个字母转换为小写。
    这样,在移除末尾的action和转换第一个字母的大小写以后,LoginAction.action将转变为login.action。(不完全是这样,例如BasicTestAction 则使用 basic-test 访问)

Struts 2 convention插件的“扫描算法”和“命名转换”特性带来了很多便利和好处,不过这要求在我们的Struts 2项目中必须正确地遵循命名约定。否则,这将会造成极大的麻烦。

2、No configuration found for the specified action: ‘/user/actionA’ in namespace: ‘’. Form action defaulting to ‘action’ attribute’s literal value.

不应该直接在前端页面的表单中的action内加入namespace的内容,而是要分开两个属性。

<s:form action="/user/actionA" method="post">

变为

<s:form action="actionA" method="post" namespace="/user">

3、拦截器与表单数据校验冲突导致无法进行校验

解决办法:因为自己设置的拦截器并不完全。你可能只是简单地调用了一个timer或者其他的拦截器,但是一般会调用这个defaultStack拦截堆栈。以下是从struts-default.xml文件中选取的截图显示,看看里面包含了什么,里面有一个很关键validation,这个是做数据检验的,开了才行,不开就不行哦
在这里插入图片描述

项目地址

这个仓库里面的ssh_learn_annotation
https://gitee.com/mrchen13427566118/ssh_learn.git

如果不会怎么弄到eclipse的话,就看这里
https://blog.csdn.net/weixin_43987277/article/details/116936221

扩展——更多的注释说明

Namespace注释(Action注释)
@Namespace注释允许在Action类中定义Action的命名空间,而不是基于零配置的约定。

@Namespace("/content")
public class Employee extends ActionSupport{
  ...
}

Result注释(Action注释)
@Result注释允许在Action类中定义Action的结果,而不是XML文件。

@Result(name="success", value="/success.jsp")
public class Employee extends ActionSupport{
 ...
}

Results注释(Action注释)
@Results注释定义了一个Action的一组结果。

@Results({
   @Result(name="success", value="/success.jsp"),
   @Result(name="error", value="/error.jsp")
})
public class Employee extends ActionSupport{
 ...
}

After注释(拦截器注释)
@After注释标记需要在执行主action方法和结果后调用的action方法(忽略返回值)。

public class Employee extends ActionSupport{
   @After
   public void isValid() throws ValidationException {
      // validate model object, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

Before注释(拦截器注释)
@Before注释标记需要在执行主action方法和结果之前调用的action方法(忽略返回值)。

public class Employee extends ActionSupport{
   @Before
   public void isAuthorized() throws AuthenticationException {
      // authorize request, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

BeforeResult注释(拦截器注释)
@BeforeResult注释标记需要在结果之前执行的action方法(忽略返回值)。

public class Employee extends ActionSupport{
   @BeforeResult
   public void isValid() throws ValidationException {
    // validate model object, throw exception if failed
   }

   public String execute() {
      // perform action
      return SUCCESS;
   }
}

ConversionErrorFieldValidator注释(验证注释)
此验证注释检查字段是否存在任何转换错误,并在存在时应用。

public class Employee extends ActionSupport{
   @ConversionErrorFieldValidator(message = "Default message", 
                        key = "i18n.key", shortCircuit = true)
   public String getName() {
       return name;
   }
}

DateRangeFieldValidator注释(验证注释)
此验证注释检查日期字段的值是否在指定范围内。

public class Employee extends ActionSupport{
   @DateRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "2005/01/01", max = "2005/12/31")
   public String getDOB() {
       return dob;
   }
}

DoubleRangeFieldValidator注释(验证注释)
此验证注释检查具有指定范围内值的双字段。如果既不设置min也不设置max,则不会执行任何操作。

public class Employee extends ActionSupport{

   @DoubleRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   minInclusive = "0.123", maxInclusive = "99.987")
   public String getIncome() {
       return income;
   }
}

EmailValidator注释(验证注释)
如果该字段包含非空字符串,则该验证注释将检查该字段是否为有效的电子邮件地址。

public class Employee extends ActionSupport{

   @EmailValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getEmail() {
       return email;
   }
}

ExpressionValidator注释(验证注释)
此非字段级验证器验证所提供的正则表达式。

@ExpressionValidator(message = "Default message", key = "i18n.key", 
shortCircuit = true, expression = "an OGNL expression" )

IntRangeFieldValidator注释(验证注释)
此验证注释检查数字字段是否具有指定范围内的值。如果既不设置min也不设置max,则不会执行任何操作。

public class Employee extends ActionSupport{

   @IntRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "0", max = "42")
   public String getAge() {
       return age;
   }
}

RegexFieldValidator注释(验证注释)
此注释使用正则表达式验证字符串字段。

@RegexFieldValidator( key = "regex.field", expression = "yourregexp")

RequiredFieldValidator注释(验证注释)
此验证注释检查字段是否为非空。注释必须在方法级别应用。

public class Employee extends ActionSupport{

   @RequiredFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getAge() {
       return age;
   }
}

RequiredStringValidator注释(验证注释)
此验证注释检查String字段不为空(即非null,长度大于0)。

public class Employee extends ActionSupport{

   @RequiredStringValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, trim = true)
   public String getName() {
       return name;
   }
}

StringLengthFieldValidator注释(验证注释)
此验证器检查字符串字段是否具有正确的长度,它假定该字段是一个字符串。如果既没有设置minLength也没有设置maxLength,则不会执行任何操作。

public class Employee extends ActionSupport{

   @StringLengthFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   trim = true, minLength = "5",  maxLength = "12")
   public String getName() {
       return name;
   }
}

UrlValidator注释(验证注释)
此验证器检查字段是否是有效的URL。

public class Employee extends ActionSupport{

   @UrlValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getURL() {
       return url;
   }
}

Validations注释(验证注释)
如果要使用多个相同类型的注释,这些注释必须嵌套在@Validations()注释中。

public class Employee extends ActionSupport{

  @Validations(
   requiredFields =
      {@RequiredFieldValidator(type = ValidatorType.SIMPLE, 
      fieldName = "customfield", 
      message = "You must enter a value for field.")},
   requiredStrings =
      {@RequiredStringValidator(type = ValidatorType.SIMPLE, 
      fieldName = "stringisrequired", 
      message = "You must enter a value for string.")}
   )
   public String getName() {
       return name;
   }
}

CustomValidator注释(验证注释)
此注释可用于自定义验证器。使用ValidationParameter注释提供其他参数。

@CustomValidator(type ="customValidatorName", fieldName = "myField")

Conversion注释(类型转换注释)
这是类型级别的类型转换的标记注释。转换注释必须在类型级别应用。

@Conversion()
   public class ConversionAction implements Action {
}

CreateIfNull注释(类型转换注释)
此注释为类型转换设置CreateIfNull。CreateIfNull注释必须在字段或方法级别应用。

@CreateIfNull( value = true )
private List<User> users;

Element注释(类型转换注释)
此注释设置类型转换的元素。Element注释必须在字段或方法级别应用。

@Element( value = com.acme.User )
private List<User> userList;

Key注释(类型转换注释)
此注释设置类型转换的key。Key注释必须在字段或方法级别应用。

@Key( value = java.lang.Long.class )
private Map<Long, User> userMap;

KeyProperty注释(类型转换注释)
此注释设置类型转换的KeyProperty。KeyProperty注释必须在字段或方法级别应用。

@KeyProperty( value = "userName" )
protected List<User> users = null;

TypeConversion注释(类型转换注释)
此注释用于类和应用程序范围的转换规则。TypeConversion注释可以在属性和方法级别应用。

@TypeConversion(rule = ConversionRule.COLLECTION, 
converter = "java.util.String")
public void setUsers( List users ) {
   this.users = users;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值