JavaWeb-NewsServlet-大总结

本文介绍了一种基于JDBC的Web应用程序优化方案,包括合并多个Servlet为一个BaseServlet、改进BaseDao和NewsDao类以增强代码复用性和灵活性,以及简化页面布局。

话说:

亲们,晚上好!正是前面一系列的优化,才有了今天这篇总结。如果读者看到这篇,觉得无厘头,请一定要回头从开始的JDBC系列开始看起,哈哈。

目录


一、BaseServlet的由来
二、多个Servlet合并归一
三、 BaseDao、NewsDao及页面
四、整体总结


整体布局:

这里写图片描述

这里写图片描述

一、BaseServlet的由来

为了避免在页面用JSP来处理请求和响应,我们用专业的处理请求和响应的工具——Servlet来替换了doAdd.jsp、doUpdate.jsp等页面。前期由于有多个功能-CURD,每个功能对应一个Servlet,页面虽然减少了,但是Servlet却多了起来。所以,我们就进一步把多个Servlet优化为了一个Servlet,在这个Servlet里面调用方法,然后处理请求,进行响应。这里有两种方式来实现在一个Servlet里面调用不同的方法:一是:采用if() else{}判断页面的请求参数op(operation,我们自己定义的);这个方法的弊端是要判断,而且在判断过后,手动调用,本质也没有优化多少;二是:用类本身创建Method对象,调用invoke()方法来实现方法的自动调用。你传过来的op值是什么,默认就调用和op同名的方法。这就弥补了第一种方法的弊端。

BaseServlet如下:

package com.hmc.jdbc.news.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * User:Meice
 * 2017/10/5
 */
public class BaseServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //根据传递参数决定方法跳转 op代表你访问页面传递的参数operation之含义
        String op = req.getParameter("op");
        if(op !=null && !"".equals(op)) {

            try {
                //获取Method对象;这里和我们前面写过的this.getClass().getDeclaredField类似
                Method method = this.getClass().getDeclaredMethod(op,HttpServletRequest.class,HttpServletResponse.class);
                /**
                 * 调用invoke()方法;属于java.lang.reflect下面的类
                 * 自动调用指定的方法 参数1:方法所在的类 参数2:调用方法的参数
                 */
                //如果不取消访问权限检查,会报IllegalAccessException异常
                method.setAccessible(true);
                method.invoke(this,req,resp);

            } catch (NoSuchMethodException e) {
                //这里,我们来掌控,不要让它抛出异常即可。因为不需要携带什么参数,有请重定向上场!但是不利于搞定Bug
                e.printStackTrace();
                //跳转注意/的区别。/直接从绝对路径开始找,没有了相对路径即当前项目名称了
              // resp.sendRedirect("error.jsp");

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }else{
            System.out.println("参数缺失");
        }

    }
}

二、多个Servlet合并归一
之所以可以方便的合并为一个Servlet,就是BaseServlet的功劳。我们只用专注的在NewsServlet里面调用各种方法,处理请求和给与响应即可。
NewsServlet中调用了大量BaseDao和NewsDao两个基类中的方法,这两个基类做了漫长的优化之路。这里一并给出,请对比参阅。

NewsServlet

package com.hmc.jdbc.news.servlet;
import com.hmc.jdbc.news.dao.BaseDao;
import com.hmc.jdbc.news.dao.NewsDao;
import com.hmc.jdbc.news.model.News;
import com.hmc.jdbc.news.util.StringConvertUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;


/**
 * User:Meice
 * 2017/10/5
 */
@WebServlet(urlPatterns = "/news.do")
public class NewsServlet extends BaseServlet {
    NewsDao nd = new NewsDao();
    BaseDao bd = new BaseDao();

        //查(R)
        // 未避免代码混乱,把显示新闻列表封装成方法;这里采用最高级的显示新闻方法listShow3()
        private  void list (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String sql = "select * from t_news";
             List<News> list =(List<News>) bd.listShow3(sql,News.class,null);
            //3 存储到req中
            req.setAttribute("list", list);
                req.getRequestDispatcher("newsShow.jsp").forward(req, resp);
        }



      //增(C)
        private void add(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
            //接受参数
         String title =   req.getParameter("title");
         String author  = req.getParameter("author");
         News news = new News(title,author);
         int result =  nd.newsAdd2(news);//(写这些方法从后往前写)
                if(result > 0) {
                    req.getRequestDispatcher("news.do?op=list").forward(req,resp);

                }else {
                    req.getRequestDispatcher("newsAdd.jsp").forward(req,resp);
                }
        }



        //改(U)

        //显示要修改的新闻
        public void changeShow(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {

            //接受参数
           String strId = req.getParameter("id");
           int id = StringConvertUtil.getVal(strId);
            News news =  nd.newsPut3(id);
            req.setAttribute("news",news);
            req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp);
        }


        //执行修改操作
        public void change(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
            //接受参数
            String strId = req.getParameter("id");
            int id = StringConvertUtil.getVal(strId);
            String title = req.getParameter("title");
            String author = req.getParameter("author");

            News news  = new News(id,title,author);
           //调用方法
            int result =  nd.newsUpdate2(news);
                if(result >0) {
                    req.getRequestDispatcher("news.do?op=list").forward(req,resp);
                }else {
                    req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp);
                }
        }



        //删(D)
        private void del(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
            //接受参数
            String strId = req.getParameter("id");
            int id = StringConvertUtil.getVal(strId);
          int result =  nd.newsDel2(id);
                req.getRequestDispatcher("news.do?op=list").forward(req,resp);
        }


}

三、 BaseDao、NewsDao及页面

BaseDao

package com.hmc.jdbc.news.dao;
import com.hmc.jdbc.news.model.Goods;
import com.hmc.jdbc.news.model.News;
import com.hmc.jdbc.news.model.User;
import com.hmc.jdbc.news.util.ConfigUtil;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

//哎呀,默认导全部的包,如果包到错了怎么办?
public class BaseDao {
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    //1、加载驱动,把加载类定义为静态语句块
    static {
        try {
            Class.forName(ConfigUtil.get("driver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //说实话感觉卡顿的问题也没怎么解决。可能搜狗输入法还没有和捷克公司做好沟通吧。
    }
    //2、连接MySQL数据库 定义方法getConn()
    public Connection getConn() {
        String url = ConfigUtil.get("url");
        String user = ConfigUtil.get("user");
        String password = ConfigUtil.get("password");
        try {
            conn = DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.print("恭喜你,连接上了....");
        return conn;
    }

    //3、关闭资源
    public void closeJDBC(ResultSet rs, PreparedStatement ps,Connection conn) {
        try {
            if (rs != null) rs.close();
            if (ps != null) ps.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static  void main(String[] args) {
        //编写查  把数据库的News输出到控制台

            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            BaseDao bd = new BaseDao();
            //这里如果赋值,就会报NullPoint错误。
           conn = bd.getConn();
        try {
            //预编译SQL语句
            String sql = "select * from t_news";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            //遍历结果集
            while(rs.next()){
                //这里我们可以分明感受到Idea和Eclipse的差别
                int id = rs.getInt(1);
                String title = rs.getString("title");
                String author = rs.getString("author");
                System.out.println(id+"---"+title+"---"+author);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        new BaseDao().test();
    }

    /**
     * 我们会发现,我们发现,在NewsDao里面,尤其是CUD有大量重复代码,他们结构都差不多,不同的只是Sql语句和SQL带的参数。所以我们可以做如下封装。
     *另外,NewsShow中的查询和改(U)代码也几乎完全相同,无非一个是
     * select * from t_news  ;一个是select * from t_news where id = ? 是否也可以类似CUD那样封装起来?
     *
     */
    public int CUD(String sql,Object[] params){
        int result = 0;
        getConn();
        try {
            ps = conn.prepareStatement(sql);
            //问题关键是参数怎么赋值?在参数个数不确定?类型不确定的情况下?
            for (int i=0;i<params.length;i++) {
            ps.setObject((i+1),params[i]);
            }
           result = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        closeJDBC(null,ps,conn);
        return  result;
    }

    //下面们把查在优化一下

    /**
     * 这里我们不把SQL写死,我们会在两个地方用到,1是newsShow.jsp用到,
     * 另外一个是修改新闻的时候要用到,代码区别仅仅只是SQL语句不同。
     */
    public List<News> listShow(String sql, Object[] params) {
        List<News> list = new ArrayList<>();
        getConn();
        try {
            ps = conn.prepareStatement(sql);
            /**
             * 以下方法解决了参数个数和参数类型不同的问题
             * 高度抽象,不论你给多少参数,什么类型,都可以处理。
             */
            //这里的params可能有,也可以没有比如select * from t_news和select * from t_news where id = ?
            //所以最好判断一下
            if(params != null && params.length>0) {
                for(int i = 0;i<params.length;i++) {
                    ps.setObject((i+1),params[i]);
                }
            }
               //否则(null),就不用给参数赋值了,直接执行,这样逻辑才够严谨。
           rs =  ps.executeQuery();
            while (rs.next()) {
                int id = rs.getInt("id");
                String title = rs.getString(2);
                String author = rs.getString("author");
                News news = new News(id,title,author);
                list.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  list;
    }



    //再次优化查的方式,把List<E>对象也变得灵活抽象,不写死
    public List<?> listShow3(String sql ,Class<?> cls,Object...  params) {
        //创建集合存放
        List<Object> list = new ArrayList<>();
        getConn();
        try {
            //预编译
            ps = conn.prepareStatement(sql);
            //如果带参,遍历赋值
            if(params != null && params.length>0){
                for(int i =0;i<params.length;i++) {
                    ps.setObject((i+1),params[i]);
                }

            }
            //执行SQL
            rs = ps.executeQuery();
            //获取元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //遍历
            while (rs.next()) {
                /**
                 * 要解决的问题就在这里
                 * 我们不知道调用该方法的人会传入什么类?那个类中有什么属性?
                 * 也同样不知道该用什么类型来接收,也同样没法把属性作为一个对象传递给
                 * list<E>集合?
                 */
                //实例化对象
                Object obj = cls.newInstance();

                //获取列数
                int count = rsmd.getColumnCount();
                //rs.getObject(这里面的列数通过remd获取);
                    for(int k=1;k<=count;k++) {
                        //获取列名
                      String colName =  rsmd.getColumnName(k);
                      //根据列名获取对象字段
                        Field f = cls.getDeclaredField(colName);
                        //给字段赋值;获取列值
                       Object colVal = rs.getObject(colName);
                       //给对象赋值
                        f.setAccessible(true);//取消访问检查
                        f.set(obj,colVal);
                    }
                list.add(obj);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        return  list;
    }

    public void test() {
        String sql = "select * from t_goods";
        List<Goods> list = (List<Goods>) listShow3(sql, Goods.class,null);
        System.out.println(list);
    }



}

BaseDao和之前最大的区别就是把查做了进一步优化。现在优化的结果就是listShow3()这个方法。不论你实体类怎么变化,给我三个参数:实体类、SQL语句、查询的参数,就可以完美执行查的操作了,并把查询结果存放到一个List<>,(中间是问号)类型中。便于页面传值。其他无大变化。

这里面最关键的用到了Field类。这个类可以把数据库中的字段反射成JavaBean的属性。因为调用listShow3()方法的时候,不知道你会给什么类,只知道你要在哪张表查询,所以在遍历结果集取值并赋值的过程中,Field类起了关键作用。

实体类News

package com.hmc.jdbc.news.model;
public class News {
  private   int id;
  private   String title;
   private String author;

    public News() {
    }


    public News(int id, String title, String author) {
        this.id = id;
        this.title = title;
        this.author = author;
    }
    //没有2个参数的构造方法,我自己就造一个出来;因为增加新闻不需要考虑ID,对于客户来说。
    public News(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "News{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}

NewsDao

package com.hmc.jdbc.news.dao;
import com.hmc.jdbc.news.model.News;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * User:Meice
 * 2017/10/1
 */
public class NewsDao extends  BaseDao{
    //这个类里面我们要写CURD啦。
    //1 查 R
    /**
     * 我们要把数据从刚才的控制台输出变为输出到页面,所以需要一个类似容器的东西存放我们的数据
     * 这里我们用List集合来存放新闻信息,作为运输工具。把我们的代码运输到JSP页面。
     */
    public List<News> list() {
        List<News> list = new ArrayList<>();
        getConn();
        String sql = "select * from t_news";
        try {
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next()) {
                int id = rs.getInt(1);
                String title = rs.getString("title");
                String author = rs.getString("author");
                //每次遍历一次,我们就把一行新闻作为一个对象,这就是JavaBean
                News news = new News(id,title,author);
                list.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //输出做验证,看以上代码是否正确
      //  System.out.println(list);
        closeJDBC(rs,ps,conn);

        return list;
    }

    public static void main(String[] args) {
        NewsDao nd = new NewsDao();
        //验证list()方法
       // nd.list();
    }

    //2 增 C
    //法1:封装发布新闻的方法
    public void newsAdd(News news) {
        getConn();
        String sql = "insert into t_news (title,author) values (?,?)";
        try {
            //预编译,步骤类似查 R
            ps = conn.prepareStatement(sql);
            //这里我们使用?来传递,专业名称忘了
            ps.setString(1,news.getTitle());
            ps.setString(2,news.getAuthor());
            //这里执行和查就不一样了,用的是Update方法
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        closeJDBC(null,ps,conn);
    }

    //法2:封装发布新闻的方法(前后对比明显吧!)
    public int newsAdd2(News news){
        String sql = "insert into t_news (title,author) values (?,?)";
        Object[] params = {news.getTitle(),news.getAuthor()};
       return CUD(sql,params);
    }





    //3 删 D 法一
    public void newsDel(int id) {
        getConn();
        String sql = "delete from t_news where id = ? ";
        System.out.println("进来了");
        try {
            ps = conn.prepareStatement(sql);
            ps.setInt(1,id);
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        closeJDBC(null,ps,conn);
    }

    //删除法二
    public int newsDel2(int id) {
        String sql = "delete from t_news where id = ?";
        Object[] params = {id};
      return   CUD(sql,params);
    }

    //4 改 U
    //法1:第一步,点击修改链接,我们要能把对应的内容放到对应的位置。
    public News newsPut(int id) {
        getConn();
        News news = null;
        String sql = "select * from t_news where id = ?";
        try {
            ps = conn.prepareStatement(sql);
            ps.setInt(1,id);
            rs = ps.executeQuery();
            while (rs.next()) {
                id = rs.getInt(1);
                String title = rs.getString(2);
                String author = rs.getString(3);
                news = new News(id,title,author);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        closeJDBC(rs,ps,conn);
        return  news;
    }
    //法2:封装根据对应ID把新闻放到页面的方法(两方法对比结果鲜明!)
    public  List<News> newsPut2(int id) {
        String sql = "select * from t_news where id = ?";
        Object[] params = {id};
       return listShow(sql,params);
    }
    //法3:根据最高级版本的查的的方法listShow3()来根据id获取新闻,直接返回新闻信息,便于获取
    public News newsPut3(int id) {
        String sql = "select * from t_news where id = ?";
        Object[] params = {id};
      List<News> list =(List<News>) listShow3(sql,News.class,params);
        //判断
        if(list != null && list.size()>0) {
            return list.get(0);
        }else{
            return null;
        }
    }





    //执行修改操作 法1:

    public  void newsUpdate(News news) {
        getConn();
        String sql = "update t_news set title = ? , author = ? where id = ?";
        try {
            ps = conn.prepareStatement(sql);
            ps.setString(1,news.getTitle());
            ps.setString(2,news.getAuthor());
            ps.setInt(3,news.getId());
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        closeJDBC(null,ps,conn);
    }

    //执行修改操作 法2:(没有对比就没有伤害)
    public int newsUpdate2(News news) {
        String sql = "update t_news set title = ?, author = ? where id = ?";
        Object[] params = {news.getTitle(),news.getAuthor(),news.getId()};
        return   CUD(sql,params);
    }

}

这个几乎没有变化,读者如果用心看,可以看到优化升级的痕迹。

页面布局
也是和之前的NewsServlet类似。不过这次3个页面搞定!

新闻列表:newsShow.jsp


<%@ page import="java.util.List" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="com.hmc.jdbc.news.model.News" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib  uri="http://java.sun.com/jstl/core" prefix="a" %>
<%--
  Created by IntelliJ IDEA.
  User: Meice
  Date: 2017/10/1
  Time: 13:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--如果不用jstl,还是采用JSP嵌套获取--%>
<%--
<%
    //本来在页面,我们获取list集合非常简单,${}这样就获取了,但是实际过程中,我们在JSP代码中没发做到用这个来获取
    List<News> list =(List<News>) request.getAttribute("list");
%>
--%>



<html>
<head>
    <title>Meice的新闻列表</title>
</head>
<body>
    <h2 align="center">Meice的新闻列表</h2>
    <table border="1" align="center" width="80%">
        <thead>
            <tr>
                <th>编号</th>
                <th>标题</th>
                <th>作者</th>
                <th>操作</th>

            </tr>

        </thead>
        <tbody>
           <%--${news}--%>
           <%--这里传过来就是那幅图的场景;现在的问题是我不知道怎么接收这个传递过来的值,直接用EL取出来的是
           个List<News>的集合。这边又没法遍历。??
           如果不用JSTL,我们用普通的for each,问题是怎么取出这个值。
           --%>
             <c:forEach var="news" items="${list}">
                    <tr>
                        <td align="center">${news.id}</td>
                        <td align="center">${news.title}</td>
                        <td align="center">${news.author}</td>
                        <td align="center">
                            <a href="news.do?op=changeShow&id=${news.id}">修改</a>
                            <a href="news.do?op=del&id=${news.id}" onclick="return confirm('真的忍心删我?')">删除</a>
                        </td>
                    </tr>
            </c:forEach>

        </tbody>
        <tfoot></tfoot>
    </table>
    <a href="newsAdd.jsp">发布新闻</a>
</body>
</html>

发布新闻页面newsAdd.jsp

<%--
  Created by IntelliJ IDEA.
  User: Meice
  Date: 2017/10/1
  Time: 15:02
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>发布新闻</title>
</head>
<body>
    <form action="news.do" method="post">
        <%--传递参数的时候,可以直接传参,也可以用隐藏域--%>
       <input type="hidden" name="op" value="add"/>
        <table>
            <tr>
                <td>标题</td>
               <td><input type="text" name="title"></td>

            </tr>
            <tr>
                <td>作者</td>
                <td><input type="text" name="author"></td>

            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="发布"></td>

            </tr>

        </table>


    </form>
</body>
</html>

修改新闻页面newsUpdate.jsp


<%@ page import="java.util.List" %>
<%@ page import="com.hmc.jdbc.news.model.News" %>
<%@ page import="java.util.ArrayList" %><%--
  User: Meice
  Date: 2017/10/1
  Time: 18:06
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="news.do" method="post">
        <input type="hidden" name="op" value="change"/>
        <%--既然form表单的提交方式都为post了,那么在带参就不好,所以用隐藏域来传参--%>
        <table>
            <%--多个可以遍历,一个元素也可以遍历的。否则又要回归到JSP方法取值了--%>

                <tr>
                    <td>编号</td>
                    <td><input type="text" name="id" value="${news.id}" disabled="disabled" ></td>

                </tr>
                <tr>
                    <td>标题</td>
                    <td><input type="text" name="title" value="${news.title}"></td>

                </tr>
                <tr>
                    <td>作者</td>
                    <td><input type="text" name="author" value="${news.author}"></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" value="确认修改"></td>
                </tr>


        </table>
    </form>
</body>
</html>

也许你还会问,web.xml配置呢?哈哈,我们全部用了Servlet3.0新特性——注解搞定啦。
这里的web.xml也贴出来,作为纪念,里面的配置已经没有任何实质作用啦。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

   <!--news Add Servlet-->

    <servlet>
        <servlet-name>newsAdd</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsAddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>newsAdd</servlet-name>
        <url-pattern>/newsAdd.do</url-pattern>
    </servlet-mapping>


    <!--news Show Servlet-->

    <servlet>
        <servlet-name>newsShow</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsShowServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>newsShow</servlet-name>
        <url-pattern>/newsShow.do</url-pattern>
    </servlet-mapping>

    <!-- news Update Servlet-->
    <servlet>
        <servlet-name>newsUpdate</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsUpdateServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>newsUpdate</servlet-name>
        <url-pattern>/newsUpdate.do</url-pattern>
    </servlet-mapping>

    <!--news Update Do Servlet-->
    <servlet>
        <servlet-name>newsUpdateDo</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsUpdateDoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>newsUpdateDo</servlet-name>
        <url-pattern>/newsUpdateDo.do</url-pattern>
    </servlet-mapping>

    <!--news Del Servlet-->
    <servlet>
        <servlet-name>newsDel</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsDelServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>newsDel</servlet-name>
        <url-pattern>/newsDel.do</url-pattern>
    </servlet-mapping>


    <!--news Servlet 这个Servlet可以处理所有操作;只要你给我一个参数-->
    <!--用Servlet3.0新特性——注解的时候就可以不用配置啦!-->
   <!-- <servlet>
        <servlet-name>news</servlet-name>
        <servlet-class>com.hmc.jdbc.news.servlet.NewsServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>news</servlet-name>
        <url-pattern>/news.do</url-pattern>
    </servlet-mapping>

-->
    <!--错误页面配置-->
   <!--<error-page>-->
        <!--&lt;!&ndash;表示页面错误类型404 400 500之类的&ndash;&gt;-->
        <!--<error-code>404</error-code>-->
        <!--&lt;!&ndash;这里配置错误页面位置&ndash;&gt;-->
        <!--<location>/error.jsp</location>-->
       <!--&lt;!&ndash;这个配置是配置错误类型类似:NullPointException&ndash;&gt;-->
       <!--&lt;!&ndash;<exception-type></exception-type>&ndash;&gt;-->
    <!--</error-page>-->

    <!--既然是Servlet新特性,我们把Filter也加入进来,这里过滤字符编码;加入注解,也就不用配置了-->
  <!--  <filter>
        <filter-name>encoding</filter-name>
        <filter-class>com.hmc.jdbc.news.filter.EncodingFilter</filter-class>

        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>-->

    <!--加入我们的监听器TestHttpSessionListener;这里同样可以加入注解,取消配置-->
   <!-- <listener>
        <listener-class>com.hmc.jdbc.news.listener.TestHttpSessionListener</listener-class>
    </listener>
-->
</web-app>


优化到这里,就会明白一个道理,温故知新,知历史方能更好的知未来。不经历优化的漫长体验,就无法体会优化后的爽歪歪。

四、整体总结

四点总结

1、根据ID获取News对象,封装成方法。这是个很好的优化过程,之前我们每次修改和删除传递ID的时候,都是接收后,然后转换为整型,搞得很无语。现在好了,一个方法,随时调用。当你重复代码多起来的时候,就思考下,怎么来简化。

package com.hmc.jdbc.news.util;

/**
 * User:Meice
 * 2017/10/8
 */
public class StringConvertUtil {

    //还记得每次修改和删除的时候,都要接受字符串id嘛,转换的很辛苦,每次都重复这段代码,今天从根源解决一下

    /**
     * 1 接受参数
     *int id = 0;
     *String strId = req.getParameter("id");
     *if (strId != null && !"".equals(strId)) {
     *id = Integer.valueOf(strId);
     *}
     */
    //未方便调用,直接来个静态的
    public static int getVal(String str){
        int id =0;
        if(str != null && !"".equals(str)) {
           id = Integer.parseInt(str);
        }else{
           id =0;
        }
        return  id;
    }

}

2、 public List<问号> listShow3(String sql ,Class<问号> cls,Object… params) {}
这里List<问号>写?而不写Object大有作用,这里的?代表Object以及任何实体类,
这样在调用该方法的时候,返回值的类型可以强转成任意需要的类型:

 List<News> list =(List<News>) 

listShow3(sql,News.class,params);
但是,如果方法开始这么定义public List listShow3(String sql ,Class<问号> cls,Object… params){}
那么接收的时候,就无法转换类型。实体类没发强转成List类。

示例:
//以下方法的弊端是:你传过去的是个List里面存放的是 Object的集合,不好取值

 /*  String sql = "select * from t_news where id = ?";
            Object[] params = {id};
            //调用这个在查功能上万能的方法,哈哈!
            List<Object> list = bd.listShow3(sql,News.class,params);
            //传参
            req.setAttribute("list",list);
            //页面跳转
            try {
                req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp);
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            */

你返回的是一个List里面存放的是Object对象,那么我们的JavaBean呢?根本没用上呢

3、传递多个参数,用&连接

<a href="news.do?op=changeShow&id=${news.id}">修改</a>

别写成这样:

<a href="news.do?op=changeShow&?id=${news.id}">修改</a>

4、修改新闻的时候,让新闻编号id显示还是不显示?如何显示,This is a question!

  <tr>
      <td>编号</td>
     <td><input type="text" name="id" value="${news.id}" readonly="readonly"></td>

  </tr>

1)编号是后台把控的,如果不想用户看到,可以作为隐藏域

<input type="hidden" name="id" value="${news.id}"/>

这样在form表单提交的时候,id照样可以传过去,便于后台执行修改操作。那为什么不直接在

 <form action="news.do" method="post">

里的news.do?id=${news.id}这样带参?又是post提交,又带参,就不好了。

2)除了设置为readonly=”readonly”之外,我们表面上还可以设置为diabled=”disabled”;但是虽然也达到了了用户不能修改id的目的且显示灰色,表示不能修改。但是,一旦改为这个,在点击提交的时候,id就没发传到后台。我们的修改和删除全都依靠id来操作…….

我们在NewsServlet里面接受参数那几行代码设置断点,然后DeBug观察参数变化,如图:

这里写图片描述

这里写图片描述

实践是检验真理的唯一标准,果然,后台没有接收到参数id.
所以,慎用disabled属性。

大数据里面,HBase表格中,一张表只有disabled,才能删除。属性之间是相通的。

好了,各位,晚安!下次再会!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值