这个作业属于哪个课程 | 2020软件工程w班 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 针对原型设计实现疫情统计网页 |
结对学号 | |
作业正文 | .... |
其他参考文献 | 《构建之法》 |
一、仓库链接和代码规范链接
-
仓库链接:https://github.com/pb-xxxx/InfectStatisticWeb
-
代码规范链接:https://github.com/pb-xxxx/InfectStatistic-main/blob/master/221701303/codestyle.md
二、成品展示
三、结对过程
四、设计实现过程
-
后端:
-
后端主要用servlet为控制器,pojo+DAO为逻辑层的javaEE的模式设计,页面显示由前端jsp显示。本来打算用纯前端完成本次作业,但在js读取文件这个模块上遇到了问题,临时改用javaEE的模式。在设计具体的代码前,因为不会爬虫且中途换成了javaEE实现,我先思考了数据库表的存储结构。最后采用省份名为表名的结构,这个决定让我后面的整个代码出现了部分冗余和麻烦,主要原因是在设计完基本的模块准备访问数据库的时候才发现我的mysql版本不支持把表名作为参数传入sql语句里,这个部分的错误花了很多时间来弥补。
-
设计的第一步肯定是先把后端各个模块dao pojo 设计好,在设计实现取数据时还增加了getdefaultdata这个方法,这也是在后面写代码的过程中发现的,第一次载入index.jsp时没办法获得数据,就在jsp的body标签了写了判断参数是否为空的代码块,为空就访问servlet调用getdefaultdata并转发。点击全国地图上的省份跳转到具体省份页面时的处理也类似。这也是整个过程中碰到的比较大的问题
-
然后就是选择具体时间这个功能,设计了dateServlet专门处理用户在两个页面输入提交的日期,调用getxxxxdata(string)方法将用户输入的日期传入,处理请求并转发。
-
-
前端:
-
前端我们使用html+css+jsp实现具体界面设计,由于能力有限没有使用框架等来实现,用单纯的html和css做出具体页面
-
主要分为两个具体视图:全国疫情视图和省份疫情视图
-
JavaScript实现地图显示和折现图,具体使用echart设置,在地图和折现切换中使用jquery来实现显示和隐藏
-
-
五、功能结构图
六、代码说明
1、后端:
-
pojo 省份对象 封装了ip sp 等数据 及对应的set get方法
-
package pojo; public class Province { private int ip; private int ipcount; private int sp; private int spcount; private int cure; private int curecount; private int dead; private int deadcount; public int getip() { return ip; } public void setip(int ip) { this.ip = ip; } public int getipcount() { return ipcount; } public void setipcount(int ipcount) { this.ipcount = ipcount; } public int getsp() { return sp; } public void setsp(int sp) { this.sp = sp; } public int getspcount() { return spcount; } public void setspcount(int spcount) { this.spcount = spcount; } public int getcure() { return cure; } public void setcure(int cure) { this.cure = cure; } public int getcurecount() { return curecount; } public void setcurecount(int curecount) { this.curecount = curecount; } public int getdead() { return dead; } public void setdead(int dead) { this.dead = dead; } public int getdeadcount() { return deadcount; } public void setdeadcount(int deadcount) { this.deadcount = deadcount; } }
-
DAO 接口 default方法日期默认为2020.02.02(主要用于第一次进入jsp网页时)
-
package dao; import pojo.Province; public interface ProvinceDAO { Province getDefaultPceData(); Province getPceData(String date); Province getDefaultNationData(); Province getNationData(String date); }
-
DAO 实现
-
全国页面默认日期 返回pojo对象
-
public Province getDefaultNationData() { String sql = "select * from 全国 where date = '2020.02.02'"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; }
-
全国页面 日期为参数 返回pojo对象
-
@Override public Province getNationData(String date) { // TODO Auto-generated method stub String udate = date; String sql = "select * from 全国 where date = ?"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, udate); rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; }
-
省份实现类似
-
dateServlet 处理两个页面的选择具体日期请求 并带值返回
-
package dao; import pojo.Province; import util.DBUtil; import java.sql.*; public class ProvinceDAOImpl implements ProvinceDAO{ @Override public Province getDefaultNationData() { String sql = "select * from 全国 where date = '2020.02.02'"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; } @Override public Province getNationData(String date) { // TODO Auto-generated method stub String udate = date; String sql = "select * from 全国 where date = ?"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, udate); rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; } @Override public Province getDefaultPceData() { // TODO Auto-generated method stub String sql = "select * from 湖北 where date = '2020.02.02'"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; } @Override public Province getPceData( String date) { // TODO Auto-generated method stub String udate = date; String sql = "select * from 湖北 where date = ?"; Province pce = new Province(); ResultSet rs = null; try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, udate); rs = ps.executeQuery(); while(rs.next()) { int ipnum = rs.getInt("ipcount"); int spnum = rs.getInt("spcount"); int curenum = rs.getInt("curecount"); int deadnum = rs.getInt("deadcount"); pce.setipcount(ipnum); pce.setspcount(spnum); pce.setcurecount(curenum); pce.setdeadcount(deadnum); } } catch (SQLException e) { e.printStackTrace(); } return pce; } }
-
nationServlet 处理全国页面(index.jsp)的第一次加载的请求,并带数据返回
-
package servlet; import java.io.IOException; 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 dao.ProvinceDAO; import dao.ProvinceDAOImpl; import pojo.Province; /** * Servlet implementation class provinServlet */ @WebServlet("/nationServlet") public class nationServlet extends HttpServlet { private ProvinceDAO provinceDAO = new ProvinceDAOImpl(); private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public nationServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub Province nation = getDefaultNationData(); request.setAttribute("nation", nation); request.setAttribute("nationdate", "2020.02.02"); request.getRequestDispatcher("index.jsp").forward(request,response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } private Province getDefaultNationData() { Province pce = provinceDAO.getDefaultNationData(); return pce; } }
-
省份servlet同
-
数据库工具类 封装访问数据库的代码
-
package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBUtil { static String ip = "127.0.0.1"; static int port = 3306; static String database = "疫情统计"; static String encoding = "UTF-8"; static String loginName = "root"; static String password = "wjl6588993"; static boolean isuseSSL= false; static String Timezone= "GMT%2B8"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { String url = String.format("jdbc:mysql://%s:%d/%s?useSSL=%b&serverTimezone=%s&characterEncoding=%s", ip, port, database,isuseSSL,Timezone, encoding); return DriverManager.getConnection(url, loginName, password); } /* 关闭连接的方法 */ public static void close(ResultSet rs, Statement stmt, Connection conn) { try { if (rs != null) rs.close(); } catch (Exception ex) { ex.printStackTrace(); } try { if (stmt != null) stmt.close(); } catch (Exception ex) { ex.printStackTrace(); } try { if (conn != null) conn.close(); } catch (Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) throws SQLException { System.out.println(getConnection()); } }
2、前端:
-
对封面的主要设计
-
科学防护 共渡难关
肺炎疫情实时动态播报
累计确诊
-累计死亡
-累计治愈
-现有确诊
22534现有重症
11234现有疑似
-截止日期:
- 设计疫情地图
-
具体地图实现和折现实现的js代码部分
-
series: [{ name: '确诊', type: 'map', mapType: 'china', roam: false, label: { normal: { show: true //省份名称 }, emphasis: { show: false } }, itemStyle:{ normal:{ borderColor: 'rgba(0, 0, 0, 0.2)' }, emphasis:{ areaColor: '#f30d1d', shadowOffsetX: 0, shadowOffsetY: 0, shadowBlur: 20, borderWidth: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } }, data:mydata //数据 }] };
-
省份点击跳转
china_chart.setOption(option); china_chart.on('click', function (param) { var selected = param.name; if (selected) { switch(selected){ case '北京': location.href = "index_province.html"; break; ... default: break; } } }); function randomData() { return Math.round(Math.random()*500); }
-
-
折现图实现代码
-
xAxis: { type: 'category', data: ['1.27', '1.29', '1.31', '2.2', '2.4', '2.6', '2.8', '2.10', '2.12', '2.14', '2.16', '2.18'], // x轴数据 name: '日期', // x轴名称 // x轴名称样式 nameTextStyle: { fontWeight: 600, fontSize: 18 } }, yAxis: { type: 'value', name: '人数', // y轴名称 // y轴名称样式 nameTextStyle: { fontWeight: 600, fontSize: 18 } },
七、收获和心路历程
221701303:
首先阅读《构建之法》了解到更多在日常中没有注意到的细节和一些代码规范,其中更多的是完成一项项目中最重要的思想,在本次结对中,更多的考验了同伴之间的配合和协调,有很多自己不懂的东西恰好伙伴懂,更好的配合,一起完成这项任务,在其中学会了很多,搭建服务器、前端制作更加了解细节,了解到了更加深入的知识,虽然学会了搭建服务器但是最终由于没有实现云数据库,我的云服务器没有起到他的作用(害....)不过还是很开心完成这项任务的同时学到更多的知识。
221701326:
-
阅读《构建之法》收获很多,从更专业系统的层面了解了代码规范,和完成项目中的思想方法,对我的认知和具体的实践写代码有很大的帮助。这次结对作业的分工让我对结对编程的好处有了更深刻的理解,具体来说,我在css和html部分比较薄弱,很多样式被我设计的不是很友好,队友正好i擅长这部分,我的困难也因此解决。
-
本来打算用纯前端完成本次作业,临时改用javaEE的模式。采用省份名为表名的结构,这个决定让我后面的整个代码出现了部分冗余和麻烦,主要原因是在设计完基本的模块准备访问数据库的时候才发现我的mysql版本不支持把表名作为参数传入sql语句里,这个部分的错误花了很多时间来弥补。这也让我知道前期的准备过程要在现在的程度上更加的充分和细致。才能减少不必要的损失。
八、评价队友
队友超级给力!!!! --------221701303
我的css部分比较弱队友正好擅长于此,这让队友在我心中形象更加高大上,在彼此沟通上也很认真,遇到问题也非常认真百度或者请教他人,最后解决 221701326