Java框架之Struts2(一)

在学习Struts2之前,我们要知道Java为什么要有反射机制呢?反射机制可以说是填补Java不能动态访问某一个类的空白。利用反射机制,动态的创建一个对象。动态的访问类的某个属性,而且访问哪一个属性自己可能还不知道,只能通过有个变量进行访问。

一、反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射机制主要提供了以下功能:

1.在运行时判断任意一个对象所属的类;

2.在运行时构造任意一个类的对象;

3.在运行时判断任意一个类所具有的成员变量和方法;

4.在运行时调用任意一个对象的方法;

5.生成动态代理。

 

Java 中反射相关的类,都在 java.lang.reflect 包下,主要有以下几个类

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。

Constructor <T> 提供关于类的单个构造方法的信息以及对它的访问权限。

java.lang 包下的 java.lang 类 Class<T>

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。

枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 注意:可以这样 int.class

//例一 通过调用无参构造函数,创建对象
          public class Test {
                public static void main(String[] args) throws InstantiationException, IllegalAccessException {
                    Dog dog=(Dog)createObj(Dog.class);
                    dog.shout();
                    
                    Cat cat=(Cat)createObj(Cat.class);
                    cat.shout();
            
                }
                
                //这个方法用来创建类的实例
                static     Object  createObj(Class clazz) throws InstantiationException, IllegalAccessException{
                    return clazz.newInstance();  //创建对象(注意:它是调用对象的构造函数(无参))
                }
            }
            
            
            class Dog{
                public void shout(){
                    System.out.println("汪汪");
                }
            }
            
            class Cat{
                public  void shout(){
                    System.out.println("喵喵");
                }
            }
    //例二 调用带参的数构造函数
                 class Dog{
                        private String dogName;
                        public Dog(String dogName){  //有了一个有参的构造函数,就没有无参的构造函数了
                            this.dogName=dogName;
                        }
                        public void shout(){
                            System.out.println("汪汪 我的名字是"+this.dogName);
                        }
                    }
        
                    static Object createObj(Class clazz) throws  Exception{
                        // return clazz.newInstance();  这样不可以
                         Constructor con=clazz.getConstructor(String.class);//它的参数是这样声明的 Class ... parameterTypes
                         Object obj= con.newInstance("tom狗");  //Object ... initargs
                         return obj;
                    }
                
                 public static void main(String[] args) throws Exception {
                        Dog dog=(Dog)createObj(Dog.class);
                        dog.shout(); //汪汪 我的名字是tom狗
                 }
      //例三 方法的调用
      class Dog{
            private String dogName;
            public Dog(String dogName){  //有了一个有参的构造函数,就没有无参的构造函数了
                this.dogName=dogName;
            }
            public void shout(){
                System.out.println("汪汪 我的名字是"+this.dogName);
            }
            
            public void shout(String content){
                System.out.println(content);
            }
            
            public void shout(String content,int age){
                System.out.println(content+"  我的年龄是:" +age);
            }
            
            public void eat(){
                System.out.println("小狗正在吃东西");
            }
        
        }
    
      //动态调用类对象中的方法
        //ojb 代表要被调用方法的对象
        //methodName 代表要被调用的方法
        static void invokeTest(Object obj,String methodName )throws Exception {
            //Method [] methods=obj.getClass().getDeclaredMethods(); //取得所有方法,但除了继承来的
            //Method [] methods=obj.getClass().getMethods(); //取得所有公共方法,包含继承来的
            
            /*for(Method m: methods){
                System.out.println(m.getName());
            }*/
            
            
        /*    Method  m=obj.getClass().getMethod(methodName, String.class); //第二个参数 :Object ... parameterTypes
            m.invoke(obj, "这是做为一只狗想说的话");*/
            
            Method  m=obj.getClass().getMethod(methodName, String.class,int.class);
            m.invoke(obj, "这是我的另一句话",2);    
        }
        
        public static void main(String[] args) throws Exception {
                Dog dog=(Dog)createObj(Dog.class);
                invokeTest(dog,"shout");
        }
      //例四 属性的调用   Field
          static void fieldTest(Dog dog)throws Exception{
                    //Field [] filedList=dog.getClass().getFields() ; //取得所有的公共字段,包含继承来的
                    Field [] filedList=dog.getClass().getDeclaredFields(); //取得所有的字段,除了继承来的
                    
                    for(Field field : filedList){
                        System.out.println(field.getName());
                        System.out.println(field.get(dog));   //注意,这里要把 类对象传进去 Field 才知道要访问哪个类对象的属性
                    }
            }
            
            class Dog{
            public  String dogName ="tom";
            public int age=90;
          }
      
       main 方法 :
       {
           Dog dog=(Dog)createObj(Dog.class);
           fieldTest(dog);
       }

二、Struts2 简介

Struts 2 是在 struts1 和 WebWork 的技术基础上进行了合并的mvc 框架,其全新的 Struts 2 的体系结构与 Struts1 的体系结构差别巨大。Struts2 以 WebWork 为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts2 可以理解为WebWork的更新产品。虽然从Struts1 到Struts2 有着太大的变化,但是相对于WebWork,Struts2 的变化很小

为什么要使用 struts2 呢?

传统的MVC模式的问题, 主要就是以下操作有重复性。

重复性一:得到请求参数 Servlet 中

String userName=request.getParameter("userName");
String password=request.getParameter("password");
UserInfo user=new UserInfo();
user.setUserName(userName);
....       

重复性二:请得到的请求参数进行类型转换

int id=Integer.parseInt(request.getParameter("id"));

重复性三:对请求参数的校验 (服务端)

重复性四:请求的跳转 ... request.getRequestDispatcher("xxx.jsp").forward(reques,response)

常用的 MVC 框架

struts1

struts2

spring mvc

jsf (sun 公司提供的mvc 规范

三、Struts2环境的搭建

在struts2的开发包中,有四个文件夹,和一些文本的授权文件

apps, docs, lib , src

apps:示例程序

--struts2-blank.war //空的struts应用
如何搭建一个最最简单的Struts2的项目;它还会告诉你,Struts2至少需要依赖哪些jar包 (请以后不要再为jar包错误而苦恼);同时,也给你做出了一些范例,web.xml怎么写,struts.xml又怎么写。
--struts2-mailreader.war //给出了注册流程、以及发邮件功能
--struts2-portlet.war // 则给出了在Portal环境下的Struts2的应用
 // Portal是一个基于web的应用程序,它主要提供个性化、单点登录、
// 不同来源的内容整合以及存放信息系统的表示层。
--struts2-rest-showcase.war  //rest是 针对WEB 提出的一种构架风格  和 SOAP (简单的对象访问协议)是并列的概念
--struts2-showcase.war

Struts2的特性的大杂烩,这对于你看reference是相当有帮助的。比如说,当在看文档时看到了"文件上传"的章节,那么你就可以参考项目中的upload子目录。相当于你一边看文档,一边已经有一个现成的跑得通的例子在这里提供给你。

docs:文档,API 和相关的指南 (Guide)

注意,要从home.html 开始,过去的版本 是 index.html,现在换了

lib:jar

src:源码
四、开发struts依赖的jar

==最少的配置:
struts2-core-2.x.x.jar : Struts2 框架的核心类库
xwork-2.x.x.jar XWork类库,Struts 在其上构建
ognl-2.6.x.jar 对象导航语言(Object Graph Navigation Lanaguage) Struts2 框架使用的一种表达式语言
freemarker-2.3.x.jar Struts2 的 UI标签模板 使用 freeMarker 编写
commons-logging-1.1.x.jar  ASF 出品的日志包,Struts2 框架使用这个日志包来支持log4j 和 jdk1.4+的日志记录
Commons-fileupload

==还有一种最省事的方法:

如果不需要跟第三方框架集成,把不带-plugin 结尾的jar文件都添加到类路径即可,反之要加入对应的 plugin.jar文件,例如 和 spring 的集成,需要加入 struts2-spring-plugin-2.x.x.jar

==或者是把 struts2-blank\WEB-INF\lib 下所有的 jar 都导入
--asm-3.3.jar  //小巧轻便的 Java 字节码操控框架 ,它能方便地生成和改造 Java 代码。 Hibernate 和 Spring 在底层都用到了 ASM(CgLib 底层用的 asm)
--asm-commons-3.3.jar  //提供了基于事件的表现形式
--asm-tree-3.3.jar //提供了基于对象的表现形式
--commons-fileupload-1.3.1.jar //Struts文件的上传下载
--commons-io-2.2.jar  //apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等
--commons-lang3-3.1.jar //用来处理Java基本对象方法的工具类包,可以简化很多平时经常要用到的写法,例如判断字符串是否为空等等。
--commons-logging-1.1.3.jar //提供的是一个日志(Log)接口(interface)
--freemarker-2.3.19.jar //是一个模板引擎,一个基于模板生成文本输出的通用工具,更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库
--javassist-3.11.0.GA.jar //(JAVA编程助手)使Java字节码操纵简单。这是一个编辑Java字节码的类库。
--log4j-1.2.17.jar //非常强大的log记录软件
--ognl-3.0.6.jar //对象图导航语言,是一种功能强大的表达式语言
--struts2-core-2.3.16.1.jar //核心包
--xwork-core-2.3.16.1.jar //webwork的核心包,因为struts2的前身是webwork

五、搭建Struts2 的初始环境:

1) 导包

apps\struts2-blank\WEB-INF\lib 下所有的jar包

2) 配置全局的一个过滤器 在 web.xml 中配置

<filter>
   <filter-name>struts2</filter-name>
   <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
                        
    <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3) 建一个struts.xml 文件,放到src目录下即可

内容如下 是空的

<?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>
                            
</struts>

4) 布署项目,如果启动没报错,则环境搭建成功      

六、第一个struts2 应用

1)

login.jsp
      <form action="gogogo" method="post">
            账号:<input type="text" name="userName" />
            密码:<input type="text" name="password" />
            <input type="submit" value="提交" />
            ${msg }
        </form>

2)

 //在工程中建 cat.action这个包,然后在包下建 UserAction 这个类
       //这个 UserAction 就是个普通类
          public class UserAction  {
                private String userName;  //一定要和form表单中的字段同名
                private String password;
                private String msg;
                .. 要生成 get set 方法
            
                //方法的返回类型必须String 型,方法名任意
                public String execute(){
                    UserInfo user=UserDao.getLoginUser(userName,password);
                    if(user!=null){
                        msg="用户名和密码正确,OK";
                        return "my_success" ;  //视图
                    }
                    
                    else{
                        msg="用户名或密码错误 Error";
                        return "my_error"; 
                    }
                }

3)

<?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="packageOne" namespace="" extends="struts-default">
                <action name="gogogo" class="cat.action.UserAction"  method="execute" >
                    <result name="my_success">/main.jsp</result>
                    <result name="my_error">/login.jsp</result>
                </action>
            </package>
        </struts>

注意

1) execute 这个方法, 它的名字可以是任意的,如果就叫 execute ,则在配置文件中,不用指定 method

2) 方法的返回值必须是String

3) 要传值的属性必须有 get set 方法

总结 struts2 的开发流程

1) 定义能发送请求的页面,这个页面要么包含表单,要么包含超链接,个另情况可以不用(比如用javasript发请求,或从地址栏直接访问)

2) 定义处理请求的 action

3) 在配置文件中,配置 请求 和action的对应关系, 还要配置处理结果和物理视图之间的对应关系

4) 编写视图 (通常是jsp 或 html 等)

对于Action 的说明

对于  Action  struts2 没有太多的要求,但通常建议

1) 实现Action接口 ,或 者继承自 ActionSupport 类(这个类实现了 Action 这个的接口),它增加了一些类型转换,输入输出校验等支持,而且它实现了execute这个方法,该方法直接返回 SUCCESS

2) 为每个请求参数都提供一个 field ,并提供get 和 set 方法 , 为传递的结果也定义field ,并提供get 和 set 方法

3) 提供一个无参的,返回值为String型的 execute 方法

对于配置文件中的Action 的配置

1) 要求所有的Action都在包中 (package)

2) action 元素通常用如下配置

-- name //皀定action处理哪个请求,也就是请求的名称 ,(gogogo)

-- class //指定action对应哪个类,

-- method //指定avction类中用哪个方法来处理请求

七、继承 ActionSupport 的Action 类

==GoodsAction ==

public class GoodsAction extends ActionSupport {
                private GoodsDao _dao=new GoodsDao();
                private GoodsInfo goodsInfo;
                
                public String execute(){
                    if( _dao.addGoods(goodsInfo)==1)
                        return SUCCESS;
                    else{
                        return ERROR;
                    }    
                }

== goods_add.jsp===

<form action="goods/goodsAction" method="post">
           商品名称:<input type="text" name="goodsInfo.goodsName" />
           商品单价:<input type="text" name="goodsInfo.price" />
           商品描述:<input type="text" name="goodsInfo.des" />
           商品单位:<input type="text" name="goodsInfo.unit" />
           <input type="submit" value="添加" >
       </form>

==配置文件==

<package name="pacakgeTwo" namespace="/goods" extends="struts-default" >
        <action name="goodsAction" class="cat.action.GoodsAction" method="execute" >
            <result name="success">/WEB-INF/goods_manage.jsp</result>
            <result name="error" >/error.jsp</result>
        </action>
    </package>

本例的知识点:

1) 可以使用对象传参,在页面用 goods.goodsName 这样的方式命名

2) extends ActionSupport

3) action 的配置文件中的namespace 的使用

4) 可以把内容放在WEB-INF下,这样可以防止客户端直接访问,只能由服务端进行跳转

例子:商品查询功能

//在 goods_manage.jsp 中
          <a href="${pageContext.request.contextPath }/goods/listgoods" >查看所有商品</a>
          
             public class GoodsAction extends ActionSupport {
                    private GoodsDao _dao=new GoodsDao();
                    private GoodsInfo goodsInfo;  //这个是用来做商品添加的
                    private List<GoodsInfo>goodsList;
                    
                    //添加商品
                    public String execute(){
                        if( _dao.addGoods(goodsInfo)==1)
                            return SUCCESS;
                        else{
                            return ERROR;
                        }    
                    }
                    
                    //查询所有商品
                    public String listGoods(){
                        goodsList=_dao.getGoodsList();
                        return SUCCESS;
                    }
//在配置文件
                 <package name="pacakgeTwo" namespace="/aaa/bbb/ccc/goods" extends="struts-default" >
                        <action name="goodsAction" class="cat.action.GoodsAction" method="execute" >
                            <result name="success">/WEB-INF/goods_manage.jsp</result>
                            <result name="error" >/error.jsp</result>
                        </action>
                        
                        <action name="listgoods" class="cat.action.GoodsAction" method="listGoods" >
                            <result name="success" >/WEB-INF/goods_list.jsp</result>
                        </action>
                    </package>
goods_list.jsp

            <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
            <%@ taglib uri="/struts-tags" prefix="s" %>
               ...
              <body>
              <table width="80%" border=1 cellspacing="0">
                  <c:forEach var="goods" items="${goodsList}"> 
                  <tr>    
                      <td>
                          ${goods.id}
                      </td>
                      <td>
                          ${goods.goodsName}
                      </td>
                      <td>
                          ${goods.unit }
                      </td>
                      
                      <td>
                          ${goods.price }
                      </td>
                      <td>
                          ${goods.des}
                      </td>
                  </tr>
                  </c:forEach>
            
              </table>
              
                    // 用 struts 标签 方式一
                  <s:iterator var="goods" value="goodsList">
                      ${goods.id } | ${goods.goodsName }  | ${goods.des } | ${goods.price } <br />
                  </s:iterator>
                  <br>
                  
                   // 用 struts 标签 方式二
               <s:iterator  value="goodsList">
                      ${id } | ${ goodsName }  | ${des } | ${price } <br />
                  </s:iterator>
              </body>
            </html>

总结:

1 该例继承自 ActionSupport 类,通常action都要继承自该类,以获得一些Struts提供的功能

2 Action中的 Field 是对象类型,所以form表单中的字段,也是 对象.属性这样的写法

3 它自动完成了类型转换

4 jsp文件(或其他 html等) 放在 WEB-INF 文件夹中,安全性更高

5 可以指定Action namespace 属性

6 namespace ,存在搜索顺序的问题,其规则如下:

1) 获得请求路径的URL 例如URL 是 http://localhost:8080/StrutsTest/p1/p2/p3/hellow.action

2) 先按长的路径,在 p1/p2/p3 下找有没有 namespace= p1/p2/p3的 package ,有这个package的话,则找pacakge里有没有名字为hellow的Action

如果没有这个package的话,则去默认 namespace的 package里去找

3) 如果没找到 namespace= p1/p2/p3的 package ,则递减,找 names民pace  =p1/p2/的包

4) 以此类推

原则 : 不管有没有.只要找到包了,就不递减了

什么是默认 namespace 的 package ? 就是 不指定namespace 或指定 namespace="" 的包

7 请注意 url 的写法    <a href="${pageContext.request.contextPath }/goodsManage/listGoods" >

实际上,对请求的路径,经常要进行这样的处理 包扩 form表单的 action 属性也这样写

附: 如何在编写 struts.xml的时候能出现提示?

在 这个配置文件的上面,可以看到有对dtd 文件的引用

<?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 提供的包中,搜索 struts-2.3.dtd 这个文件,找到后,复制出来放到一个地方
然后 点击 windows -> prefrences ->Myeclipse ->Files and Editors ->XML ->XML Catalog 点击右边的 add 按钮,
在弹出的对话框中, 上面的location 选刚才放置的struts
-2.3.dtd文件的位置,
下面的 Key type 中选 uri,key的值输入 http:
//struts.apache.org/dtds/struts-2.3.dtd ,点击 ok 即可,一般来说要重启这个 struts.xml文件

附:   折叠代码插件 code folding 使用方法

解压后,把com.cb.eclipse.folding_1.0.6.jar复制到MyEclipse 8.5\dropins包下面

重启 myeclipse

点击Window > Preferences > Java >Editor>Folding ,进行设置,使用的时候:

 /_start
     public String nihao="nihao";
     public String tahao="tahao";
      //_end  
posted @ 2017-12-19 18:55  江河湖泊  阅读(466)  评论(0编辑  收藏  举报