zoukankan      html  css  js  c++  java
  • J2EE struts2MVC应用在线书签1

    序:之前花了一天研究了一下filter,虽然是实现了MVC模式开发了 WebBookmark,但是代码过于冗长,集中在filter中使用if语句不易阅读,为了体现两份作业的不同点,我决定学习 JavaEE下的struts2框架,实现WebBookmark的MVC模式,这一次,代码将会更加清晰,代码文件分布也会更加容易被读懂,这一次敏捷学习,将会沿用上一代产品的部分代码技术,同时也会暴露很多愚蠢的使用方式,毕竟不是专业的JavaEE程序员,见谅。

    科普:struts2与struts从框架构成来说,完全是两个不同产品,可能大部分新手会觉得这两个东西名儿都一样,struts2一定是struts的 升级版吧,不然,我们不要慵懒的认为struts1书写的项目可以轻松升级到struts2,这么说,要升级几乎就要重写。因为struts2根本不是 struts1升级来这么简单的,struts2基于WebWork2,是完全不同于struts1的框架,Struts2对应的有自己的标签,并且功能 强大。Webwork也有自己的标签。在2005年12月,WebWork与Struts Ti决定合并, 在此同时, Struts Ti 改名为 Struts Action Framework 2.0,成为Struts真正的下一代。官方这么做纯粹是为了炒作,因为struts1很火,但事实上很糟糕,需要被更加优秀的WebWork淘汰掉了, 于是为了拯救这个商标,他们直接升级了Webwork,命名为struts2,基于大名鼎鼎的struts使得struts2可以不费吹灰之力,一炮走 红!

    技术点一:搭建struts框架环境

    接下来我们看看struts2的搭建,还是基于javaweb的dynamic web project应用,创建详情请看我的博客《带你在javaee世界起飞——开发环境搭建》!

    我们直接上struts2环境搭建(注意:基于javaee环境已经搭建好了),struts2将会把应用的代码质量带上一个新的高度,首先下载几个jar包作为类库:

    第一步:下载并解压struts2:

           1.百度“struts2”即可,上“http://struts.apache.org/”下载struts-2.3.24.1-all.zip包

           2.打开压缩文件=》apps/struts2-blank.war这个应用

                  解压其中的/WEB-INF/lib下的jar包,安放到新建的WebBookmark对应的/WebContent/WEB-INF/lib下

                  解压/src/java/struts.xml到新建项目的java source/src下

    第二步:修改web.xml文件(注意在新建项目最后一个next窗口finish前需要勾选)

     

    xml文件在WebContent/WEB-INF/下,配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    
      <display-name>WebBookmark</display-name>
    
     
    
    <filter>
    
    <filter-name>struts2</filter-name>
    
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    
    <init-param>    
    
          <param-name>encoding</param-name>    
    
          <param-value>utf8</param-value>    
    
    </init-param>
    
    </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>

    其实这段代码可以直接在刚刚解压的struts2-blank这个项目相同位置找到并复制!

    我们看看这个xml文件主要就配置了两项,一个是filter,另一个是filter-mapping,咦,不就是我们用的filter过滤器吗?这么配置只不过是把servlet的过滤器交给的struts2框架

    另外welcome-file设置项目首页为index.jsp。

    第三步,设置struts.xml:

    既 然使用了struts作为filter,那么我们不用在像第一次开发那样自己去制作filter了,统统交给struts2配置,那么所有的配置,最麻烦 的地方是我们要不停往这个struts2.xml文件添加配置项了,且先看完整的WebBookmark项目所需的配置文件吧,上代码:

    <?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>
    
        <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
    
        <constant name="struts.configuration.xml.reload" value="true"/>
    
        <constant name="struts.i18n.encoding" value="UTF-8"/>
    
        <!--配置Convention 插件自动重加载映射 -->
    
        <constant name="struts.convention.classes.reload" value="true"/>
    
        <!--user-->
    
        <package name="BookmarkUser" namespace="/user" extends="struts-default">
    
            <!--列出bookmark-->
    
            <action name="list" class="cslg.cn.controller.BookmarkAction" method="list">
    
                <result name="list">/WEB-INF/view/user/list.jsp</result>
    
                <result name="error" type="">/index.jsp</result>
    
            </action>
    
            <!--新增bookmark-->
    
            <action name="add" class="cslg.cn.controller.BookmarkAction" method="add">
    
                <result name="add">/WEB-INF/view/user/add.jsp</result>
    
                <result name="error" type="">/index.jsp</result>
    
            </action>
    
            <!--保存-->
    
            <action name="save" class="cslg.cn.controller.BookmarkAction" method="save">
    
                <result name="success" type="redirect">/user/list.action</result>
    
                <result name="error">/WEB-INF/view/user/error.jsp</result>
    
                <result name="login" type="">/index.jsp</result>
    
            </action>
    
            <!--删除-->
    
            <action name="del" class="cslg.cn.controller.BookmarkAction" method="del">
    
                <result name="success" type="redirect">/user/list.action</result>
    
                <result name="error">/WEB-INF/view/user/error.jsp</result>
    
                <result name="login" type="">/index.jsp</result>
    
            </action>
    
            <!--登录操作-->
    
            <action name="login" class="cslg.cn.controller.UserAction" method="login">
    
                <!--登录成功:重置到list页面-->
    
                <result name="success" type="redirect">/user/list.action</result>
    
                <!--登录错误:首页(非重置)-->
    
                <result name="error" type="">/index.jsp</result>
    
            </action>
    
            <!--注销操作-->
    
            <action name="logout" class="cslg.cn.controller.UserAction" method="logout">
    
                <result name="logout" type="">/index.jsp</result>
    
            </action>
    
        </package>
    
        <!--admin操作-->
    
        <package name="BookmarkAdmin" namespace="/admin" extends="struts-default">
    
            <!--登录操作-->
    
            <action name="login" class="cslg.cn.controller.UserAction" method="login">
    
                <!--登录成功:重置到list页面-->
    
                <result name="success" type="redirect">/admin/list.action</result>
    
                <!--登录错误:首页(非重置)-->
    
                <result name="error" type="">/index.jsp</result>
    
            </action>
    
            <!--列出user-->
    
            <action name="list" class="cslg.cn.controller.UserAction" method="list">
    
                <result name="list">/WEB-INF/view/admin/list.jsp</result>
    
                <result name="error" type="redirect">/index.jsp</result>
    
            </action>
    
            <!--新增user-->
    
            <action name="add" class="cslg.cn.controller.UserAction" method="add">
    
                <result name="add">/WEB-INF/view/admin/add.jsp</result>
    
                <result name="error" type="">/index.jsp</result>
    
            </action>
    
            <!--保存-->
    
            <action name="save" class="cslg.cn.controller.UserAction" method="save">
    
                <result name="success" type="redirect">/admin/list.action</result>
    
                <result name="error">/WEB-INF/view/adminr/error.jsp</result>
    
                <result name="login" type="">/index.jsp</result>
    
            </action>
    
            <!--删除-->
    
            <action name="del" class="cslg.cn.controller.UserAction" method="del">
    
                <result name="success" type="redirect">/admin/list.action</result>
    
                <result name="error">/WEB-INF/view/admin/error.jsp</result>
    
                <result name="login" type="">/index.jsp</result>
    
            </action>
    
            <!--注销操作-->
    
            <action name="logout" class="cslg.cn.controller.UserAction" method="logout">
    
                <result name="logout" type="">/index.jsp</result>
    
            </action>
    
        </package>
    
    </struts>

    xml文件有点小复杂,但是稍作介绍,就能明白原理。

    首先,所有的配置都写在struts这个大架子里面。开头是一些开发中用的初始化,不必多了解,为了方便开发的调试,统一文字编码而已。

    然后,我们看到两个<package>,一个注释为user,意为普通用户的功能,另一个是admin,意为超级用户的功能,在 struts.xml下,package可以作为命名空间,相当于把他们安放在了不同的路径目录“/user”和“/admin”中,注意既然这么设置 了,那么访问的时候,所有关于普通用户操作bookmark的功能url都是“/WebBookmark/user/xxx.action”,同理admin用户管理用户的功能url都在“/WebBookmark/admin/xxx.action”。这个在前端开发中尤为重要,而且不同package的namespace中跳转的相对路径都在当前命名空间下,因为每个命名空间都被看成为一个目录,所以相对路径理所当然是当前空间目录下。

    再后,看<action>,这个是调用java source下的功能的核心,一个action对应一个访问的方法,class映射到java source下package下的类,method映射到类下的方法名,那么name属性就是为用户提供的访问方法,就是url中 “xxx.action”的xxx啦!

    最后,请看<result>,意为“结果”,就是执行完后的页面跳转,里面夹着一个页面,这个页面也可以是另外一个url访问,也可以是对应服务器的jsp文件的物理路径,有一个name是什么呢?一会儿解释!

     

    至少我们已经配置完成了所有的struts配置,也已经把前(V)后(C,M)端分离了,MVC已经基本实现,来看看新目录结构:

    1.java文件

     

    2.前端文件

     

    3.类库文件,其中mysql连接和jstl请参照《J2EE MVC应用在线书签——filter实现1》一文,并没有变

     

    主要是多了struts的类库罢了

     

    技术点二:struts2控制器下的action的getter,setter方法

    在这儿,我发现struts2有个特别的功能,可以将controller和model结合使用,但我没有做深入研究,这里提一下,请看下面这段代码:

    public class UserAction {
    
            /*
    
             * Model:User
    
             */
    
            private Integer id;
    
            private String username;
    
            private String password;
    
            private String user;
    
     
    
            public String getUser() {
    
                    return user;
    
            }
    
     
    
            public void setUser(String user) {
    
                    this.user = user;
    
            }
    
     
    
    /*其他getter,setter方法略*/
    
     
    
         public String login() {
    
                    // 普通用户
    
                    if ("user".equals(this.getUser())) {
    
                            String sql = "select * from user where username='" + this.getUsername() + "' and password='"
    
                                            + this.getPassword() + "'";
    
                            MyDB db = new MyDB();
    
                            try {
    
                                    db.openConnection();
    
                                    ResultSet res = db.executeQuery(sql);

    上面这段代码来自“UserAction.java”,被精简了,但是总结下来无非两个东西,一个是user类的 getter方法,一个是setter方法,我们在filter中,把这个类分离在了Model(模型)中了,但在这里我们直接放在action中,并且 发挥了作用,原来struts2可以把form表单提交的数据(无论post,get方式)利用actiong下的setter方法存储到私有变量中,然 后使用this.getXxx()方法直接在Action之后的方法中获得,这是及其方便的,但,我只用了一次,后面的方法中,我们使用另一种接收方法获取。

     

    技术点三,借用servlet来获取form表单提交的数据

    看下面这行代码:

    String url = "http://"+ new String(ServletActionContext.getRequest().getParameter("url")).trim();

    来自“BookmarkAction.java”,这样获取表单数据看上去很愚蠢,但是借用servlet的方法也是很机智的绕过了很多struts特性,对于敏捷学习的初学者来说相当的实用。

     

    技术点四,借用servlet来操作session

    看下面两段代码:

    保存session:

    ActionContext.getContext().getSession().put("loginuser", loginuser);

    获取已有session:

    User user = (User) ActionContext.getContext().getSession().get("loginuser");

    也是借用了servlet的session

     

    技术点五,借用servlet向jsp发送标签

    后端代码:

    ServletActionContext.getRequest().setAttribute("message", "错误:该用户已存在!");

    前端代码:

    ${requestScope.message }

    后端代码:

                          

      List<BookMark> bms = new ArrayList<BookMark>();
    
                            MyDB db = new MyDB();
    
                            String sql = "select * from bookmark where userid = '" + user.getId() + "';";
    
                            try {
    
                                    db.openConnection();
    
                                    ResultSet res = db.executeQuery(sql);
    
                                    while (res.next()) {
    
                                            BookMark bm = new BookMark(res.getInt(1), res.getString(2), res.getString(3), res.getString(4),
    
                                                            res.getInt(5));
    
                                            bms.add(bm);
    
                                    }
    
                                    db.closeConnection();
    
                            } catch (SQLException e) {
    
                                    e.printStackTrace();
    
                            }
    
                            ServletActionContext.getRequest().setAttribute("list", bms);

    前端代码,由于后端set一个对象列表,前端使用JSTL标签foreach出来:

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <c:forEach items="${list}"  var="list"  varStatus="num">
    
        <tr>
    
            <td>${list.sitename}</td>
    
            <td>${list.url}</td>
    
            <td>${list.cate}</td>
    
            <td><a href="add.action?id=${list.id}">修改</a>&nbsp;<a
    
                    href="del.action?id=${list.id}">删除</a></td>
    
        </tr>
    
    </c:forEach>

    技术点六,方法的返回处理字符串

    注意,在struts.xml对应的所有Action类下的method,即方法,最后返回值都是String类型,所以所有方法都是“public String xxx(){}”形式的;

    且看下面的代码,是删除一条书签的方法:

    public String del() throws UnsupportedEncodingException {
    
        User user = (User) ActionContext.getContext().getSession().get("loginuser");
    
     
    
        //检查session
    
        if (user != null && user.getId() > 0) {
    
            // 获取id
    
            String getid = new String(ServletActionContext.getRequest().getParameter("id").getBytes("ISO-8859-1"),
    
                    "UTF-8").trim();
    
            Integer id = Integer.parseInt(getid);
    
            MyDB db = new MyDB();
    
            String sql = "delete from bookmark where id='" + id + "'";
    
            if (id > 0 && id != null) {
    
                try {
    
                    db.openConnection();
    
                    db.executeUpdate(sql);
    
                    db.closeConnection();
    
                    return "success";
    
                } catch (SQLException e) {
    
                    e.printStackTrace();
    
                }
    
            }
    
            return "error";
    
        }
    
     
    
        return "login";
    
    }

    有三种情况,返回success,返回error,返回login,分别对应删除成功,删除失败,未登录返回登录,然后看关于它的struts.xml配置:

    <action name="del" class="cslg.cn.controller.UserAction" method="del">
    
        <result name="success" type="redirect">/admin/list.action</result>
    
        <result name="error">/WEB-INF/view/admin/error.jsp</result>
    
        <result name="login" type="">/index.jsp</result>
    
    </action>

    很明显,最终返回的字符串是被映射到了struts的result标签的name属性上,例如返回了success,最终以type="redirect"的形式跳转到list.action,重新列出所有的书签,另外两个显而易见,分别跳转到错误页,登录页(index.jsp被设定为登录页)!

     

    技术点七,公用edit和add页面

    从代码高可用性的角度说,edit和add页面其实是可以公用的,且看前端代码:

    <form action="save.action" method="post" class="am-form am-form-horizontal">
    
        <input type="hidden" name="id" value="${requestScope.bookmark.id}" />
    
        <div class="am-form-group">
    
            <label for="url" class="am-u-sm-2 am-form-label">网 址:http://</label>
    
            <div class="am-u-sm-10">
    
                <input type="text" id="url" name="url" placeholder="输入书签地址"
    
                    value="${requestScope.bookmark.url}">
    
                </div>
    
            </div>
    
            <div class="am-form-group">
    
                <label for="sitename" class="am-u-sm-2 am-form-label">网站名称:</label>
    
                <div class="am-u-sm-10">
    
                    <input type="text" id="sitename" name="sitename" placeholder="输入网站名称"
    
                        value="${requestScope.bookmark.sitename}">
    
                    </div>
    
                </div>
    
                <div class="am-form-group">
    
                    <label for="cate" class="am-u-sm-2 am-form-label">分类:</label>
    
                    <div class="am-u-sm-5">
    
                        <select name="cate" id="cate">
    
                            <option value="">选择分类</option>
    
                            <c:forEach items="${list}" var="list" varStatus="num">
    
                                <option value="${list.catename}"
    
                                    <c:if test="${requestScope.bookmark.cate==list.catename}">selected</c:if>>${list.catename }</option>
    
                            </c:forEach>
    
                        </select>
    
                    </div>
    
                    <div class="am-u-sm-5">
    
                        <input type="text" name="newcate" placeholder="新增一个分类"/>
    
                    </div>
    
                </div>
    
                <div class="am-form-group">
    
                    <div class="am-u-sm-10 am-u-sm-offset-2">
    
                        <button type="submit" class="am-btn am-btn-primary am-btn-block">提交</button>
    
                    </div>
    
                </div>
    
            </form>

    我们只需要一个hidden的input传递一个bookmark的id来标记,id存在即为编辑模式,不存在即为添加模式,在后端进行判断,且看代码:

    //获取id
    
    String id = Se)vletActionContext.getRequest().getParameter("id").trim();
    
     
    
    String sql = "";
    
    if (!"".equals(id)) {
    
        bm.setId(Integer.parseInt(id));
    
        sql = "update bookmark set url='" + bm.getUrl() + "', sitename='" + bm.getSitename() + "', cate='"
    
            + bm.getCate() + "' where userid=" + user.getId() + " and id=" + bm.getId() + ";";
    
    } else {
    
        sql = "INSERT INTO bookmark VALUES (null,'" + bm.getUrl() + "','" + bm.getSitename() + "','"
    
            + bm.getCate() + "','" + bm.getUserid() + "');";
    
    }

    如果存在id就执行update语句,不存在就insert into。

  • 相关阅读:
    【hdu 2222】Keywords Search
    【codeforces 750E】New Year and Old Subsequence
    Bit error testing and training in double data rate (ddr) memory system
    北风网09.接收普通消息2
    北风网08.接收普通消息1
    慕课网消息的接收与响应2
    MyEclipse/eclipse 添加作者、注释、版本、时间等
    北风网开发者接入
    java.lang.Error: Unresolved compilation problem: 解决方案
    北风网环境搭建二
  • 原文地址:https://www.cnblogs.com/devilyouwei/p/6293260.html
Copyright © 2011-2022 走看看