JavaWeb项目-管家婆账务系统(JSP+Servlet+Bootstrap)

Gitee链接:https://gitee.com/fanggaolei/housekeeper-bookkeeping-system

本项目为个人练手项目,采用Servlet+JSP+BootStrap为主要技术点,适合JSP课程设计,练习Java开发,SQL查询

项目概述

  本项目为一个记账系统,实现用户进行注册登录后,进入主页面,对个人账单数据进行增啥改查,并提供丰富的查询聚合统计功能。

​    项目主要用到JSP做页面展示,使用Servlet,作为做后端数据的处理工作,使用MySql作为数据存储,项目采用标准的MVC架构实现即”模型-视图-控制器“三层架构实现(View—>Controler—>Service—>Dao),开发者可以通过个人需求对页面内容进行分层开发。

主要采用技术:

前端:bootstrap,javascript,JQuery,html,css

后端:Java,SQL,servlet

1.需求说明

1.用户注册

   用户注册提交表单后需要进行数据的校验功能,输入框不能为空,两次输入的密码必须一致,用户名和密码长度符合需求。

2.用户登录

   用户输入个人正确的账号密码进入主页。输入数据必须不能为空,且必须符合长度规范才能提交。

3.用户主页

   用户进入主页后,根据用户的个人ID,在账务数据库中查询,只属于个人的账户信息,并在页面左侧边栏显示账务的聚合信息,在中间部分主页显示具体的数据表单。

4.用户数据查询

   显示所有数据,当用户进入主页后,直接根据用户ID查询当前用户的所有账务信息,并显示在页面,用户点击类型或时间查询,弹出对应的模态框,用户根据模态框的提示信息,填写对应格式的数据,如果数据格式不匹配,则表单无法进行提交。

5.用户删除数据

当用户点击对应信息的删除按钮,弹出模态框,提示用户是否确认删除当前信息,用户点击确认后,则将当前数据删除,并自动刷新当前页面

6.用户新增数据

   当用户点击新增数据时,弹出对应新增数据表单,用户根据提示信息,将正确的内容输入,点击提交按钮即可提交数据,如果用户输入的数据不符合规范,页面弹出对应的提示,让用户填写符合格式的数据。

7.用户修改数据

   当用户点击对应数据的修改按钮时,当前数据的信息回显到,修改数据模态框中,用户根据个人情况对数据进行修改,并且提交的数据必须是符合规范的,如果数据不符合格式要求,提示用户填写正确格式的数据。

8.用户退出登录

   当用户退出登录后,用户不可通过返回页面继续修改页面数据,实现方式为,当用户点击 退出按钮,就销毁当前session,用户无法再修改数据。

2.运行环境说明

MySql:5.7版本

Tomcat:7(使用Maven插件,在Pom.xml文件中配置即可使用,无需个人下载)

JDK:1.8版本

3.页面展示

1.登录页面

image-20230319155848386

2.注册页面

用户需要输入用户名

并需要输入两次相同密码才能注册成功

image-20230319155911466

3.主页面

左边栏显示时间信息,以及当前用户数据信息

image-20230319155935318

4.增删改查模态框

页面左边栏显示表格聚合信息

系统支持:用户数据的增删改查

image-20230319155957094

image-20230319160027208

image-20230319160048627

image-20230319160107824

image-20230319160128063

4.开发问题

1.servlet如何向另外一个servlet传值?

将数据放入到对应的请求体中,通过页面的转发和重定向可以实现,两个servlrt的数据传输

request.setAttribute("list",zhangWu);
request.getAttribute("list",zhangWu);
2.servlet如何向JSP页面传值?

1.servlet将数据放入到session中,jsp页面可以从session获取数据

2.Servlet将数据放到请求体重,并进行转发

request.setAttribute("data", "this is a data to send");
request.getRequestDispatcher("next.jsp").forward(request, response); 
3.JSP如何向Servlet传值?

1.form表单

2.URL 发送get请求即可

3.session:jsp页面直接将数据存入到session中就可以了

4.JS如何将数据回显到修改模态框中

下面是本项目的表单回显

主要说明:

1.获取到需要回显的值

2.将数据打包成一个对象

3.普通数据回显根据dom的name直接将数据写回

$("#money1").attr("value",strings1[2]);

4.下拉菜单回显

遍历下拉菜单的元素信息,当信息与当前相等的时候进行数据回显即可

let options = document.getElementById("xiaofei").options;
        for(let i = 0;i<options.length;i++){
            if(options[i].value==strings1[1]){//根据id选中阿里
                options[i].selected = true;
            }
        }
<script type="text/javascript">
    var Zhanghu=new Object();
    function upimg(id){
        var res=id;

        //将当前ID数据传递给删除模态框提交到servlet中
        var box = document.getElementById("s")

        box.innerText=res
        //box1.innerText=res
        //将id值传给input标签
        $("#imgtalk").attr("value",res);
        $("#imgtalk1").attr("value",res);

        var attribute = document.getElementById(id).getAttribute("value");
        console.log(attribute)

        var strings1 = attribute.split("=");

        console.log(strings1[0]);

        Zhanghu.zwid=strings1[0];
        Zhanghu.flname=strings1[1];
        Zhanghu.money=strings1[2];
        Zhanghu.zhanghu=strings1[3];
        Zhanghu.createtime=strings1[4];
        Zhanghu.description=strings1[5];
        Zhanghu.userid=strings1[6];
        huixian(strings1);
    }

    function huixian(strings1){
        console.log(strings1[0]);
        console.log(strings1[1]);
        $("#money1").attr("value",strings1[2]);
        $("#type1").attr("value",strings1[3]);
        $("#time1").attr("value",strings1[4]);
        $("#desc").attr("value",strings1[5]);


        let options = document.getElementById("xiaofei").options;
        for(let i = 0;i<options.length;i++){
            if(options[i].value==strings1[1]){//根据id选中阿里
                options[i].selected = true;
            }
        }

        let options1 = document.getElementById("type1").options;
        for(let i = 0;i<options.length;i++){
            if(options1[i].value==strings1[3]){//根据id选中阿里
                options1[i].selected = true;
            }
        }
    }
</script>
5.如何向JSP页面直接写数据

这应该是最直接的写入方式

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
	request.setCharacterEncoding("utf-8");//解决中文乱码的问题
	String name = request.getParameter("uname");
	String password = request.getParameter("pwd");
	String sex = request.getParameter("sex");
	String []favour = request.getParameterValues("duo");
	String email = request.getParameter("email");
%>

	<p>账号:<%=name %></p>
	<p>密码:<%=password %></p>
	<p>性别:<%=sex %></p>
	
	爱好:
	 <%
     /* for(String c : favour){
        out.println(c + " "); 
     }
 	*/
 	for(int i = 0 ; i < favour.length ; i++){
 		String message = favour[i];
 		out.print(message+"   ");
 	}
 	%> 
     
     <p>邮箱:<%=email %></p>
     

</body>
</html>
6.maven中tomcat7插件配置的问题?

不能在标签内引入

<plugins>
      <!-- 配置Tomcat插件 -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>8080</port>
          <path>/</path>
          <uriEncoding>UTF-8</uriEncoding>
        </configuration>
      </plugin>
    </plugins>

点击这个直接运行

image-20230319165526792

使用servlet必须将组件配置为

<scope>provided</scope>

scope:这个项目在编译,测试,运行阶段都需要这个jar包在classpath中

provided:可以认为这个provided是目标容器已经provide这个jar。换句话说,它只影响到编译,测试阶段。而在运行阶段,假定目标的容器(比如我们这里的tomcat容器)已经提供了这个jar包,app可以直接使用容器提供的jar,所以无需我们打包对应的jar包了。

import:解决maven继承(单)问题,Maven的继承和Java的继承一样,是无法实现多重继承的,一个子模块只能有一个标签。如果这个父模块有十几个子模块,那这个父模块的dependencyManagement会包含大量的依赖,不利于管理。

runtime:表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段。

test:表示dependency作用在测试时,不作用在运行时。 只在测试时使用,用于编译和运行测试代码。不会随项目发布。

system:跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它

image-20230319165620434

7.JS如何实现简单form表单的数据校验?
<form action="/register" method="post" id="registform"  name="form1" onSubmit="return beforeSubmiti(this);">
                <input type="text" name="name" placeholder="name" class="input-item">
                <input type="password" name="password" placeholder="password" class="input-item">
                <input type="password" name="password2" placeholder="password notarize" class="input-item">
                <button class="btnn" type="submit">Sign Up</button>
</form>

<script type="text/javascript">
    function beforeSubmiti(form1){

        if(form1.name.value==''){
            alert('用户名不能为空!');
            form1.name.focus();
            return false;
        }

        if(form1.password.value==''){
            alert('密码不能为空!');
            form1.password.focus();
            return false;
        }

        if(form1.password.value.length<6){
            alert('密码至少为6位,请重新输入!');
            form1.password.focus();
            return false;
        }

        if(form1.password.value!=form1.password2.value) {
            alert('你两次输入的密码不一致,请重新输入!');
            form1.password2.focus();
            return false;
        }
        return true;
    }
</script>
8.commons-dbcp连接池的基本配置?

commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

package com.fang.gjp.util;

/*
 *  获取数据库连接的工具类
 *  实现连接池,dbcp连接池
 */
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
public class JDBCUtils{
    //创建BasicDataSource对象
    private static BasicDataSource datasource = new BasicDataSource();
    //静态代码块,实现必要参数设置
    static{
        datasource.setDriverClassName("com.mysql.jdbc.Driver");
        datasource.setUrl("jdbc:mysql://127.0.0.1:3306/gjp?useUnicode=true&serverTimezone=GMT&characterEncoding=UTF-8&useSSL=false");
        datasource.setUsername("root");
        datasource.setPassword("fgl123");
        datasource.setMaxActive(10);
        datasource.setMaxIdle(5);
        datasource.setMinIdle(2);
        datasource.setInitialSize(10);
    }
    public static DataSource getDataSource(){
        return datasource;
    }
}
9.commons-dbutils的说明?

是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。

commons-dbutilsAPI介绍:

  • org.apache.commons.dbutils.QueryRunner
  • org.apache.commons.dbutils.ResultSetHandler

工具类

  • org.apache.commons.dbutils.DbUtils

一些说明:

查询结果的返回值:

ArrayHandler:把结果集中的第一行数据转成对象数组。

ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。

BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。//重点

MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。//重点

MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

ColumnListHandler:将结果集中某一列的数据存放到List中。

KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),再把这些map再存到一个map里,其key为指定的列。

ScalarHandler:将结果集第一行的某一列放到某个对象中。//重点

基本查询方法:

    public static void delete()throws SQLException{
33         //创建QueryRunner类对象
34         QueryRunner qr = new QueryRunner();    
35         //写删除的SQL语句
36         String sql = "DELETE FROM classmate WHERE id<=?";
37         //调用QueryRunner方法update
38         int row = qr.update(conn, sql, 10);
39         System.out.printf("已经有[%d]发生了改变",row);
40         /*
41          *  判断insert,update,delete执行是否成功
42          *  对返回值row判断
43          *  if(row>0) 执行成功
44          */
45         DbUtils.closeQuietly(conn);
46     }
47     
48     /*
49      *  定义方法,使用QueryRunner类的方法update将数据表的数据修改
50      */
51     public static void update()throws SQLException{
52         //创建QueryRunner类对象
53         QueryRunner qr = new QueryRunner();    
54         //写修改数据的SQL语句
55         String sql = "UPDATE classmate SET age=? WHERE name=?";
56         //定义Object数组,存储?中的参数,注意传入的位置哟,不要把顺序写反了!
57         Object[] params = {18,"尹正杰"};
58         //调用QueryRunner方法update
59         int row = qr.update(conn, sql, params);
60         System.out.printf("已经有[%d]发生了改变",row);
61         DbUtils.closeQuietly(conn);
62     }
63     
64     /*
65      * 定义方法,使用QueryRunner类的方法update向数据表中,添加数据
66      */
67     public static void insert()throws SQLException{
68         //创建QueryRunner类对象
69         QueryRunner qr = new QueryRunner();
70         String sql = "INSERT INTO classmate VALUES(?,?,?,?,?,?,?,?,?,?)";
71         //将三个?占位符的实际参数,写在数组中
72         Object[] params = {null,"方合意",24,"python开发工程师",100,60,89,94,92,87};
73         //调用QueryRunner类的方法update执行SQL语句
74         System.out.println(conn);
75         int row = qr.update(conn, sql, params);
76         System.out.printf("已经有[%d]发生了改变",row);
77         DbUtils.closeQuietly(conn);
78     }
10.HttpServlet的请求响应流程

HttpServlet的请求响应流程

Web客户向Servlet容器发出Http请求
Servlet容器解析Web客户的Http请求
Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息
Servlet容器创建一个HttpResponse对象

Servlet容器调用HttpServlet的service方法,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象

HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息
HttpServlet调用HttpResponse的有关方法,生成响应数据
Servlet容器把HttpServlet的响应结果传给Web客户

11.请求转发和请求重定向的区别?

getRequestDispatcher()包含两个重要方法,分别是请求转发和请求包含。一个请求跨多个Servlet时,需要使用请求转发和请求包含。

首先需要获得一个RequestDispatcher 对象:RequestDispatcher rd = request.getRequestDispatcher(“/MyServlet”);

请求转发: rd.forward( request , response ); 留头不留体
请求包含: rd.include( request , response); 都留
需注意的是,无论是请求转发还是请求包含,都在一个请求范围内!使用同一个request和response!

请求转发和请求包含的区别

请求转发:由下一个Servlet完成响应体,当前Servlet可以设置响应头(留头不留体)。举个例子,AServlet请求转发到BServlet,那么AServlet不能够使用response.getWriter() 和response.getOutputStream()向客户端输出响应体,但可以使用response.setContentType(“text/html;charset=utf-8”) 设置响应头。而在BServlet中可以输出响应体。
请求包含:由两个Servlet共同完成响应体(留头又留体)。同样用上面的例子,AServlet请求包含到BServlet,那么AServlet既可以设置响应头,也可以完成响应体。

12.request和session的区别

1.request

request范围较小一些,只是一个请求。

request对象的生命周期是针对一个客户端(说确切点就是一个浏览器应用程序)的一次请求,当请求完毕之后,request里边的内容也将被释放点 。

简单说就是你在页面上的一个操作,request.getParameter()就是从上一个页面中的url、form中获取参数。

但如果一个request涉及多个类,后面还要取参数,可以用request.setAttribute()和request.getAttribute()。

但是当结果输出之后,request就结束了。

2.session

session可以跨越很多页面。

而session的生命周期也是针对一个客户端,但是却是在别人设置的会话周期内(一般是20-30分钟),session里边的内容将一直存在,即便关闭了这个客户端浏览器 session也不一定会马上释放掉的。

可以理解是客户端同一个IE窗口发出的多个请求。

这之间都可以传递参数,比如很多网站的用户登录都用到了。

java语言写的android系统,用于个人账目管理,课程设计上写的欢迎下载 package moneymanager.moneymanager; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; /* * * 데이터베이스를 관리하는 클래스입니다. * */ public class DBAdapter { private static final String TAG = "NotesDbAdapter"; private DatabaseHelper mDbHelper; private SQLiteDatabase mDb; // 데이터베이스이름과 테블이름들을 정의 private static final String DATABASE_NAME = "MoneyManagerDB"; private static final int DATABASE_VERSION = 2; private static final String DATABASE_SETTING_TABLE = "SettingTbl"; private static final String DATABASE_BADGET_TABLE = "BadgetTbl"; private static final String DATABASE_PAYMENT_TABLE = "PaymentTbl"; // 테블안의 항목들을 정의 public static final String KEY_SETTINGTBL_ID = "ID"; public static final String KEY_SETTINGTBL_NAME = "Name"; public static final String KEY_SETTINGTBL_VALUE = "Value"; public static final String KEY_BADGETTBL_ID = "ID"; public static final String KEY_BADGETTBL_ITEM = "Item"; public static final String KEY_BADGETTBL_MONEY = "Money"; public static final String KEY_PAYMENTTBL_ID = "ID"; public static final String KEY_PAYMENTTBL_BADGETID = "BadgetID"; public static final String KEY_PAYMENTTBL_OUTDATE = "OutDate"; public static final String KEY_PAYMENTTBL_MONEY = "Money"; public static final String KEY_PAYMENTTBL_NOTE = "Note"; private final Context mCtx; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String strCreateTbl; // SettingTbl생성 strCreateTbl = "CREATE TABLE " + DATABASE_SETTING_TABLE + " (" + KEY_SETTINGTBL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_SETTINGTBL_NAME + " TEXT NOT NULL, " + KEY_SETTINGTBL_VALUE + " TEXT NOT NULL);"; db.execSQL(strCreateTbl); // BadgetTbl생성 strCreateTbl = "CREATE TABLE " + DATABASE_BADGET_TABLE + " (" + KEY_BADGETTBL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_BADGETTBL_ITEM + " TEXT NOT NULL, " + KEY_BADGETTBL_MONEY + " INTEGER NOT NULL);"; db.execSQL(strCreateTbl); // PaymentTbl생성 strCreateTbl = "CREATE TABLE " + DATABASE_PAYMENT_TABLE + " (" + KEY_PAYMENTTBL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_PAYMENTTBL_BADGETID + " INTEGER NOT NULL, " + KEY_PAYMENTTBL_OUTDATE + " TEXT NOT NULL, " + KEY_PAYMENTTBL_MONEY + " INTEGER NOT NULL, " + KEY_PAYMENTTBL_NOTE + " TEXT);"; db.execSQL(strCreateTbl); } ......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天蓝_BlueSky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值