JavaWeb-NewsServlet-大总结

来源:互联网 发布:qq空间个性域名注册 编辑:程序博客网 时间:2024/06/18 13:43

话说:

亲们,晚上好!正是前面一系列的优化,才有了今天这篇总结。如果读者看到这篇,觉得无厘头,请一定要回头从开始的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,才能删除。属性之间是相通的。

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