一次jsp电商系统开发总结

文章目录

    • 界面展示
    • 前端部分
      • 如何将多个表单提交给一个servlet处理
      • form表单中的button自动刷新页面问题
      • JS的全局变量
      • $.ajax的回调函数success中使用jquery无效
      • 打开某个页面就加载执行某个js的函数
      • jQuery的children方法
    • servlet部分
      • session的工作原理生存周期
      • Servlet的路由
      • servlet和jsp对比
      • 解决中文乱码
      • ajax前后端数据封装交互(json格式)
    • 数据库部分
      • Mysql操作:Error Code:1175
      • 关于rs.next()问题
      • JDBC:Mysql基本操作增删改查(封装一个类)
      • 数据库连接池
    • 后记

界面展示

  • 主界面-未登录

  • 主界面-登录成功

  • 用户注册
    一次jsp电商系统开发总结_第1张图片

  • 商品浏览
    一次jsp电商系统开发总结_第2张图片

  • 商品查询
    一次jsp电商系统开发总结_第3张图片

  • 购物车界面
    一次jsp电商系统开发总结_第4张图片

  • 留言板
    一次jsp电商系统开发总结_第5张图片

  • 管理员登录
    一次jsp电商系统开发总结_第6张图片

  • 商品管理后台:可商品实现增删(改差没写)
    一次jsp电商系统开发总结_第7张图片

  • 商品添加
    一次jsp电商系统开发总结_第8张图片

前端部分

如何将多个表单提交给一个servlet处理

  • 通过form的隐藏域。
  • <input type="hidden" name="..." value="...">
  • type="hidden"定义隐藏域;name属性定义隐藏域的名称,value属性定义隐藏域的值

form表单中的button自动刷新页面问题

  • form表单中



  • 解决的办法:
  • 1.在

  • 2.将

  • 3.在button的点击事件中加入阻止默认事件执行的代码段
$('button').on('click', function(e) {
    e.preventDefault();
});

JS的全局变量

  • 声明方式一:显式声明
    使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量
var test=5; //全局变量
function a()
{
  var cc=3; //局部变量
  alert(test);
}
function b(){alert(test);}
  • 声明方式二:函数内部不加var关键字声明变量
function a()
{
  aa=3; //全局变量
}
  • 声明方式三:使用window全局对象来声明
window.test;
window.test = 5;

$.ajax的回调函数success中使用jquery无效

  • 解决方法:将需要操作的jquery方法单独封装在一个函数中,然后调用该函数
    一次jsp电商系统开发总结_第9张图片

打开某个页面就加载执行某个js的函数

  • 方法一:使用onload事件
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>测试</title>
    </head>
    <body onload="myfun()">
        <script>
            function myfun(){
                alert("方法一:myfun函数执行");
            }
        </script>
    </body>
</html>

一次jsp电商系统开发总结_第10张图片

  • 方法二:直接调用函数
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>测试</title>
    </head>
    <body>
        <script>
            function myfun(){
                alert("方法二:myfun函数执行");
            }
            myfun();
        </script>
    </body>
</html>

一次jsp电商系统开发总结_第11张图片

jQuery的children方法

  • children()方法返回被选元素的所有直接子元素
  • 该方法只会向下一级对DOM树进行遍历

servlet部分

session的工作原理生存周期

HttpSession session = request.getSession();//取出session
session.setAttribute("goods1","Scoat");//session存数据
session.getAttribute("goods1");//session取数据
request.getSession().removeAttribute("xxx"); //移除Session中特定的值
HttpSession session = request.getSession();
session.setMaxInactiveInterval(20 *  60);//设置session过期时间
session.invalidate();//销毁session的方法
session.getCreationTime();//获得session的创建时间
session.getLastAccessedTime();//获得session最后一次被使用的时间
  • Session在用户访问第一次访问服务器时创建,只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session
  • HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONIDCookie,它的值为该Sessionid(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。
  • 新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择”在新窗口中打开”时,子窗口便可以访问父窗口的Session。
  • URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。
  • HttpServletResponse类提供了encodeURL(String url)实现URL地址重写,该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中。
  • TOMCAT判断客户端浏览器是否支持Cookie的依据是请求中是否含有Cookie。尽管客户端可能会支持Cookie,但是由于第一次请求时不会携带任何Cookie(因为并无任何Cookie可以携带),URL地址重写后的地址中仍然会带有jsessionid。当第二次访问时服务器已经在浏览器中写入Cookie了,因此URL地址重写后的地址中就不会带有jsessionid了。

Servlet的路由

  • 路由信息:
	
        BuyServlet
        younghd.BuyServlet
    
    
        BuyServlet
        /doCar
    
  • 我们此刻配置的路由为/doCar,是和index.jsp,因此在跳转到子文件是应该为jsp/...,从子文件跳出应该为../doCar

servlet和jsp对比

  • jsp经编译后就变成了servlet(jsp本质就是servlet,jvm只能识别java的类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类)

  • Servlet请求过程:当客户端浏览器向服务器请求一个 Servlet 时,服务器收到该请求后,首先到容器中检索与请求匹配的 Servlet 实例是否已经存在。若不存在,则 Servlet 容器负责加载并实例化出该类 Servlet的一个实例对象,接着容器框架负责调用该实例的 init() 方法来对实例做一些初始化工作,然后
    Servlet 容器运行该实例的 service() 方法。若 Servlet 实例已经存在,则容器框架直接调用该实例的 service() 方法。service() 方法在运行时,自动派遣运行与用户请求相对应的 doXX() 方法来响应用户发起的请求。

  • jsp请求过程:当客户端浏览器向服务器请求一个 JSP 页面时,服务器收到该请求后,先检查所请求的这个JSP 文件内容 ( 代码 ) 是否已经被更新,或者是否是 JSP 文件创建后的第一次被访问,如果是,那么,这个 JSP 文件就会在服务器端的 JSP 引擎作用下转化为一个 Servlet 类的 Java 源代码文件。紧接着,这个 Servlet 类会在 Java 编译器的作用下被编译成一个字节码文件,并装载到 jvm 解释执行。剩下的就等同于 Servlet 的处理过程了。

  • jsp是servlet的一种简化,使用jsp只需要完成程序员需用输出到客户端的内容,jsp中的java脚本如何镶嵌到一个类中,由jsp容器完成,而servlet则是个完整的java类,这个类的service方法用于生成对客户端的响应JSP 本质是一个 Servlet,它的运行也需要容器的支持。

  • 在 JSP 和 Servlet 文件中都可以编写 Java 和 HTML 代码,不同的是Servlet 虽然也可以动态的生成页面内容,但更加偏向于逻辑的控制。

  • JSP 最终被转换成 Servlet 在 jvm 中解释执行,在 JSP 中虽然也可以编写 Java 代码,但它更加偏向于页面视图的展现。

  • 参考链接:Servlet与JSP的异同

解决中文乱码

response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=UTF-8");
String addID=new String(request.getParameter("addID").getBytes("ISO8859-1"),"utf-8");

ajax前后端数据封装交互(json格式)

  • ajax部分
function load_goods()
{
    var operation = "all";
    var InfOut = {
        "pan": operation
    };
    $.ajax({
        type: "post",
        url: "../deal_manger",
        data: InfOut,
        success: function (data) {
            var infIn = JSON.parse(data);
            goodsList = infIn.goodslist;
            //商品动态展示
            goodShow();
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert(XMLHttpRequest.status);
        },
    });
}
  • servlet部分
public class mangerServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setHeader("content-type", "text/html;charset=UTF-8");
        String pan =request.getParameter("pan"); //判断是什么操作
        PrintWriter out = response.getWriter();
        JSONObject data = new JSONObject();
        if (pan.equals("all"))
        {
            //获得所有商品的列表
            MyDataBase db=new MyDataBase();
            JSONArray array = new JSONArray();
            try {
                ResultSet rs=db.inputSQL("select * from shop.goods");
                //将数据封装为json数组
                while(rs.next()) {
                    JSONObject obj =  new JSONObject();
                    String id = rs.getString(1);
                    String name=rs.getString(2);
                    obj.put("id", id);
                    obj.put("name", name);
                    array.add(obj);
                }
                db.close();
                //传递Json数组到前端
                data.put("goodslist", array);
                out.print(data);
                out.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

数据库部分

Mysql操作:Error Code:1175

  • 错误:Error Code:1175.You are using safe update mode and you tried to update a table without a WHERE…
  • 原因::在mysql的safe-update模式中,如果where后跟的条件不是主键id,就会报错
  • 解决方法:
    方法一:更改mysql数据库模式SET SQL_SAFE_UPDATE = 0
    方法二:在where判断条件中跟上主键id
  • 参考链接:传送门

关于rs.next()问题

  • rs.next():从查询出来的Resultset集合中拿出一条数据

  • 最开始的指针位于返回结果集的头部,执行一次rs.next(),指针向后移动一位

  • rs.next()返回的是truefalse 如果集合下一条中有数据返回的就是true,否则为false

  • 参考链接

JDBC:Mysql基本操作增删改查(封装一个类)

  • 版本:MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
package younghd;

import java.sql.*;

public class MyDataBase {
    //MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    final String DB_URL = "jdbc:mysql://localhost:3306/数据库名称?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC";
    // 数据库的用户名与密码,需要根据自己的设置
    final String USER = "root";
    final String PASS = "123456";
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs =null;
    PreparedStatement pst=null;
    public MyDataBase() {
        try {
            Class.forName(JDBC_DRIVER);  // 注册 JDBC 驱动
            conn = DriverManager.getConnection(DB_URL,USER,PASS); // 打开链接
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ResultSet inputSQL (String sql) throws SQLException {
        //可以进行增删改查,不能防止sql注入
        stmt = conn.createStatement();
        rs = stmt.executeQuery(sql);
        return rs;
    }
    
    public void insertDB(String t1,String t2,String t3,String t4,String t5) throws SQLException{
        String sql = "insert into 表名 values (?,?,?)";
        //用来执行SQL语句查询,对sql语句进行预编译处理
        //防止sql注入
        pst = conn.prepareStatement(sql);
        pst.setString(1, t1);
        pst.setString(2, t2);
        pst.setString(3, t3);
        pst.executeUpdate();
    }
    public int updateDB(String str) throws SQLException
    {
    	String sql ="update 表名 set name = ? where id=1";
    	pst=conn.prepareStatement(sql);
        pst.setString(1,str);
        int updateOk=pst.executeUpdate();
        return updateOk;
    }

    public int deleteDB(String str) throws SQLException {
        String sql = "delete from shop.goods(表名称)  where id=?";
        pst=conn.prepareStatement(sql);
        pst.setString(1,str);
        int deleteOk=pst.executeUpdate();
        return deleteOk;
    }

    public void close() {
        // 关闭资源
        try{
            if(rs!=null) rs.close();
            if(pst!=null) pst.close();
            if(stmt!=null) stmt.close();
            if(conn!=null) conn.close();
        }catch(SQLException se){
            se.printStackTrace();
        }
    }
}

数据库连接池

  • 什么是数据库连接池:通过维护长连接,减少建立连接的次数,减少占用时间和系统资源,避免资源泄露
  • 为什么需要连接池呢?假如我们的服务器跟数据库没有部署在同一台机器,那么,服务器每次查询数据库都要TCP建立连接(三次握手),MySQL认证(三次握手)、真正的SQL执行、MySQL的关闭、TCP的四次握手关闭建立的连接,假设后台服务跟数据库的单程的访问时间需要10ms,那么光是建立连接就花了30ms,并且TCP还有慢启动的机制,实际上一次查询可能还不止1次TCP来回,查询效率就会大大降低。
  • 连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。

后记

这个电商小系统虽然写完了,问题还是很多,混一次作业,基本都是想到什么就写什么,后面写的越来越乱,也懒得改了勉勉强强完成一次作业吧。算法基本上都是遍历,二分查找什么的都没有用,以后在写程序的过程中尽可能考虑考虑算法,学以致用。学习的东西还很多,比如数据库的查询是如何实现的,Druid的使用,Spring的管理对象,推荐系统等等,慢慢学习吧。

你可能感兴趣的:(学习笔记)