基于Hadoop与Spring+ssm框架相关知识开发的浏览统计网站

顺应近年来,科学社会的不断发展,人们对于海量数据的挖掘以及实际运用以及重视,互联网是面向全社会公众信息交流的平台,已经成为了收集信息的最佳最有效率的渠道并成为当前主流。伴随大数据技术的创新与实际应用,进一步为人民进行大数据统计分析提供了极大的便利。

大数据信息的统计分析可为企业决策者提供充实可行的依据支持,例如:通过对于移动APP的下载数据量进行统计分析,可以得出应用程序的受欢迎程序,还可以通过访问的ip编号,区域,时间段,下载方式等,进行下一步更深层次的数据分析,为运营分析与推广决策提供强有力的数据支持。

本项目对于某个网站产生的流量日志数据进行统计分析,可以得出网站的日访问量,从而得出网站的欢迎程度,对于访问网站ip的地区统计分析,可以得出对于此网站,某地区的点击热度,并对其进行实现可视化界面等。

本项目的主要流程为:首先通过提供的ip日志数据,进行数据预处理,并将处理后的数据上传到分布式文件管理系统(HDFS)上,再导入到Hive数据库中,然后使用Navicat工具连接Mysql数据库,并使用Sqoop将数据导出,然后搭建SSM+Spring框架,自定义传导至前端的web接口,使用Tomcat、HTML语言、SQL语言等相关知识进行操作,最后实现数据的最终可视化界面。

数据预处理过程:

  1. 根据源数据的数据字段创建相应的属性变量,部分操作见图2;

图2 建立与源数据字段相对应的属性

(2) 重写toString()方法,使用Hive默认分隔符进行分隔,为后期导入Hive表提供便利、设置初始化方法(详见图3),加载网站需要分析的url分类数据,存储到MapTask的内存中,用来对日志数据进行过滤,如果用户请求的资源是以下列形式,就表示用户请求的是合法资源(详见图4)

图3 重写toString方法

图4 过滤日志数据及存储到MapTask内存

(3)数据预处理后效果展示(见图5)

部分核心代码:

(1)WebLogBean.java
package cn.edu.fjjxu.mr.bean;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class WebLogBean implements Writable {
    private Boolean valid = false;
    private String remote_addr;
    private String remote_user;
    private String time_local;
    private String requset;
    private String status;
    private String body_byes_sent;
    private String http_referer;
    private String http_user_agent;

    public void setBean(boolean valid, String remote_addr,
                        String remote_user, String time_loacl,
                        String requset, String status, String body_byyes_sent,
                        String http_referer, String http_user_agent) {
        this.valid = valid;
        this.remote_addr = remote_addr;
        this.remote_user = remote_user;
        this.time_local = time_loacl;
        this.requset = requset;
        this.status = status;
        this.body_byes_sent = body_byyes_sent;
        this.http_referer = http_referer;
        this.http_user_agent = http_user_agent;
    }

    public Boolean getValid() {
        return valid;
    }

    public void setValid(Boolean valid) {
        this.valid = valid;
    }

    public String getRemote_addr() {
        return remote_addr;
    }

    public void setRemote_addr(String remote_addr) {
        this.remote_addr = remote_addr;
    }

    public String getRemote_user() {
        return remote_user;
    }

    public void setRemote_user(String remote_user) {
        this.remote_user = remote_user;
    }

    public String getTime_local() {
        return time_local;
    }

    public void setTime_local(String time_local) {
        this.time_local = time_local;
    }

    public String getRequset() {
        return requset;
    }

    public void setRequset(String requset) {
        this.requset = requset;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getBody_byes_sent() {
        return body_byes_sent;
    }

    public void setBody_byes_sent(String body_byes_sent) {
        this.body_byes_sent = body_byes_sent;
    }

    public String getHttp_referer() {
        return http_referer;
    }

    public void setHttp_referer(String http_referer) {
        this.http_referer = http_referer;
    }

    public String getHttp_user_agent() {
        return http_user_agent;
    }

    public void setHttp_user_agent(String http_user_agent) {
        this.http_user_agent = http_user_agent;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(this.valid);
        sb.append("\001").append(this.getRemote_addr());
        sb.append("\001").append(this.getRemote_user());
        sb.append("\001").append(this.getTime_local());
        sb.append("\001").append(this.getRequset());
        sb.append("\001").append(this.getStatus());
        sb.append("\001").append(this.getBody_byes_sent());
        sb.append("\001").append(this.getHttp_referer());
        sb.append("\001").append(this.getHttp_user_agent());
        return sb.toString();
    }

    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeBoolean(this.valid);
        dataOutput.writeUTF(null==remote_addr?"":remote_addr);
        dataOutput.writeUTF(null==remote_user?"":remote_user);
        dataOutput.writeUTF(null==time_local?"":time_local);
        dataOutput.writeUTF(null==requset?"":requset);
        dataOutput.writeUTF(null==status?"":status);
        dataOutput.writeUTF(null==body_byes_sent?"":body_byes_sent);
        dataOutput.writeUTF(null==http_referer?"":http_referer);
        dataOutput.writeUTF(null==http_user_agent?"":http_user_agent);
    }

    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.valid = dataInput.readBoolean();
        this.remote_addr = dataInput.readUTF();
        this.remote_user = dataInput.readUTF();
        this.time_local = dataInput.readUTF();
        this.requset = dataInput.readUTF();
        this.status = dataInput.readUTF();
        this.body_byes_sent = dataInput.readUTF();
        this.http_referer = dataInput.readUTF();
        this.http_user_agent = dataInput.readUTF();
    }
}

(2)WebLogParser.java
package cn.itcast.mr.weblog.preprocess;

import cn.itcast.mr.weblog.bean.WebLogBean;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Set;


public class WebLogParser {

	//定义时间格式
	public static SimpleDateFormat df1 = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss", Locale.US);
	public static SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);

	public static WebLogBean parser(String line) {
		WebLogBean webLogBean = new WebLogBean();
		//把一行数据以空格字符切割并存入数组arr中
		String[] arr = line.split(" ");
		//如果数组长度小于等于11,说明这条数据不完整,因此可以忽略这条数据
		if (arr.length > 11) {
			//满足条件的数据逐个赋值给webLogBean对象
			webLogBean.setRemote_addr(arr[0]);
			webLogBean.setRemote_user(arr[1]);
			String time_local = formatDate(arr[3].substring(1));
			if(null==time_local || "".equals(time_local)) time_local="-invalid_time-";
			webLogBean.setTime_local(time_local);
			webLogBean.setRequest(arr[6]);
			webLogBean.setStatus(arr[8]);
			webLogBean.setBody_bytes_sent(arr[9]);
			webLogBean.setHttp_referer(arr[10]);
			//如果useragent元素较多,拼接useragent
			if (arr.length > 12) {
				StringBuilder sb = new StringBuilder();
				for(int i=11;i<arr.length;i++){
					sb.append(arr[i]);
				}
				webLogBean.setHttp_user_agent(sb.toString());
			} else {
				webLogBean.setHttp_user_agent(arr[11]);
			}
			if (Integer.parseInt(webLogBean.getStatus()) >= 400) {// 大于400,HTTP错误
				webLogBean.setValid(false);
			}
			if("-invalid_time-".equals(webLogBean.getTime_local())){
				webLogBean.setValid(false);
			}
		} else {
			webLogBean=null;
		}
		return webLogBean;
	}
	
	//添加标识
	public static void filtStaticResource(WebLogBean bean, Set<String> pages) {
		if (!pages.contains(bean.getRequest())) {
			bean.setValid(false);
		}
	}
	//格式化时间方法
	public static String formatDate(String time_local) {
		try {
			return df2.format(df1.parse(time_local));
		} catch (ParseException e) {
			return null;
		}
	}

}

(3)WeblogPreProcess.java
package cn.itcast.mr.weblog.preprocess;

import cn.itcast.mr.weblog.bean.WebLogBean;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * 处理原始日志,过滤出真实请求数据,转换时间格式,对缺失字段填充默认值,对记录标记valid和invalid
 */
public class WeblogPreProcess {

	public static void main(String[] args) throws Exception {
		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf);
		job.setJarByClass(WeblogPreProcess.class);
		job.setMapperClass(WeblogPreProcessMapper.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(NullWritable.class);
		FileInputFormat.setInputPaths(job, new Path("D:\\HadoopTest\\MapReduce\\WebLog\\input"));
		FileOutputFormat.setOutputPath(job, new Path("D:\\HadoopTest\\MapReduce\\WebLog\\output"));
		job.setNumReduceTasks(0);
		boolean res = job.waitForCompletion(true);
		System.exit(res ? 0 : 1);
	}

	public static class WeblogPreProcessMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
		// 用来存储网站url分类数据
		Set<String> pages = new HashSet<String>();
		Text k = new Text();
		NullWritable v = NullWritable.get();
		/**
		 * 设置初始化方法,加载网站需要分析的url分类数据,存储到MapTask的内存中,用来对日志数据进行过滤
		 * 如果用户请求的资源是以下列形式,就表示用户请求的是合法资源。
		 */
		@Override
		protected void setup(Context context) throws IOException, InterruptedException {
			pages.add("/about");
			pages.add("/black-ip-list/");
			pages.add("/cassandra-clustor/");
			pages.add("/finance-rhive-repurchase/");
			pages.add("/hadoop-family-roadmap/");
			pages.add("/hadoop-hive-intro/");
			pages.add("/hadoop-zookeeper-intro/");
			pages.add("/hadoop-mahout-roadmap/");
		}

		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			//获取一行数据
			String line = value.toString();
			//调用解析类WebLogParser解析日志数据,最后封装为WebLogBean对象
			WebLogBean webLogBean = WebLogParser.parser(line);
			if (webLogBean != null) {
				// 过滤js/图片/css等静态资源
				WebLogParser.filtStaticResource(webLogBean, pages);
				k.set(webLogBean.toString());
				context.write(k, v);
			}
		}
	}
}


    1. 数据分析

数据仓库中的数据分析与数据导出:

(1)插入项目操作所需的数据表,详见图6;

 

图6 hive数据源表

(2)把预处理结果上传到hadoop3:

(3)并在分布式文件管理系统(HDFS)上查看数据的上传情况,如图7所示;

图7  HDFS上传文件内容显示

 

(4)在hive中查看表中的结构以及插入的数据,查询结果如图8、图9、图10所示;

图8 ods_weblog_origin 部分数据

 

图9 dw_pvs_erverdays数据内容

 

图10 dw_avgpv_user_erverdays数据内容

 

(4) 使用Sqoop将hive的dw_avgpv_user_erverdays表导入到Mysql数据库中,导入代码如下;

sqoop export \

  --connect jdbc:mysql://hadoop01:3306/sqoopdb \

  --username root \

  --password 123456 \

  --table t_pv_num \

  --columns

"dw_pvs_everyday,dw_pvs_everyday.month,dw_pvs_everyday.day" \

  --fields-terminated-by '\001' \

  --export-dir /user/hive/warehouse/weblog.db/dw_pvs_everyday

(5)使用Navicat工具连接Mysql数据库,查看所导出的数据表,查看结果如图11所示;

图11 日平均PV量

 

(1)inedex.jsp(最近7天日平均PV量):
				<!-- BEGIN ROW  最近7天日平均PV量-->
				<div class="row">
					<div class="col-lg-6 col-sm-6">
						<section class="panel">
							<div class="panel-body">
								<div id="main1" style="width: 100%; height: 400px;"></div>
								<script type="text/javascript">
									$(document)
											.ready(
													function() {
														var myChart = echarts
																.init(document
																		.getElementById('main1'));
														// 显示标题,图例和空的坐标轴
														myChart
																.setOption({
																	title : {
																		text : '最近7天日平均PV量',
																		subtext : '动态数据'
																	},
																	tooltip : {},
																	legend : {
																		data : [ '日平均PV量' ]
																	},
																	xAxis : {
																		data : []
																	},
																	yAxis : {},
																	series : [ {
																		name : '日平均PV量',
																		type : 'bar',
																		data : []
																	} ]
																});
														//loading 动画
														myChart.showLoading();
														// 异步加载数据
														$.get('http://localhost:8080/avgPvNum').done(function(data) {
															//填入数据
															myChart.setOption({
																xAxis : {
																							data : data.dates
																						},
																						series : [ {
																							// 根据名字对应到相应的系列
																							name : 'PV量',
																							data : data.data
																						} ]
																					});
																			//数据加载完成后再调用 hideLoading 方法隐藏加载动画
																			myChart.hideLoading();
																		});
													});
								</script>

							</div>
						</section>
					</div>

(2)index.jsp(折线图):
<!-- 动态加载数据示例 开始-->
				<div class="row">
					<div class="col-lg-12 col-sm-12">
						<section class="panel">
							<div class="panel-body">
								<div id="main4" style="width: 100%; height: 400px;"></div>
								<script type="text/javascript">
									// 基于准备好的dom,初始化echarts实例
									var myChart4 = echarts.init(document
											.getElementById('main4'));

									// 指定图表的配置项和数据
									option = {
										title : {
											text : '近一周访客数量变化趋势',
											subtext : '动态数据'
										},
										tooltip : {
											trigger : 'axis'
										},
										legend : {
											data : [ '独立访客', '新独立访客' ]
										},
										toolbox : {
											show : true,
											feature : {
												mark : {
													show : true
												},
												dataView : {
													show : true,
													readOnly : false
												},
												magicType : {
													show : true,
													type : [ 'line', 'bar' ]
												},
												restore : {
													show : true
												},
												saveAsImage : {
													show : true
												}
											}
										},
										calculable : true,
										xAxis : [ {
											type : 'category',
											boundaryGap : false,
											data : []
										} ],
										yAxis : [ {
											type : 'value',
											axisLabel : {
												formatter : '{value} 人'
											}
										} ],
										series : [ {
											name : '独立访客',
											type : 'line',
											data : [],
											markPoint : {
												data : [ {
													type : 'max',
													name : '最大值'
												}, {
													type : 'min',
													name : '最小值'
												} ]
											},
											markLine : {
												data : [ {
													type : 'average',
													name : '平均值'
												} ]
											}
										}, {
											name : '新独立访客',
											type : 'line',
											data : [],
											markPoint : {
												data : [ {
													type : 'max',
													name : '最大值'
												}, {
													type : 'min',
													name : '最小值'
												} ]
											},
											markLine : {
												data : [ {
													type : 'average',
													name : '平均值'
												} ]
											}
										} ]
									};

									// 使用刚指定的配置项和数据显示图表。
									myChart4.setOption(option);
									myChart4.showLoading();
									// 异步加载数据
									$.get('http://localhost:8080/flowNum')
											.done(function(data) {
												// 填入数据
												myChart4.setOption({
													xAxis : {
														data : data.dates
													},
													series : [ {
														name : '独立访客',
														data : data.uvs
													}, {
														name : '新独立访客',
														data : data.new_uvs
													} ]
												});
												myChart4.hideLoading();
											});
								</script>
							</div>
						</section>
					</div>
				</div>
				<!-- 动态加载数据示例 结束-->

(3)index.jsp(饼状图):
	</div>
					<div class="col-lg-6 col-sm-6">
						<section class="panel">
							<div class="panel-body">

								<div id="main2" style="width: 600px; height: 400px;"
									align="center"></div>
								<script type="text/javascript">
									// 基于准备好的dom,初始化echarts实例
									var myChart = echarts.init(document
											.getElementById('main2'));

									myChart
											.setOption({
												series : [ {
													name : '访问来源',
													type : 'pie',
													radius : '55%',
													data : [ {
														value : 235,
														name : '视频广告'
													}, {
														value : 274,
														name : '联盟广告'
													}, {
														value : 310,
														name : '邮件营销'
													}, {
														value : 335,
														name : '直接访问'
													}, {
														value : 400,
														name : '搜索引擎'
													} ]
												} ],
												itemStyle : {
													normal : {
														// 阴影的大小
														shadowBlur : 200,
														// 阴影水平方向上的偏移
														shadowOffsetX : 0,
														// 阴影垂直方向上的偏移
														shadowOffsetY : 0,
														// 阴影颜色
														shadowColor : 'rgba(0, 0, 0, 0.5)'
													}
												}
											})
								</script>
							</div>
						</section>
					</div>

				</div>
    1. 数据可视化

SSM+Spring框架实现的数据可视化:

(1)通过IDEA创建相关目标项目,部分代码如图12所示;

图12 SSM+Spring框架部分代码展示

(2)借用Tomcat、HTML语言、SQL语言等相关知识实现目标操作;

 

  • 2013-09-18至2013-09-24网站访问次数总量柱状图

  1. 通过数据来源dw_pvs_everday表获取访问次数总量
  2. hive数据仓库中建立临时表tmp用于存储目标数据
  3. 借助sqoophive中的tmp表导出到Mysql数据库中(如图15所示)

图15 日访问PV总量

 

结果可视化(如图16):

图16  日PV总量图

部分核心代码:

(1)TpvNumMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="cn.itcast.mapper.TpvNumMapper">

  <select id="selectByDate" resultType="cn.itcast.pojo.TpvNum"

         parameterType="String">

         select *

         from t_pv_num

         where dateStr between #{0} and #{1} order by dateStr asc;

  </select>

</mapper>

(2)IndexController.java:

package cn.itcast.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import cn.itcast.service.PvService;

@Controller

public class IndexController {

  @Autowired

  private  PvService pvService;

  @RequestMapping("/index")

  public String showIndex() {

         return "index";

  }

  @RequestMapping(value = "/ PvNum", produces = "application/json;charset=UTF-8")

  @ResponseBody

  public String getChart() {

         System.out.println("获取pv数据..");

         String data = pvService.get PvNumByDates("2013-09-18", "2013-09-24");

         return data;

  }

}

  • 网站访问来源中国地区分布图
  1. 首先根据数据源表清洗出所有的记录的IP插入到hive仓库的临时表中;
  2. 借用sqoop将临时表中的数据导出到Mysql数据库中,如图17所示;

图17 清洗出IP数据表

  1. 使用Python访问IP定位的API接口对Mysql中的IP记录进行位置定位,获取出每个IP对应的位置信息相关操作如图18所示(API接口涉及个人隐私不方便显示);

图18 定位IP位置

  1. 统计中国省份的访问总量并通过自定义SSM框架接口,实现可视化展示到项目页面的操作,具体操作如图19、图20、图21;

图19 自定义框架传导操作1

 

图20 自定义框架传导操作2

 

图21 自定义框架传导操作3

 

结果可视化(如图22、图23):

 

图22 ip归属地区总量图1

图23 ip归属地区总量图2

 

部分核心代码:
(1)IndexController.java:
	@RequestMapping(value = "/LocationPvnum", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getLocationPvnum(){
		System.out.println("获取地区访问数据..");
		String data = lpnService.getTLocationPvNum();
		return data;
	}
}

(2)TLocationPvNumMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.itcast.mapper.TLocationPvNumMapper">

	<select id="selectPvNum" resultType="cn.itcast.pojo.TLocationPvNum"
		parameterType="String">
		select *
		from t_location_pv_num;
	</select>

</mapper>

(3)LocationPvNumToPageBean.java:
package cn.itcast.pojo;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LocationPvNumToPageBean {
    private List<HashMap> datas;

    public List<HashMap> getDatas() {
        return datas;
    }

    public void setDatas(List<HashMap> datas) {
        this.datas = datas;
    }
}

(4)TLocationPvNum.java
package cn.itcast.pojo;

public class TLocationPvNum {

    private String province;
    private Integer num;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }
}

(5)ip定位操作:
import csv

import requests
import pymysql
import time


def get_data():
    # 连接数据库
    db = pymysql.connect(host="hadoop01", user='root', password="123456", database="sqoopdb")

    # 使用cursor()方法创建一个游标对象
    cursor = db.cursor()

    # 使用execute()方法执行SQL语句
    cursor.execute('SELECT * FROM ip_total')

    # 使用fetall()获取全部数据
    data = cursor.fetchall()

    # 打印获取到的数据
    ip = data
    # 关闭游标和数据库的连接
    cursor.close()
    db.close()
    return ip


def get_location(ip):
//此处api地址为个人隐私不方便透露出处,所以进行删除处理
    l_location = list()
    t = 0
    for i in ip:
        t += 1
        if t == 1000:
            print("time sleep!!1")
            t = 0
            time.sleep(10)
            print(l_location)
        try:
            r = requests.get(s + i[0])
            l_location.append(r.text.split(',')[0][8:-1])
        except Exception as e:
            print(e)
    dic = dict()
    for i in l_location:
        dic[i] = l_location.count(i)
    return dic


def write_data(d):
    with open("1.csv", "a", encoding="utf-8", newline='') as csv_file:
        writer = csv.writer(csv_file)
        for key, value in d.items():
            writer.writerow([key, value])


if __name__ == '__main__':
    data = get_data()
    start = time.time()
    write_data(get_location(data))
    end = time.time()
    print(end - start)

  • 网站访问所属地区次数top4饼状图

  1. 根据之前所统计出的地区次数,借助SQL语句查询出数量前四的地区并将剩下的地区访问量进行统计
  2. 根据查询的结果并将其进行可视化操作,最终以饼状图形式展现

结果可视化(如图24):

图24 地区Top4饼状图

 

  • 2013-09-18至2013-09-24访问状态(true/false)可视化

  1. 首先根据数据源,借用mapreduce清洗并统计出每日对应的true、false状态各自的访问数量,预处理结果表数据展示如图25

图25 每日访问状态类型总量

  1. 在SSM框架中自定义传到到web前端的接口,具体实现如图26、图27、图28所示

图26 自定义框架传导操作1

 

图27 自定义框架传导操作2

 

图28 自定义框架传导操作3

 

  1. 以时间为横坐标,状态数量为纵坐标,绘制可视化图形,突出正确错误的访问次数(并提供web前端多种可视化图形展示类型具体如图29、图30所示)

图中虚线表示为平均值,图中红色方框内可以自由切换显示图形!

图29 切换以折线图来体现

 

图30 切换以柱状图来体现

 

 

 

(1)IndexController.java
	@RequestMapping(value = "/TypeNum", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getTypeNum() {
		System.out.println("获取访问状态数据..");
		String data = tyService.getTypeNumByDates("2013-09-18","2013-09-24");
		return data;
	}

(2)TTypeNumMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.itcast.mapper.TTypeNumMapper">

	<select id="selectByDate" resultType="cn.itcast.pojo.TTypeNum"
		parameterType="String">
		select *
		from t_typeNum_everyday
		where dateStr between #{0} and #{1} order by dateStr asc;
	</select>

</mapper>

(3)TTypeNum.java
package cn.itcast.pojo;

public class TTypeNum {
    private String datestr;
    private String true_num;
    private String false_num;
    public String getDatestr() {
        return datestr;
    }

    public void setDatestr(String datestr) {
        this.datestr = datestr;
    }

    public String getTrue_num() {
        return true_num;
    }

    public void setTrue_num(String true_num) {
        this.true_num = true_num;
    }

    public String getFalse_num() {
        return false_num;
    }

    public void setFalse_num(String false_num) {
        this.false_num = false_num;
    }



}

(4)TypeNumToPageBean.java
package cn.itcast.pojo;
public class TypeNumToPageBean {
    private String[] dates;
    private String[] true_nums;
    private String[] false_nums;
    public String[] getDates() {
        return dates;
    }

    public void setDates(String[] dates) {
        this.dates = dates;
    }

    public String[] getTrue_nums() {
        return true_nums;
    }

    public void setTrue_nums(String[] true_nums) {
        this.true_nums = true_nums;
    }

    public String[] getFalse_nums() {
        return false_nums;
    }

    public void setFalse_nums(String[] false_nums) {
        this.false_nums = false_nums;
    }

}

 

最终项目系统页面可视化结果(如图31所示):

图31 项目全局界面

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值