struts2学习笔记之六(Action访问servlet的API以及复制项目小技巧)

action和servlet分离使得action代码更加纯洁,与servlet的耦合性也降低了
    但是有时候却不得不访问servlet API,比如把数据放到session,application里,
        更甚至于添加cookie(response.addCookie())
    strust2提供了两种方式访问servlet api
        伪访问
            借助于ActionContext类
                Map<String ,Object > getApplication()
                    模拟访问http application
                Map<String,Object> getSession()
                    返回的是一个Map,模拟session,但是对齐修改却又可以作用到session
                    例:
                        Action类的处理代码包含下述语句
                            ActionContext actCtx =  ActionContext.getContext();
                            Map<String,Object> sess = actCtx.getSession();
                            sess.put("userID" ,id);
                            //看似是加入了map,但实际上是放入到了HTTP SESSION里
                        //验证页面访问
                        session里的数据${SessionScope.userID}
                Map<String,Object > getParameter()
                    模拟访问http parameter
        真访问
            这种方法必然会污染Action代码,以为其必须要和Servlet耦合
            借助于ServletActionContext
                提供了获取servlet API的静态方法
                    static  PageContext getPageContext()
                    static  HttpServletRequest getRequest()
                    static  HttpServletResponse getResponse()
                    static  SevletContext getServletContext()
            例:用户登录之后,添加到cookie
                //这个例子的action会被污染,因为添加cookie必须用HttpServletResponse对象,所以该Action必须与Servlet API耦合
                HttpServletResponse response = ServletActionContext.getRespones();
                Cookie cookie = new Cookie("userName",name);
                cookie.setMaxAge(30000);
                response.addCookie(cookie);
                //验证
    复制项目技巧:
        写例子之前先将一个建项目的小技巧。由于每次建项目的前几步都是一样的,建web.xml,struts.xml,导入包,
    将重要的jar包放到WEB-INF\lib下面,这几步每次都重复,显然是很繁琐的。所以现在可以建一个空的项目,里面
    只有必要的包和web.xml和struts.xml,这样就可以不新建项目,而直接复制整个空的项目,然后重命名。


        接下来还有重要的步骤,重命名之后,发布会发现webapps目录没有这个项目,为什么呢?因为复制之后重命名
    只是把项目名改了,而发布到tomcat的配置没有更改,导致发布到tomcat里只是把原来的项目更新了,而不是重新建
    了一个项目。

        方法是:右击项目--->properties---->Project Facets--->web,将Web Context-root里的内容改

        需要注意的,当发布这个新项目的时候,在Project Developments窗口里注意一下发布的位
    置Location是不是新项目文件夹,不是的话,需要删除,重新添加服务器选项。(由于这个没注意,即使更改了
    Web Context-root,也发布不成功)。OK,这样就可以了。

    接下来是设置几个常量(常量的知识下节更新),这样就不需要每次改动项目都需要发布-->重启服务器了

    在struts.xml文件里添加常量。
    <!-- 开发模式为true,出错的时候信息很多,或者配置文件修改会自动备份,减少重启服务器 -->
    <constant name="struts.devMode" value="true"></constant>
    <!-- 编码字符集,应于页面的字符集一样 -->
    <constant name="struts.i18n.encoding" value="gb2312"></constant>
    实例:新建一个项目,测试访问网站的次数
    第一步,复制制作的blank项目(这里面只有web.xml,struts.xml以及必要的包),并且重命名
    第二步,修改Web Context-root。
    第三步,由于是初次使用这种方法,编写一个hello world测试页面测试下。OK,测试成功。稍后附上我的blank项目的web.xml,struts.xml。
    第四步,进入今天的主题,实现Action访问servlet的API。下面编写实现统计访问网站的人数。
        1、编写登陆页面(输入用户名以便存入session)
            <body>
                <form action="login" method="post">
                    用户名:<input type="text" name="name" />
                    <input type="submit" value="登陆">
                </form>
            </body>
        2、编写action类
            public String execute() throws Exception {
                //判断用户是否登陆,
                //用户已登录,则count不变
                //第一次登陆,count++;
                ActionContext ac = ActionContext.getContext();
                Map<String,Object> sess = ac.getSession();
                if(!sess.containsKey(name)){//第一次登陆
                    int count = (int) sess.get("count");
                    sess.put("count", count+1);
                    sess.put(name , "true");
                }
                return SUCCESS;
            }   
        3、根据逻辑视图返回物理视图
            配置strtus.xml
    <?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>
        <!-- 开发模式为true,出错的时候信息很多,或者配置文件修改会自动备份,减少重启服务器 -->
        <constant name="struts.devMode" value="true"></constant>
        <!-- 编码字符集,应于页面的字符集一样 -->
        <constant name="struts.i18n.encoding" value="gb2312"></constant>    

        <package name="abc" extends="struts-default">
            <action name="loginAction" class="org.struts2.action.Login">
                <result>
                    /WEB-INF/content/count.jsp
                </result>
            </action>
        </package>
        <package name="def" extends="struts-default">

                <!-- 万能的action,可以匹配任何action -->
                <action name="*">
                    <!-- 这样的处理可以访问WEB-INF下面的内容,一般来说,用户是不可以访问WEB-INF的内容,有利于安全 -->
                    <!-- 这个思想也就是用户的一切请求皆action-->
                    <result>/WEB-INF/content/{1}.jsp</result>
                </action>
        </package>
    </struts>
            物理视图
    <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
            <title>CountVisitor Page</title>
      </head>

      <body>
            当前在线用户数:${sessionScope.count}
      </body>
    </html>

    测试发现,可以正常访问session。
    遇到的问题:
        大意的将action的name属性和jsp页面名字都定义为了login,结果出现了错误,反思,当定义action的name
    属性是最好用doAction(do表示要做的事),这样就不会出现意想不到的错误了,如此处:登陆页面时login.jsp,提交
    给loginAction,这样也达到了识字知意的效果了,也符合名字的命名规范。
    附:blank项目的情况
    ![项目的整体部署](http://img.blog.csdn.net/20150506192508639)
    其中content文件用来部署jsp页面
    web.xml
            <?xml version="1.0" encoding="UTF-8"?>
            <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

            <display-name>Struts Blank</display-name>

            <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>

            <welcome-file-list>
                <welcome-file>index.jsp</welcome-file>
            </welcome-file-list>

        </web-app>
    struts.xml
        <?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>
        <!-- 开发模式为true,出错的时候信息很多,或者配置文件修改会自动备份,减少重启服务器 -->
        <constant name="struts.devMode" value="true"></constant>
        <!-- 编码字符集,应于页面的字符集一样 -->
        <constant name="struts.i18n.encoding" value="gb2312"></constant>    
        <package name="def" extends="struts-default">

                <!-- 万能的action,可以匹配任何action -->
                <action name="*">
                    <!-- 这样的处理可以访问WEB-INF下面的内容,一般来说,用户是不可以访问WEB-INF的内容,有利于安全 -->
                    <!-- 这个思想也就是用户的一切请求都是action请求-->
                    <result>/WEB-INF/content/{1}.jsp</result>
                </action>

        </package>
    </struts>

你可能感兴趣的:(action,复制项目,ServletAPI,复制项目无法部署解决)