struts2框架(1)---struts2入门

struts2框架

如果你之前在MVC模式的时候一直都是通过servlet,获取和返回数据,那么现在开始学习struts2框架,

Struts是一个实现MVC设计模式的优秀的框架。它的许多优点我就不说了。

我用自己做的一张图说明servlet和struts2的区别。

写一个最基本的开发步骤,完成开发。

(1)创建WEB 工程

(2)导入必要jar包

(3) 编写JSP 页面

(4)编写Action 服务器端处理逻辑

(5)进行框架配置web.xml、struts.xml

(6)运行测试

(1)创建WEB 工程

         这步还是很正常一样,创建一个普通web工程。如图:

(2)导入必要jar包

      首先我要告诉你到哪里去下载这个框架:在apache官网,你百度struts2下载就可以找到了。

Struts运行必要jar包介绍:

开发中为了方便导入,可以使用app/struts2-blank.war 携带jar包

(3) 编写JSP 页面

在webRoot下新建一个Demo文件,网页先访问start.jsp之后通过框架返回到result页面

start.jsp界面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<h1>请求发起的页面</h1>
<!-- 发起一个请求 访问Struts2框架 -->
<!-- Struts2请求 默认是以.action结尾 -->
<a href="${pageContext.request.contextPath }/hello.action">访问Struts2入门程序</a>
</body>
</html>

result.jsp界面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<h1>处理完成的结果页面</h1>
</body>
</html>

(4)编写Action 服务器端处理逻辑

这里就是通过java创建一个类,该类可以说是action最普通的一个类

1 package com.yudian.struts;
2 public class HelloAction {
3 public String execute() throws Exception{ //这里取execute代表默认执行这个方法
4 System.out.println("我是执行的内容...");
5 return "excutesuccess"; //有返回值,我们用来跳转页面
6 }
7 }

(5)进行框架配置web.xml、struts.xml

配置文件才是核心关键,先配置web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app version="2.5"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
7 <display-name></display-name>
8 <!-- 配置Struts2的前端控制器 --><!--filter-class里面很关键,固定 -->
9 <filter>
10 <filter-name>struts2</filter-name>
11 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
12 </filter>
13 <filter-mapping>
14 <filter-name>struts2</filter-name>
15 <url-pattern>/*</url-pattern>
16 </filter-mapping>
17
18
19 <welcome-file-list>
20 <welcome-file>index.jsp</welcome-file>
21 </welcome-file-list>
22 </web-app>

在配置struts.xml,注意了这个是放在src下面而不是包下面

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
4 "http://struts.apache.org/dtds/struts-2.3.dtd">
5
6 <struts>
7 <package name="default" extends="struts-default">
8 <!-- 3.默认Action 和Action的默认处理类 -->
9 <!-- 1.初步认识Struts2 --><!-- 这里hello一定要和jsp中hello。action一致才能找到 -->
10 <action name="hello" class="com.yudian.struts.HelloAction">
11 <result name="excutesuccess">/demo/result.jsp</result>
12 </action> <!-- result代表如果返回值为 excutesuccess则跳转页面-->
13 </package>
14 </struts>

(6)运行测试

先通过浏览器访问start界面:

当点击:访问Struts2入门程序连接直接跳转到了result.jsp

运行结果:

这上面是一个最基本的struts框架的运用,很简单,主要是供大家理解,关于每一个细节我会在接下面慢慢补充.

欢迎大家的留言给出指点意见,谢谢!

Struts2系列笔记(2)---struts.XML

Struts2.xml

本篇博客主要讲struts.xml中package下的标签和标签属性,主要分以下四个部分说明:

(1)action的配置基本属性

(2)同一个Action类中不同方法满足不同的action逻辑

(3)通配符解决多业务问题

(4)配置处理结果:

(1)action的配置基本属性

 1  <!--首先声明本片文章基本还是参考http://www.cnblogs.com/Nouno/p/5683447.html的博客,特此说明-->
2 <?xml version="1.0" encoding="UTF-8"?>
3 <!DOCTYPE struts PUBLIC
4 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
5 "http://struts.apache.org/dtds/struts-2.3.dtd">
6 <struts>
7 <!-- /primer/helloWorldAction.action
8 package:包
9 * name:包名,唯一的,必选项
10 * namespace:命名空间,唯一的,相当于房间号。可选项,省略情况下是"/"。页面中请求连接的前半部分
11 * extends:继承
12 * extends="struts-default":struts2框架底层提供的核心包struts2-core-2.3.3.jar下的struts-default.xml文件
13 * 为什么要继承这个struts-default.xml文件?
14 * 因为struts2框架底层提供的struts-default.xml声明了所有的拦截器和拦截器栈,
15 知道在struts2框架运行时执行struts-default.xml文件中的拦截器栈。
16 * 如果不继承struts-default.xml文件,就没有办法使用struts2框架提供的所有拦截器
17 -->
18 <package name="primer" namespace="/" extends="struts-default">
19
20 <!--
21 如果找不到对应的action名的时候,配置默认要执行的action
22 * name:指定action的名称
23 -->
24 <default-action-ref name="error"></default-action-ref>
25
27 <action name="error" class="com.yyc.struts.action.ErrorAction">
28 <result name="error">/error.jsp</result>
29 </action>
30 <!--
31 action:
32 * name:对应页面中请求连接的后面半部分,这里表示jsp请求链接为hello.action才会和它匹配
33 * class:对应要执行的类的完整路径 ,表示Action类的完整路径,相当于之前的servlet类
34 *method:对应的class类中要执行的方法,默认执行method="execute()"
35 -->
36 <action name="hello" class="cn.yht.primer.HelloWorldAction" method="execute()">
37 <!--
38 result:结果类型 ,可以用来把Action类处理好的数据跳转到某界面
39 * name:对应的是执行的类的方法的返回值
40 public String execute() throws Exception {
41 System.out.println("HelloWorldAction ************* execute()");
42 return "success";
43 }
44 * 默认判断name="success",后半部分的文本内容:要转向到的页面
45 -->
46 <result name="success">/primer/success.jsp</result>
47 </action>
48 <!--
49 没有为action指定class
50 * 在struts2框架底层的struts-default.xml文件中,配置了默认执行的类
51 com.opensymphony.xwork2.ActionSupport
52 public String execute() throws Exception {
53 return SUCCESS;
54 }
55 * 实际上,默认执行的是底层提供的ActionSupport类的execute()方法
56 * result结果类型,默认是根据struts2框架底层提供的ActionSupport类的execute()方法返回值,进行跳转
57 -->
58 <action name="actionNoClass">
59 <result name="success">/primer/success.jsp</result>
60 </action>
61 </package>
62 </struts>

(2)同一个Action类中不同方法满足不同的action逻辑

 1 <!--这个Action中有两个方法
2 public class ProductAction extends ActionSupport {
3 public String add(){
4 System.out.println("添加商品");
5 return NONE;
6 }
7 public String del(){
8 System.out.println("删除商品");
9 return NONE;
10 }
11 }-->
12
13 <!-- 多个业务需求 -->
14 <action name="addBook" class="com.guigu.struts.action.BookAction" method="add"></action>
15 <action name="delBook" class="com.guigu.struts.action.BookAction" method="del"></action>
16 <!--这样确实能够实现一个Action类中的不同方法,都能被调用
17 但是你也许会注意到,每调用一个方法都需要配置action-->

(3)通配符解决多业务问题

 1 <!--这里是jsp文件
2 <h1>客户管理</h1>
3 <a href="${pageContext.request.contextPath }/customer_add">添加客户</a><br/>
4 <a href="${pageContext.request.contextPath }/customer_del">删除客户</a><br/>
5 <a href="${pageContext.request.contextPath }/customer_edit">修改客户</a><br/>
6 <a href="${pageContext.request.contextPath }/customer_find">查询客户</a><br/>
7 -->
8 <!-- 使用通配符解决多业务问题 -->
9 <!-- method 属性{1}是取第一个* ,这样就只需要写一个action就可以了,我们只要在Action类中写好相对应的方法即可-->
10 <action name="customer_*" class="com.guigu.struts.action.CustomerAction" method="{1}">
11 <result >/demo1/{1}.jsp</result>
12 </action>

(4)配置处理结果: 

Struts2的Action处理用户请求结束后,返回一个普通字符串-逻辑视图名,必须在struts.xml文件中完成逻辑视图和物理视图资源的映射,才可让系统转到实际的视图资源。

Struts2通过在struts.xml文件中使用<result …/>元素来配置结果。Struts2提供了两种结果。

a.局部结果:将<result …/>作为<action …>元素的子元素配置。

b.全局结果:将<result …/>作为<global-results …>元素的子元素配置。

在package元素中配置<global-results>子元素:

<!--全局result(global-results)
有很多时候一个<result>可供很多<action>使用,这时可以使用<global-results>标签来定义全局的<result>l。执行顺序:当一个Action返回的String没有相应的<result>与之对应,Struts2就会查找全局的<result>。--> <global-results> <result name="error">/Error.jsp</result>
<result name="invalid.token">/Error.jsp</result>
<result name="login" type="redirect-action">Logon!input</result> </global-results>

欢迎大家留言指点!

Struts2框架(3)---Action类的3种书写方式

Action类的3种书写方式

本文主要写有关写Action类的3种书写方式:

(1)第一种 Action可以是POJO (简单模型对象)  不需要继承任何父类 也不需要实现任何接口

(2)实现Action接口

(3)继承ActionSupport(推荐)

那我们先来书写第一种:

(1)第一种 Action可以是POJO (简单模型对象)  不需要继承任何父类 也不需要实现任何接口

1 //这里其实就是一个普通的类,类里面的方法可以任意写,如果写execute()方法那就代表默认执行它
2 public class RequestAction1 {
3 //提供满足条件的方法 excute方法
4 //public 范围的 带有String返回值的 无参的方法
5 public String execute(){
6 System.out.println("测试方式一");
7 return null;//null表示不进行跳转
8 }
9 }

     (2)实现Action接口

 1 import com.opensymphony.xwork2.Action;
2 public class RequestAction2 implements Action{
3
4 public String execute() throws Exception {
5 System.out.println("方式二 实现Action接口 成功执行....");
6 return SUCCESS;
7 }
8 }
9 /**
10 * Action接口中一共有5个五种逻辑视图 和一个方法分别如些:
11 * public abstract interface com.opensymphony.xwork2.Action {
12 数据处理成功(成功的跳转页面)
13 public static final java.lang.String SUCCESS = "success";
14 页面不进行跳转 return null
15 public static final java.lang.String NONE = "none";
16 数据处理发送错误(错误页面)
17 public static final java.lang.String ERROR = "error";
18 用户处理数据 数据有误 用于表单的校验
19 public static final java.lang.String INPUT = "input";
20 主要是权限认证
21 public static final java.lang.String LOGIN = "login";
22
23 public abstract java.lang.String execute() throws java.lang.Exception;
24 }
25 */

(3)继承ActionSupport(推荐)

 1 import com.opensymphony.xwork2.Action;
2 import com.opensymphony.xwork2.ActionSupport;
3 //为什么推荐ActionSupport,在Action中如果使用基础ActionSupport的方式 可以使用表单的校验 错误信息的设置 和国际化信息 三个重要的功能。
4 public class RequestAction3 extends ActionSupport {
5 @Override
6 public String execute() throws Exception {
7 System.out.println("方式三 继承ActionSupport完成 书写");
8 return super.execute();//返回SUCCESS
9 }
10 }
11 /**ActionSupport类的特点,点进去发现它实现了许多的接口
12 * public class ActionSupport implements Action, Validateable,
13 * ValidationAware, TextProvider, LocaleProvider, Serializable
14 * 这么多接口说明它不简单
15 *
16 */

关于action类的创建我就说这么多!请大家多指点!

Struts2框架(4)---Action类访问servlet

Action类访问servlet

Action类有三种方式servlet:

(1)间接的方式访问Servlet API  ---使用ActionContext对象

(2)  实现接口,访问Action时完成注入

(3)直接通过ServletActionContext获得Servlet的API

下面我来讲第一种:

  (1)间接的方式访问Servlet API  ---使用ActionContext对象

Struts2中提供了一个ActionContext类(当前Action的上下文对象),通过这个类可以访问Servlet API。下面是该类中提供的几个常用方法:

     1.public static ActionContext getContext() :获得当前Action的ActionContext实例。
     2.public Object get(Object key) :此方法类似于调用HttpServletRequest的getAttribute(String name)方法。
     3.public void put(Object key, Object value) :此方法类似于调用HttpServletRequest 的setAttribute(String name, Object o)。 
     4. public Map getParameters() :获取所有的请求参数。类似于调用HttpServletRequest对象的getParameterMap() 方法。  
     5. public Map getSession() :返回一个Map对象,该Map对象模拟了HttpSession实例。 
     6. public void setSession(Map session) : 直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名-属性值对。 
     7. public Map getApplication() :返回一个Map对象,该对象模拟了该应用的ServletContext实例。 

8. public void setApplication(Map application) :直接传入一个Map实例,将该Map实例里

的key-value对转换成application的属性名- 属性值对。

 1 import java.util.Map
2 import com.opensymphony.xwork2.ActionContext;
3 import com.opensymphony.xwork2.ActionSupport;
4 public class LoginAction1 extends ActionSupport{
5
6 public String login() throws Exception{
7 //获取ActionContext
8 ActionContext actionContext =ActionContext.getContext();
9 //1.获取表单的请求参数
10 Map<String, Object> parameters=actionContext.getParameters();
11 //因为用户名username可能有多个,所以返回数组
12 String [] values =(String[]) parameters.get("username");
13 System.out.println("用户名是:"+values[0]);
14
15 //2.存取request 的Attribute
16 actionContext.put("company", "雨点的名字"); //相当于request.setAttribute("","");
17 System.out.println(actionContext.get("company"));
18
19 //3.存取session 的Attribute
20 Map<String, Object> sessionMap=actionContext.getSession();
21 sessionMap.put("age", 11);//相当于session.setAttribute("","");
22 System.out.println(sessionMap.get("age"));
23
24 //4.存取application的Attribute
25 Map<String, Object> applicationMap=actionContext.getApplication();
26 applicationMap.put("info", "下周考试第二阶段");
27 System.out.println(applicationMap.get("info"));
28 return SUCCESS;
29 }
30 }

 (2)  实现接口,访问Action时完成注入

如果是实现结构注入一般需要实现3个接口

(1)ServletContextAware:      实现此接口的Action可直接访问Web应用的ServletContext实例;

(2)ServletRequestAware: 实现此接口的Action可直接访问Web应用的HttpServletRequest实例;

(3)ServletResponseAware:   实现此接口的Action可直接访问Web应用的HttpServletResponset实例

 1 import java.util.Map;
2
3 import javax.servlet.ServletContext;
4 import javax.servlet.ServletResponse;
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7 import org.apache.struts2.interceptor.RequestAware;
8 import org.apache.struts2.interceptor.ServletRequestAware;
9 import org.apache.struts2.interceptor.ServletResponseAware;
10 import org.apache.struts2.util.ServletContextAware;
11
12 import com.opensymphony.xwork2.ActionContext;
13 import com.opensymphony.xwork2.ActionSupport;
14
15 public class LoginAction2 extends ActionSupport implements ServletRequestAware,
16 ServletContextAware,ServletResponseAware {
17
18 private HttpServletRequest request;
19
20 private ServletContext context;
21
22 private HttpServletResponse response;
23
24 public String login() throws Exception{
25 //1.获取表单的请求参数
26 System.out.println(request.getParameter("username"));
27
28 //2.存取request 的Attribute
29 request.setAttribute("company","hzgg" );
30
31 //3.存取session 的Attribute
32 request.getSession().setAttribute("age", 50);
33
34 //4.存取application的Attribute
35 context.setAttribute("info", "今天下午你们可以出去玩");
36
37 return SUCCESS;
38
39 }
40 //实现ServletRequestAware接口必须实现的方法
41 public void setServletRequest(HttpServletRequest request) {
42 this.request=request;
43 }
44 //实现ServletContextAware接口必须实现的方法
45 public void setServletContext(ServletContext context) {
46 this.context=context;
47 }
48 //实现ServletResponseAware接口必须实现的方法
49 public void setServletResponse(HttpServletResponse response) {
50 this.response=response;
51 }
52
53 }

   (3)使用ServletActionContext工具类访问Servlet API

在ServletActionContext工具类中常用的几个方法(都是静态方法):

(1)PageContext getPageContext():          取得应用的PageContext对象;
(2)HttpServletRequest getRequest():       取得该应用的HttpServletRequest对象;
(3)HttpServletRequest getResponse():    取得该应用的HttpServletResponse对象;
(4)ServletContext getServletContext():   取得该应用的ServletContext对象。
 1 import org.apache.struts2.ServletActionContext;
2 import com.opensymphony.xwork2.ActionSupport;
3
4 public class LoginAction3 extends ActionSupport {
5
6 public String login() throws Exception {
7 // 1.获取表单的请求参数
8 String username= ServletActionContext.getRequest().getParameter("username");
9 System.out.println(username);
10
11 // 2.存取request 的Attribute
12 ServletActionContext.getRequest().setAttribute("company", "haha");
13
14 // 3.存取session 的Attribute
15 ServletActionContext.getRequest().getSession().setAttribute("age", 40);
16
17 // 4.存取application的Attribute
18 ServletActionContext.getServletContext().setAttribute("info", "今天下课你们可以约会去了");
19
20 return SUCCESS;
21 }
22 }

下面我来写一个用第三种方法实现访问servlet,从jsp到struts.xml在到Action类,最后从页面显示结果供大家学习:

jsp界面:

start.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<form action="${pageContext.request.contextPath }/hello.action">
姓名:<input type="text">
<input type="submit" value="提交">
</form>
</body>
</html>

struts.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
4 "http://struts.apache.org/dtds/struts-2.3.dtd">
5 <struts>
6 <package name="default" extends="struts-default">
7 <action name="hello" class="com.guigu.struts.action2.LoginAction3" method="login">
8 <result>/result.jsp</result>
9 </action>
10 </package>
11 </struts>
result.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<p>${company}</p>
<p>${age}</p>
<p>${info}</p>
</body>
</html>

  运行结果如下:

当点击提交的时候

发现数据已经从Action类中转发到了界面

这篇文章就讲到这里,欢迎大家指点和点评!

Struts2框架(5)---result结果集

result结果集

上一篇文章主要讲Struts2框架(4)---Action类访问servlet这篇主要讲result结果集

在Struts.xml中的result元素指的是:指定动作类的动作方法执行完后的结果视图.

(1)局部结果和全局结果

他有两个属性:

  name:字符串,与动作方法返回的值一致。默认是success

  type:指定处理结果的结果类型的别名。默认值是dispatcher

首先处理结果分为两种,一种是局部结果一种是全局结果。

局部结果:

 <action name="login" class="com.study.struts.action2.LoginAction" method="login">
<!--在action内配置的是针对某个Action起作用的局部的配置 -->
<result name="success" >/demo2/result.jsp</result>
</action>

全局结果:

 <!--全局结果视图:包中所有的action都能使用同一个视图 -->
<global-results>
<!-- <result name="success">/index.jsp</result> -->
<!-- a.默认的结果集类型 -->
<result name="error" type="dispatcher">/error.jsp</result>
<!-- b.转发到另外一个Action -->
<!-- <result name="success" type="chain">hello</result> -->
<!-- c.重定向到jsp页面 -->
<!-- <result name="success" type="redirect">/index.jsp</result> -->
<!-- d.重定向到action -->
<!-- <result name="success" type="redirectAction">hello</result> -->
</global-results>

这里同时要思考一个问题,如果你返回的是success,但在全局和局部都配置了,那么会执行哪个呢?

按照规则,先看局部变量是否配置,配置了就执行局部变量的,而且一般成功的结果集不会配置成全局的,只有在错误(error)的时候可能配置全局

(2)结果类型

在struts-default.xml 配置常用结果类型有10种:

当然在我们实际开发中运用的比较多的也就4.5种,这里我就写4种

举例:

 1        <action name="main">
2 <result type="dispatcher">/main.jsp</result>
3 </action>
4
5 <action name="main2">
6 <result type="redirect">/main2.jsp</result>
7 </action>
8
9 <action name="main3">
10 <result type="chain">main3</result>
11 </action>
12
13 <action name="main4">
14 <result type="redirectAction">main4</result>
15 </action>

a)  dispatcher(默认)    forward到一个JSP或者HTML或者其他结果页面,不能是Action

请求转发,底层调用RequestDispatcher的forward() 方法,dispatcher是result的type属性默认值,通常用于转向一个JSP。

b)  redirect                    重定向到结果视图   重定向到一个URL

重定向,新页面无法显示Action中的数据,因为底层调用  response.sendRedirect("")方法,无法共享请求范围内的数据。

c)   chain                      服务器forward(转发)到一个另一个Action

将action的带着原来的状态请求转发到新的action,两个action共享一个ActionContext,actionName指定转向的新的Action的名字,method指定转向哪个方法,

namespace指定新的Action的名称空间,不写表示与原Action在相同的名称空间;

d) redirectAction          重定向到另外一个Action

重定向到另一个Action,参数与chain用法相同,允许将原Action中的属性指定新名称带入新Action中,可以在Result标签中添加 <param name=”b”>${a} </param>,

这表示原Action中的变量a的值被转给b,下一个Action可以在值栈中使用b来操作

(3)重定向和转发的区别?

1 请求转发只能将请求转发给同一个WEB应用中的组件,而重定向还可以重新定向到同一站点不同应用程序中的资源,甚至可以定向到一绝对的URL。

2 重定向可以看见目标页面的URL,转发只能看见第一次访问的页面URL,以后的工作都是有服务器来做的。

3 请求响应调用者和被调用者之间共享相同的request对象和response对象,重定向调用者和被调用者属于两个独立访问请求和响应过程。

4 重定向跳转后必须加上return,要不然页面虽然跳转了,但是还会执行跳转后面的语句,转发是执行了跳转页面,下面的代码就不会在执行了。

 (4)结果类型中redirect和redirectAction
  首先要知道:
  只要是重定向,那么之前凡是保存在request里面的东西就全都消失了
  因为重定向实际是发送第二个请求,故请求中的东西也就不会出现在第二个请求里面了
  也就是说重定向是不共享request的东西,重定向后的页面中无法接收request里的东西
  区别:

  redirect是在处理完当前Action之后,重定向到另外一个实际的物理资源
  redirectAction也是重定向,但它重定向到的是另外一个Action

 (5)思考,在我们实际开发中是么时候使用重定向什么时候转发?

我个人观点:就是你在request作用域进行相关操作后,需要从数据库返回进行回显的话,比如说你在点击修改的时候就需要把信息回显,这就建议转发,因为用重定向是无法得到回显数据

还有你要跳转到外部网站,比如www.baidu.com,那你就不能用转发,就指定用重定向,这个上面第一点就说了。

本文章就讲到到这里,如果哪里有不足,或者可以修改的更好,欢迎留言指出。

Struts框架(6)---action接收请求参数

action接收请求参数

在web开发中,去接收请求参数来获得表单信息非常的常见,自己也总结整理了有关Struts2通过action接收请求参数的几种方法。

Struts2 提供三种数据封装的方式:

(1)  Action 本身作为model对象,通过成员setter封装

(2)  创建独立model对象,页面通过ognl表达式封装

(3)   使用ModelDriven接口,对请求数据进行封装(推荐)

下面我们来讲解第一种:

 (1)   Action类本身作为model对象通过成员的setter方法封装(属性驱动)

setXxx()的xxx必须与请求的参数名一样。就是指和form表单中的name对应的属性要一致

action类的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.Arrays;
import com.ssh.struts2.model.User;
import com.opensymphony.xwork2.ActionSupport;
/*
 * 通过这种方法最简单,但也有缺点如果要把数据封装到model对象中然后传递给业务层和数据层 
 *    还需要单独定义model对象进行传递数据           
 */
public class RegisterAction1 extends ActionSupport {
   
    private String username;   
    private String [] hobby;
     
    @Override
    public String execute() throws Exception {
        //获取表单的数据
        System.out.println("用户名是:"+username);
        System.out.println("兴趣爱好是:"+Arrays.toString(hobby));        
        return null;
    }
   //这里必须提供set方法,get方法可有可无
    public void setUsername(String username) {
        this.username = username;
    }
    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }   
}
/*当你在界面中用户名输入:zhangsan,兴趣爱好选择:体育和读书那么运行结果如下:
 * 用户名是:zhangsan
 * 兴趣爱好是:[sport, read]
 */

struts.xml

1
2
3
4
5
6
7
8
9
10
<?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="default"  extends="struts-default">    
        <action name="register1" class="com.ssh.struts2.action.RegisterAction1">
        </action>             
    </package>
</struts>

register.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
  <head>
  </head>
  <body>
     <h4>注册表单1 </h4>
     <form action="${pageContext.request.contextPath }/register1.action" method="post">
           用户名:<input type="text" name="username"><br/>
          爱好:<input type="checkbox" name="hobby" value="sport">体育
          <input type="checkbox" name="hobby" value="music">音乐
          <input type="checkbox" name="hobby" value="read">读书  <br/>    
          <input type="submit" value="注册">
     </form>
  </body>
</html>

网页:

  (2)  创建独立model对象,页面通过ognl表达式封装

该方法首先要创建一个专门的领域对象进行封装

User领域对象

import java.util.Arrays;
public class User { private String username;
private String [] hobby;
//为这两个常量提供set和get方法和toString方法

Action类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.ssh.struts2.model.User;
import com.opensymphony.xwork2.ActionSupport;
 
public class RegisterAction2 extends ActionSupport{
    //直接定义model对象
    private User user;
    @Override
    public String execute() throws Exception {
        System.out.println("user:"+user);
        return NONE;
    }  
    /*
     * 必须提供get方法 
     *  封装第一个参数 创建一个新的User对象    然后把username属性封装到这个创建的user对象中    User user =new User();user.setUserName("");
     *  封装第二个参数    已经存在user对象   User  user =getUser();     user.setPassword(");
     */
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }   
}
/*
 * 如果jsp界面输入:用户名:aa 兴趣爱好:体育读书
 * 后台输出:user:User [username=aa, hobby=[sport, music]]
 */

register.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <html>
3 <head>
4 </head>
5 <body>
6 <!-- 用ognl表达式要注意的一点就是,标签的属性name在取名字的时候是:领域对象.属性
7 user.username这里user是具体的对象,username是领域对象的属性-->
8 <h4>注册表单1 </h4>
9 <form action="${pageContext.request.contextPath }/register2.action" method="post">
10 用户名:<input type="text" name="user.username"><br/>
11 爱好:<input type="checkbox" name="user.hobby" value="sport">体育
12 <input type="checkbox" name="user.hobby" value="music">音乐
13 <input type="checkbox" name="user.hobby" value="read">读书 <br/>
14 <input type="submit" value="注册">
15 </form>
16 </body>
17 </html>

说明:struts2首先通过反射技术调用User的默认构造器创建User对象,然后通过反射技术调用User中与请求参数同名的属性的setter方法来获取请求参数值。在这里需要注意的一点是:User对象一定要有默认的构造器。

采用复合类型接收请求参数的好处,可以减少action中的setter和getter方法,同时可以把相应的属性组合成一个类,这样使代码更好清晰,代码有更好的结构。

   (3)使用ModelDriven接口,对请求数据进行封装

第三种方法比较方便,和方法(1)不同在于它也要先创建一个领域对象类进行对象的封装。其它和方法(1)一样

  Action类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import com.ssh.struts2.model.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
//实现ModelDriven<User>接口
public class RegisterAction3 extends ActionSupport implements ModelDriven<User> {
    /**
     * 方式三 使用模型驱动
     */
    //这里需要注意,方法2中的user对象不需要自己创建,而这里必须手动初始化
    private User user =new User();
 
    public User getModel() {
        return user;
    
    @Override
    public String execute() throws Exception {
        System.out.println("user:"+user);
        return NONE;
    
}
/*
 * 如果jsp界面输入:用户名:aa 兴趣爱好:体育读书
 * 后台输出:user:User [username=aa, hobby=[sport, music]]
 */

  

 最后我们来思考两个问题,也是常见的笔面试题:

     问题一:Action封装数据会不会有线程问题?

问题二:在使用第一种方式进行封装的时候数据封装到Action 属性中不能把Action传递给业务层数据如何传递?

谢谢大家浏览,欢迎大家指点!

Struts2系列笔记(7)---Struts2类型转换

Struts2类型转换     

struts2中内置了大量的类型转换器用来完成数据类型转换的问题,这篇随笔主要通过两个方面来写Struts类型转换

1:Struts2内置的类型转换器

2:如何自定义类型转换器

那么首先我们来学习有关Struts2内置的类型

1:Struts2内置的类型转换器

Struts2的内置类型转换器,可以为你处理大多数的类型转换,这包括了以下类型和String类型之间的转换!

1.String

将int,double,boolean,String类型的数组或java.util.Date类型转换成字符串。

2:boolean和Boolean

在字符串与boolean之间转换

3:char/Character

在字符串和字符之间转换

4:int/Integer,float/Float,long/Long,double/Double

在字符串与数值类型之间进行转换

5:date

在字符串和日期类型之间进行转换,默认格式是:YYYY-MM-DD

6:数组

由于数组本身就有类型,可以将多个同名参数,转换到数组中(在之前总结的兴趣爱好多选择,如果你选择多个,同时他们name属性相同就自动变为数组)

7:集合

支持将数据保存到 List 或者 Map 集合

关于内置类型转换器举例:

Action类

 1 import java.util.Date;
2 import com.opensymphony.xwork2.ActionSupport;
3
4 public class CustomerAction extends ActionSupport {
5
6 private String username;
7
8 private int age;
9
10 private Date birthday;
11
12 @Override
13 public String execute() throws Exception {
14 System.out.println("客户姓名是:" + username + ",年龄是:" + age + ",生日:" + birthday);
15
16 return NONE;
17 }
18 public void setUsername(String username) {
19 this.username = username;
20 }
21 public void setAge(int age) {
22 this.age = age;
23 }
24 public void setBirthday(Date birthday) {
25 this.birthday = birthday;
26 }
27 }
28 /*控制台输出结果:客户姓名是:zhangsan,年龄是:12,生日:Tue Jul 09 00:00:00 CST 1996
29 */

jsp界面

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <html>
3 <head>
4 </head>
5 <body>
6 <form action="${pageContext.request.contextPath }/customer.action">
7 客户姓名:<input type="text" name="username"><br/>
8 年龄:<input type="text" name="age"><br/>
9 生日:<input type="text" name="birthday"><br/>
10 <input type="submit" value="提交">
11 </form>
12 </body>
13 </html>

界面输入:这里年龄只能输入合法年龄,日期的默认格式:yyyy-MM-dd,如果你输入不合规则网页会报错,比如你输入1996/7/9页面就会报错

 2:如何自定义类型转换器

       为什么需要自定义类型转换器,这个问题相信大家都知道,就像我上面所说的,日期的默认格式是yyyy-MM-dd,那如果你想输入yyyy/mm/dd或者其它的

这个时候就需要你修改你自己的类型转换器,否则会报错。下面我写一个有关自定义类型转换器的方法: 继承StrutsTypeConverter

DateConverter 
 1 import java.text.DateFormat;
2 import java.text.ParseException;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import java.util.Map;
6
7 import javax.xml.bind.TypeConstraintException;
8 import org.apache.struts2.util.StrutsTypeConverter;
9
10 public class DateConverter extends StrutsTypeConverter {
11 //为方便支持多种日期格式的转换,可增加时间格式
12 private final DateFormat [] dateformats={
13 new SimpleDateFormat("yyyy-MM-dd"),
14 new SimpleDateFormat("yyyy年MM月dd日"),
15 new SimpleDateFormat("yyyy.MM.dd"),
16 new SimpleDateFormat("yyyy/MM/dd")
17 };
18 /* 将一个或多个字符串值转换为指定的类型
19 *
20 */
21 @Override
22 public Object convertFromString(Map arg0, String[] values, Class toType) {
23 //从表单获取的日期字符串
24 String dateStr = values[0];//思考:这里为什么是数组而不是字符串?我自己也没有搞明白,希望大神看到后宰评论区给予解答,谢谢
25 for(int i = 0;i<dateformats.length;i++){//遍历日期类型进行转换
26
27 try { //SimpleDateFormat类中parse()方法用于将输入的特定字符串转换成Date类的对象
28 return dateformats[i].parse(dateStr);
29 } catch (Exception e) {
30 continue; //很关键
31 }
32 }
33 throw new TypeConstraintException("遍历结束仍没有指定的类型转换");
34 }
35
36 /* 将指定对象转化为字符串
37 * method:这个方法是用来回显用的,就是你需要回显成什么样的格式就可以设置什么样的格式
38 */
39 @Override
40 public String convertToString(Map context, Object object) {
41 Date date = (Date) object;
42 //指定输出的格式
43 return new SimpleDateFormat("yyyy年MM月dd日").format(date);
44 }
45 }
46 /*主要讲这里的continue,就是如果你是输入的是1992-2-2,那么dateformats[0]和你直接匹配
47 * 那么直接返回,当如果你开始输入的是1992/2/2那么就和dateformats[0]不匹配,那么出现异常执行
48 * catch中的内容,而catch中是continue代表终止本次循环进入下一次循环,那么有和dateformats[1]
49 * 进行匹配,如果都不匹配才会异常,所以这里用的太关键了
50 *

Aation(类)

 1 import java.util.Date;
2 import com.opensymphony.xwork2.ActionSupport;
3
4 public class RegisterAction1 extends ActionSupport {
5 private Date brithday1;
6 private Date brithday2;
7 private Date brithday3;
8 private Date brithday4;
9 /*
10 * 为上面四个提供set和get方法
11 */
12
13 @Override
14 public String execute() throws Exception {
15 //获取表单的数据
16 System.out.println("生日1"+brithday1);
17 System.out.println("生日2"+brithday2);
18 System.out.println("生日3"+brithday3);
19 System.out.println("生日4"+brithday4);
20 return SUCCESS;
21 }
22 }
23 /*后台输出结果:
24 * 生日1Sun Feb 02 00:00:00 CST 1992
25 * 生日2Sun Feb 02 00:00:00 CST 1992
26 * 生日3Sun Feb 02 00:00:00 CST 1992
27 * 生日4Sun Feb 02 00:00:00 CST 1992
28 */

register.jsp(登录界面)

 1 <html>
2 <head>
3 <title>注册</title>
4 </head>
5 <body>
6 <!-- 这里有四个生日 -->
7 <form action="${pageContext.request.contextPath }/register1.action" method="post">
8 生日1:<input type="text" name="brithday1"><br/><br/>
9 生日2:<input type="text" name="brithday2"><br/><br/>
10 生日3:<input type="text" name="brithday3"><br/><br/>
11 生日4:<input type="text" name="brithday4"><br/><br/>
12 <input type="submit" value="注册">
13 </form>
14 </body>
15 </html>

struts.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
4 "http://struts.apache.org/dtds/struts-2.3.dtd">
5 <struts>
6 <!-- 开发者模式 -->
7 <constant name="struts.devMode" value="true"></constant>
8
9 <package name="default" extends="struts-default">
10 <action name="register1" class="com.guigu.struts2.action.RegisterAction1">
11 <result>/result.jsp</result>
12 </action>
13 </package>
14 </struts>
result.jsp
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@ taglib uri="/struts-tags" prefix="s"%>
3 <html>
4 <head>
5 </head>
6 <body>
7 <!-- 回显的时候发现尽管前面输入格式不一样,但输出格式是一样的 -->
8 生日1:<s:property value="brithday1"/><br/>
9 生日2:<s:property value="brithday2"/><br/>
10 生日3:<s:property value="brithday3"/><br/>
11 生日4:<s:property value="brithday4"/><br/>
12 </body>
13 </html>
界面:

最终返回界面:

注意:这中间还有很重要的东西需要配置:配置转换器

4、配置转换器
     Struts2提供了两种方式配置转换器
方式一:应用于全局范围的类型转换器,在src目录下创建xwork-conversion.properties
     转换类全名=类型转换器类全名
    java.util.Date=com.sytudy.struts2.action.DateConverter  (前面是你需要转换的类型,后面是类型转换器类
方式二:应用于特定类的类型转换器,在特定类的相同目录下创建一个名为ClassName-conversion.properties的属性文件
     特定Action类的属性名=类型转换器类全名  

这篇文字就讲到这里,如果哪里有不足,欢迎大家指点,谢谢

Struts2框架(8)---Struts2的输入校验

Struts2的输入校验

在我们项目实际开发中在数据校验时,分为两种,一种是前端校验,一种是服务器校验:

客户端校验:主要是通过jsp写js脚本,它的优点很明显,就是输入错误的话提醒比较及时,能够减轻服务器的负担,但是客户端校验并不是安全的,简单来讲就是防君子防不了小人。

服务器端校验:最大特点就是数据安全,但是如果只有服务器端校验,会大大增加服务器端的负担。

所以一般在我们开发中,是客户端和服务器端校验相结合作用的。

那这篇文章,我只讲服务器端校验,在Struts2支持两种校验方式:

代码校验 :在服务器通过编辑java代码完成数据校验

配置校验: xml配置校验 通过xml配置文件完成数据的校验

(1)代码校验:

代码校验分为三个步骤:

步骤一、封装数据

步骤二、实现要校验的Action  必须继承ActionSupport

步骤三、覆盖Validate方法  然后完成业务逻辑数据的校验

用户界面 register.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
3 <%@ taglib uri="/struts-tags" prefix="s" %>
4 <html>
5 <head>
6 <title>用户注册</title>
7 </head>
8 <body style="text-align: center;">
9 <table align="center" width="50%">
10 <tr>
11 <td style="color: red">
12 <!-- <s:fielderror></s:fielderror> --> <!-- 这里是显示错误的地方 -->
13 </td>
14 </tr>
15 </table>
16
17 <form action="${pageContext.request.contextPath }/login" method="post" >
18
19 用户名:<input type="text" name="username"><br><br>
20 密 码:<input type="text" name="password"><br><br>
21 确认密码:<input type="text" name="password2"><br><br>
22 <input type="reset" value="清空">
23 <input type="submit" value="注册">
24
25 </form>
26 </body>
27 </html>

struts.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
4 "http://struts.apache.org/dtds/struts-2.3.dtd">
5 <struts>
6 <!-- 配置常量信息 -->
7 <constant name="struts.devMode" value="true"></constant>
8
9 <package name="struts2" extends="struts-default" >
10 <action name="login" class="com.study.Login.RegisterAction">
11 <result name="success">/success.jsp</result>
12 <!-- 在input视图中可以通过<s:fielderror/>显示失败信息 -->
13 <result name="input">/register.jsp</result>
14 </action>
15 </package>
16 </struts>
RegisterAction.java
 1 import com.opensymphony.xwork2.ActionSupport;
2 public class RegisterAction extends ActionSupport{
3
4 private String username;
5 private String password;
6 private String password2;
7 //这里我通过set方法封装数据
8 public void setUsername(String username) {
9 this.username = username;
10 }
11 public void setPassword(String password) {
12 this.password = password;
13 }
14 public void setPassword2(String password2) {
15 this.password2 = password2;
16 }
17
18 @Override
19 public String execute() throws Exception {
20 return NONE;
21 }
22
23 //在服务器端需要完成对数据的校验
24 @Override
25 public void validate() {
26 //测试是否得到属性值,证实已经得到
27 System.out.println(username+"---"+password+"---"+password2);
28 if(username==null || username.length()<6 || username.length()>20){
29 //把错误信息保存到字段中
30 this.addFieldError("username", "有户名输入不合法");
31 }
32
33 if(password==null || password.length()<6 || password.length()>20){
34 //把错误信息保存到字段中
35 this.addFieldError("password", "密码输入不合法");
36 }else if( password2==null || password2.length()<6 || password2.length()>20){
37 this.addFieldError("password2", "密码输入不合法");
38 }else if(!password.equals(password2)){
39 this.addFieldError("password2", " 两次密码不一致");
40 }
41
42 super.validate();
43 }
44 }
运行结果:

 (2)框架校验

框架校验也就是通过XML配置方式进行数据校验 ,这也是我们在企业开发的主流校验。

XML校验原理: 将很多规则代码已经写好只需要在xml文件中定义需要使用的校验规则即可。,所以大大减少了我们的开发时间。

我先把步骤写一下:

步骤一:编写JSP

步骤二:编写Action 继承ActionSupport或者Validateable接口

 步骤三:封装请求参数

   步骤四:编写xml校验规则文件

Xml校验文件的命名规则:   Action类名-validation.xml 对Action中所有的方法都执行校验

举例命名规则RegisterAction-validation.xml

同时要满足:Xml校验文件和Action类要在同一包下

步骤一: register.jsp

 register.jsp

步骤二:RegisterAction.java

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class RegisterAction extends ActionSupport implements ModelDriven<User>{ //手动创建一个对象
private User user =new User(); @Override
public String execute() throws Exception {
return NONE;
} public User getModel() {
return user;
}
}

步骤三:封装请求参数

上面手动校验的案例我是用set方法封装数据,那这里我采用的是使用ModelDriven接口,对请求数据进行封装,

在之前我讲过封装数据的三种方法不清楚的可以看下这篇文章:Struts框架(6)---action接收请求参数

User.java

 1 import java.util.Date;
2 public class User {
3
4 private String username;
5 private String password;
6 private String password2;
7 private Integer age;
8 private String email;
9 private Date birthday;
10 private Date graduation;
11
12 /*
13 * 给属性提供get和set方法
14 */
15 }

步骤四:RegisterAction-validation.xml

<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<!--dtd约束在xwork-core-**.jar包中 -->
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户民不能为空</message>
</field-validator> <field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">15</param>
<message>有户名长度必须在 ${minLength} 和 ${maxLength}之间 </message>
</field-validator>
</field> <field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>密码不能为空</message>
</field-validator> <field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">15</param>
<message>密码必须在 ${minLength}和${maxLength}之间 </message>
</field-validator>
</field> <field name="password2">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[password==password2]]></param>
<message>两次密码不一致</message>
</field-validator>
</field> <field name="age">
<field-validator type="required">
<param name="trim">true</param>
<message>年龄不能为空</message>
</field-validator>
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年龄必须在 ${min} 和 ${max}之间</message>
</field-validator> </field> <field name="email">
<field-validator type="email">
<message>不是一个合法的邮箱地址</message>
</field-validator>
</field> <field name="birthday">
<field-validator type="date">
<param name="min">2001-01-01</param>
<param name="max">2003-12-31</param>
<message>生日必须在 ${min} 和${max}之间</message>
</field-validator>
</field> </validators>

struts.xml不需要任何改变,和之前一样就可以了

运行结果:

如果你觉得提示错误的位置有点丑,那你可以运用Struts2的<s:form>标签,效果会更好

现在两种方式都讲了,现在对xml配置的要点一些知识要点进行归纳。

xml校验文件详解:

<validators>: 根元素

<field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字

<field-validator>:指定校验器, type 指定验证规则

上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求

的校验器,这些校验器的定义可以在xwork-2.x.jar中的

com.opensymphony.xwork2.validator.validators下的default.xml中找到。

<param>:子元素可以向验证程序传递参数

<message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message

指定key属性,key的值为属性文件中的key。

struts2校验规则:

系统提供的校验器如下:

required (必填校验器,要求被校验的属性值不能为null)

requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)

stringlength(字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)

regex(正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)

int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)

double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)

fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)

email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)

url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)

date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)

conversion(转换校验器,指定在类型转换失败时,提示的错误信息)

visitor(用于校验action中复合类型的属性,它指定一个校验文件用于校验复合类型属性中的属性)

expression(OGNL表达式校验器,它是一个非字段校验器, expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)

最后讲一个细节:

编写校验文件时,不能出现帮助信息

在编写ActionClassName-validation.xml校验文件时,如果出现不了帮助信息,可以按下面方式解决:

windwos->preferences->myeclipse->files and editors->xml->xmlcatalog

点“add”,在出现的窗口中的location中选“File system”,然后在xwork-2.1.2解压目录的src\java目录中选择xwork-validator-1.0.3.dtd,

回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为URI 。Key改为http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd

struts2框架详解的更多相关文章

  1. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

  2. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

  3. lombok+slf4j+logback SLF4J和Logback日志框架详解

    maven 包依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lomb ...

  4. [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解

    Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...

  5. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  6. Quartz.NET作业调度框架详解

    Quartz.NET作业调度框架详解 http://www.cnblogs.com/lmule/archive/2010/08/28/1811042.html

  7. mapreduce框架详解

    hadoop 学习笔记:mapreduce框架详解 开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感 ...

  8. iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)

    本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...

  9. iOS 开发之照片框架详解

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework.html 一. 概要 在 iOS 设备中,照片和视频是相当重 ...

  10. iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...

随机推荐

  1. Antlr4 语法解析器(下)

    Antlr4 的两种AST遍历方式:Visitor方式 和 Listener方式. Antlr4规则文法: 注释:和Java的注释完全一致,也可参考C的注释,只是增加了JavaDoc类型的注释: 标志 ...

  2. register at least one qt version using“qt vs tools“->“qt options“问题描述及解决方法

    问题描述:在安装了Qt 5.9.8,vs 2022, QT VS Tool 2022并配置好环境变量之后创建Qt项目时无法创建,提示至少需要注册一个Qt版本到Qt VS Tools的Qt Option ...

  3. 基于Java+SpringBoot心理测评心理测试系统功能实现九

    一.前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色.随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态.诊断心理问题.制定心理治疗方案的工 ...

  4. 开源 - Ideal库 - 常用枚举扩展方法(一)

    今天和大家享一些关于枚举操作相关的常用扩展方法. 我们平时用的比较多的是正常枚举,同时还有加[Flags]特性的位标志枚举,因此以下所有扩展方法同时适用正常枚举以及位标志枚举. 我们首先定义两种枚举用 ...

  5. SQLSERVER 2019数据库(可疑) 数据修复案例

    2019 数据库 , 在正常使用过程中 , 服务器突然断电 , 重新启动服务器后 , 数据库变为(可疑). [数据恢复故障分析] 由于数据库在正常读写操作过 , 服务器突然断电 , 导致数据库无法把所 ...

  6. Docker可视化容器管理工具之Portainer

    官网:https://www.portainer.io/ 仓库地址:https://hub.docker.com/r/portainer/ Portainer 是一个轻量级的管理 UI ,可让你轻松管 ...

  7. HZNU Winter Trainning 7 补题 - Zeoy

    CodeForces - 1660C 题目传送门:https://vjudge.net/contest/535955#problem/C 题意:询问一个字符串最少删去几个字符,能够把这个字符串变成aa ...

  8. python3(iJmeter-master)接口测试程序部署实践

    记录学习性能测试过程遇到的问题,加油! 环境 安装环境如下: Windows 10 1803 VMWare Workstation 15 Pro Centos Linux release 7.9.20 ...

  9. RepoDB:一个介于Dapper、EFCore之间.Net的ORM库

    推荐一个介轻量ORM和全功能ORM的开源项目. 01 项目简介 RepoDB 提供了基本操作所需的方法,同时也提供了一些高级功能,如第二层缓存.跟踪.仓储.属性处理器和批量/大量操作.支持的数据库,包 ...

  10. 中电金信鲸视:以AI视觉技术为复杂行业场景装上“火眼金睛”

    ​ 作为人工智能和计算机视觉的交叉领域,智能视觉通过仿生人类视觉机能,对不同形式的视觉输入进行处理.理解和决策.现今,智能视觉已成为应用广泛.市场覆盖大.形式多样的产业方向,得到了国家政策的大力支持. ...