电商小学期 - 智能家居网站结项报告

前言:

「  Design & Build 」

        三个专业三个方向,共同完成一个项目,分别为:

        物联网   数据库的搭建及管理员相关

        电管      硬件设施的实现

        电商      用户方面的前后端

        在本次项目开发中,自身经历了从0到对前后端的基本完备了解与操作,以此记录一下长达一个月的开发流程。包括自己对于项目开发的一些理解和我遇到的问题及思考。

        提前说明:在小学期之前,本人只有JavaEE的基础,对于web开发,网络协议,css,JavaScript等等没有任何了解,项目结束之后也才刚开始系统的学习相关知识,所以一些描述较为个人并不专业。

项目简介(电商方向):

       

        要求开发Web应用程序

主要功能包括:

1. 与数据访问软件通信并检索/发送必要的信息。

2. 客户注册与登录

3. 显示家庭信息的当前状态与摘要(例如室内外温度的最低和最高时间段,设备的开关次数等)

更多功能包括但不限于:

1. 监测到任何欲动或任何窗户/门打开以供入室警报

2. 自主设计

项目理解:

        与之前的C语言小学期一样,本质依然是对数据的操作,底层在于增删改查,上层在于显示。

        只不过这次我们需要将数据存入数据库,这就涉及到数据库的设计,链接,数据规范等等。以及数据的显示从cmd变为web,这就涉及数据与网站的交互传输。这些为后端。

        而关于数据怎么在web上面显示,这是前端。

项目开发

1.关键字

操作系统:MacOS

环境:IDEA(2021.2.1),MyEclipse ,HbuilderX

服务器:Tomcat(9.0.52)

后端:Java (1.8.0_221)

前端:Jsp,Html,Javascript,css

2.框架简介

 

 这里根据项目目录来介绍,左边为后端,右边为前端。

首先看左边

lib:jar包

src:后端的java文件

DAO:接口类,内部的Impl为对应的接口实现类

Email : 因为我在网页中添加了发送邮件的功能,所以这里建一个文件夹来存放相关函数

Entity :项目中类的集合,比如用户类,设备类,里面定义好了自己的属性,即他的数据应该如何存放,从而与数据库里的table进行交互

Servelt :里面的类全部extends HttpSevlet,即与jsp网页实现交互,进行数据传输的类

util :工具包,存放比如数据库连接类等

target:这个放在下面说,与IDEA的artifacts相关

右边:

html:html会定义页面的内容,比如在html里写入一个button,那么打开网页就回出现一个button。

css :css的作用为美化页面,比如你可以定义jsp和html网页中组件的颜色,样式,排版从而让他们更好看,比如button等等。

js :JavaScript作用为控制一些页面的行为,利用定义好的js函数,你可以直接在网页上实现一些操作,比如点击一个button,他的颜色发生改变。

images:需要在网页上显示的图片组件

webfonts:因为pc端之间的不同,所以显示组件肯定会有所不同,而webfonts里面的组件发布在网络上这就可以让pc统一访问来显示,比如字体。

assets:也是css和js

jsp:可以理解为html+java代码。jsp允许写入一些java代码从而进行数据的传输(即上面提到的Servlet类)。但是因为jsp的存在,这个项目并不能说成前后端分离的开发。

(tip:关于jsp和html的区别)

你可以直接将html代码复制到jsp里,然后加上jsp的开头即可。但是html是可以直接打开的,而jsp需要部署到服务器才能打开。这个也好理解,因为jsp允许写入java代码,来从后台读取数值,如果不发到服务器上便没办法传输这些数据,那么自然也就打不开。所以在开发前端过程中,你可以先利用html进行内部组件,css和js的调整来使得页面更加美观。页面调整完备后复制进jsp里,然后添加java代码进行相应的操作。这样效率较高,因为每次部署服务器都需要时间。

WEB-INF

 这个文件夹在创建web项目的时候自动生成,包括里面的web.xml。在配置环境的过程中,网上的教程都让在该目录下新建一个classes,来存放.java编译后的class,lib依然是需要的jar包。关于web.xml的作用,与之前提过的jsp与HttpServlet继承类之间的对应关系有关,我们需要把之间的映射关系写入这样才能搭建起联系。

3.开发流程

当了解完以上框架之后,我们清楚了一个完整的web项目内应该有什么,那么应该如何从0开始。

在我最开始的时候,这些我全部都不知道,只是在课上老师给了个demo,是登录验证,连接了数据库以得到用户信息,但是demo的框架在开发过程中一直没变。

随后我又找到几个完整项目的代码,包括前后端。

最后总结出来web项目的开发流程如下:

1. 首先根据需求建立数据库,并且构建好数据库规范,包括命名以及数据库范式。这确保数据的存取规范,而成功的数据库是可以避免很多SQLExeption的。

2. 根据数据库的table内的entity和attributes建立Entity类,统一命名及数据结构。比如用户类,我们就要统一用户变量,比如Id,邮箱,密码等等。(这个我在开发后期改了好几次,就是因为开始没有定义完善,以及当你定义完成员变量后,IDEA等所有主流IDE是支持自动generate getter和setter的。请一定要用自动生成而不是自己写,这样的命名较为规范。)

package Entity;

public class User {
    private int userNo;
    private String userEmail;
    private String FName;
    private String IName;
    private String password;
    private int familyNo;

    public int getUserNo() {
        return userNo;
    }

    public void setUserNo(int userNo) {

        this.userNo = userNo;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public String getFName() {
        return FName;
    }

    public void setFName(String FName) {
        this.FName = FName;
    }

    public String getIName() {
        return IName;
    }

    public void setIName(String IName) {
        this.IName = IName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getFamilyNo() {
        return familyNo;
    }

    public void setFamilyNo(int familyNo) {
        this.familyNo = familyNo;
    }
}

3. 然后我们需要与数据库进行连接 ,这里需要导入jdbc的jar包到lib里,然后配置好端口号等等,并且在util包内写好连接类,这里详细操作后续会说。

package util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnect {
    private final String DBDRIVER = "com.mysql.cj.jdbc.Driver" ;
    private final String DBURL = "jdbc:mysql://localhost/smarthome?useSSL=false&serverTimezone=UTC" ;
    private final String DBUSER = "root" ;
    private final String DBPASSWORD = "11111111" ;
    public Connection conn = null ;

    public DBConnect(){
        try{
            Class.forName(DBDRIVER) ;//指定连接类型
            this.conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ;//获取连接

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public Connection getConnection() {
        return this.conn;
    }

    //关闭数据库连接
    public void close(){
        try{
            this.conn.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
    }
}

4. 连接完成后,便需要通过Java来对数据库进行操作,而关于需要如何操作,先在接口类中定义好。 比如我需要用户登录,用户注册,用户注销等等。

package DAO;

import Entity.User;

public interface UserDAO {
    public User userLogin(User user) throws Exception;
    public int userLogout(User user) throws Exception;
    public int userRegister(User user) throws Exception;
    public int findEmail(String email) throws Exception;
    public int userChange_password(User user) throws Exception;
}

5. 然后我们可以去Impl去具体完成接口,比如用户登录,我们需要去数据库查询账户与密码是否对应。而这个操作的本质其实就是增删改查中的查,用户注册就是增,用户注销就是删,以此类推,而这四种操作方式基本都一个模版,所以代码基本相似。但是功能是跟着需求走的,你需要通过SQL来找到你想要的数据。

public class UserDAOImpl implements UserDAO {
    String sql= null ;
    PreparedStatement pstmt = null;
    DBConnect dbc = null ;

    @Override
    public User userLogin(User user) throws Exception {
        int flag = 0;
        User tempUser = null;
        try {
            sql="SELECT * FROM User WHERE userNo=? OR userEmail=? AND password=?";
            dbc= new DBConnect();
            pstmt = dbc.getConnection().prepareStatement(sql);
            pstmt.setInt(1, user.getUserNo());
            pstmt.setString(2, user.getUserEmail());
            pstmt.setString(3,user.getPassword());
            ResultSet rs=pstmt.executeQuery();
            if(rs.next()) {
                tempUser = new User();
                tempUser.setUserNo(rs.getInt("userNo"));
                tempUser.setUserEmail(rs.getString("userEmail"));
                tempUser.setFName(rs.getString("FName"));
                tempUser.setIName(rs.getString("IName"));
                tempUser.setPassword(rs.getString("password"));
                tempUser.setFamilyNo(rs.getInt("Family_familyNo"));
            }
            rs.close();
            pstmt.close();
        }catch(SQLException e) {
            e.printStackTrace();
        }finally {
            dbc.close();
        }
        return tempUser;
    }
}

 6. 我们根据账号密码从数据库得到相关信息后,我们需要从网站上得到用户输入的账号密码,那么就需要去jsp网页中添加输入的窗口,这里因为 以及添加了css样式所以不太好阅读,总之就是两个input框。这里需要定义好input的name值,因为表单转发后,servlet需要通过name来获取attributes的值。

<!--/Login-->
<div class="modal fade" id="exampleModalCenter2" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header text-center">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div class="login px-4 mx-auto mw-100">
                    <h5 class="text-center mb-4">Login Now</h5>
                    <form id="form_login" action="UserLogin" method="post">
                        <div class="form-group">
                            <label class="mb-2">userNo or Email address</label>
                            <label for="exampleInputEmail1"></label><input type="text" class="form-control" id="exampleInputEmail1" name="idOrEmail" aria-describedby="emailHelp" placeholder="" value="${idOrEmail}" required="">
                            <small id="emailHelp" class="form-text text-muted">We'll never share your information with anyone else.</small>
                        </div>
                        <div class="form-group">
                            <label class="mb-2">Password</label>
                            <label for="exampleInputPassword1"></label><input type="password" class="form-control" id="exampleInputPassword1" name="password" placeholder="" required="">
                        </div>
                        <button type="submit" id="loginBtn" class="btn btn-primary submit mt-2">Sign In</button>
                        <a style="color: #e2a0a0"> ${errorMsg_log} </a>
                        <div class="text-right pb-4">
                            <a href="EmailCode.jsp" data-toggle="modal2" data-target="#exampleModalCenter" > Forgot password </a>
                            <span style="color: #8c9398"> | </span>
                            <a href="userLogin.jsp" data-toggle="modal2" data-target="#exampleModalCenter" >  Sign up</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
<!--//Login-->

 7.然后我们需要在段jsp代码中填入一个form标签并为其添加action与method。在上面这张图中的form的action是UserLogin,method是post。其作用是当用户输入完账号密码之后,点击摁钮,网站会将这些数据以表单的形式提交,然后根据action的url去之前提到的web.xml进行对应来转发表单数据到指定的servelt类中。这里的welcome-file-list可以理解为打开的第一个页面,下面的servlet与servlet-mapping必须是成对出现的。servlet-name上下一致,为了方便阅读一般都定义成相应的java文件名,当然也可以写成别的。servlet-class就是form转发表单所到的类,url-patten就是上面提到的form的action,当然这个命名也是自己定义的。这段代码的意义就是用户的登录信息通过为UserLogin的action被转发到UserServlet这个类中进行操作。

    <welcome-file-list>
        <welcome-file>/userLogin.jsp</welcome-file>
    </welcome-file-list>



    <servlet>
        <servlet-name>UserLoginServlet</servlet-name>
        <servlet-class>Servlet.UserLoginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>UserLoginServlet</servlet-name>
        <url-pattern>/UserLogin</url-pattern>
    </servlet-mapping>

 8. 其实可以将Servlet类理解成那个连接web上传来的数据与数据库内数据进行交互的地方,这是一个连接口,比如在下面这段代码中我从表单中读取出了账号密码,然后去上面写好的DAOImpl函数去数据库进行查询看是否存在这个用户,如果存在则跳转到登录成功界面,失败则重新输入。当然我这段代码里还混合了查询家庭设备并传给web端。

package Servlet;

import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import DAO.FamilyDAO;
import DAO.HwEDAO;
import DAO.Impl.FamilyDAOImpl;
import DAO.Impl.HwEDAOImpl;
import DAO.UserDAO;
import DAO.Impl.UserDAOImpl;
import Entity.HandwareEquipment;
import Entity.User;

public class UserLoginServlet extends HttpServlet{
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException{
    }

    public void doPost(HttpServletRequest req,HttpServletResponse res)
            throws IOException, ServletException{
        User user = new User();
        String idOrEmail = req.getParameter("idOrEmail");
        String password = req.getParameter("password");
        FamilyDAO familyDao = new FamilyDAOImpl();
        HwEDAO hwedao=new HwEDAOImpl();
        List<HandwareEquipment> result_list1 = null;
        List<User> result_list2 = null;
        int total=0;
        int humidity=0;
        int daw=0;
        int brightness=0;

        if(idOrEmail.contains("@")){
            user.setUserEmail(idOrEmail);
            user.setUserNo(-1);
        }
        else{
            user.setUserNo(Integer.parseInt(idOrEmail));
            user.setUserEmail("-1");
        }

        user.setPassword(password);

        UserDAO dao = new UserDAOImpl();
        User tempUser = null;

        try {
            tempUser =  dao.userLogin(user);
        }catch(Exception e) {
            e.printStackTrace();
        }

        if(tempUser!=null) {
            int familyNo=tempUser.getFamilyNo();
            try{
                total=hwedao.countTotal(familyNo);
                humidity=hwedao.countHum(familyNo);
                daw=hwedao.countDaW(familyNo);
                brightness=hwedao.countBri(familyNo);
                result_list1 = familyDao.queryHwE(familyNo);
                result_list2 = familyDao.queryUser(familyNo);
            }catch (Exception e){
                e.printStackTrace();
            }

            HttpSession session = req.getSession();
            session.setAttribute("userNo", user.getUserNo());
            session.setAttribute("FName",tempUser.getFName());
            session.setAttribute("IName",tempUser.getIName());
            session.setAttribute("familyNo",tempUser.getFamilyNo());


            if(result_list1!=null ||result_list2!=null) {
                session.setAttribute("HwE_List", result_list1);
                session.setAttribute("User_List",result_list2);
                session.setAttribute("Total",total);
                session.setAttribute("Humidity",humidity);
                session.setAttribute("DaW",daw);
                session.setAttribute("Brightness",brightness);
                req.setAttribute("successMsg_homepage", "Please check the following information!");
                res.sendRedirect("./Homepage.jsp");
            }
            else {
                req.setAttribute("errorMsg_homepage", "No result in Database");
                res.sendRedirect("./Homepage.jsp");
            }
        }
        else {
            req.setAttribute("errorMsg_log", "Error! Please try again!");
            req.setAttribute("idOrEmail", idOrEmail);
            req.getRequestDispatcher("./userLogin.jsp").forward(req, res);
        }
    }
}

 9.然后web收到信息后就会跳转到对应界面,我这里的后端逻辑为查询到用户匹配信息后会查到相应的家庭Id,然后进一步查询到家庭内设备信息,然后将这些数据打印出来。

 

 

10. 以上就是关于用户登录的整个开发流程,以此类推可以写出其他功能比如用户注册,设备查询等等。本质区别都在于对数据的操作。等这些功能实现后,就可以进行花里胡哨的操作了。因为我也同是负责了前端开发有些忙不过来,而我也没有系统的学过前端语言。于是就找了几个模版自己在上面修改。通过调整css里的配色及布局以达到自己想要的效果,增添一些js比如输入格式判断,也可以在后台添加一些花哨,我自己加了一个邮箱验证码的功能。

总之前端其实很简单,因为你可以看到<div>内是页面组件,而你只需要将你需要的组件替换掉模版内的组件,然后添加你自己的form,将name值全部定义好,这样就可以与后端连接起来。其实一般前端的代码都比较长,我找的模版大概六七千行,但其实比较有条理与逻辑,组件与组件之间是分开的。可以边看网页边看代码,耐着性子看一遍就知道怎么去修改。而且Chrome有Developer Tool,使得阅读源码更加方便。

4.开发中的问题(后续有空更)

- IDEA+Tomcat+JavaWEB 开发环境配置

- IDEA Artifacts 配置问题及报错 Couldn't copy ... to ...

- IDEA JAVA MySQL 连接

- Java Mail的实现

- 如何在JSP与后端传值及出现的NullPointerException等一系列问题

- HTML网页导入CSS和JS的路径问题

- 数据库内数据实时更新到页面上(WebSocket,Ajax两种方式)

结语

码字过程中又回顾了一下这几个月断断续续的开发过程,感谢自己硬着头皮接下来这么多活,不然其实也学不到这些东西。

但其实作为Web开发来说,上面这些技术大部分已经落后于时代,尤其是jsp。而关于为什么学习这些我也不知道,但是这个过程确实让我了解到一个网站的搭建。

我在开头说学校的课程安排并不合理,是因为我觉得,在只学了数据库与Java的情况下,就直接塞给这种任务。虽然是可以完成的,但在这个过程中磕磕绊绊,许多东西一知半解的做下来。而互联网协议与Socket编程等这些技术居然是安排在小学期之后。

如果先修过这些相关技术,那么开发中对于代码的理解会更加深刻,而不仅仅是从别人的代码复制过来强行阅读理解,虽然学会了,但本质不一样。

最后感谢在我开发过程中的五月天,周杰伦,林俊杰等,排名不分先后。

感谢自己亲手敲出的上万行代码

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值