数据可视化是利用计算机图形学和图像处理技术,将数据转换成图形或图像在屏幕上显示出来,从而进行交互处理的理论、方法和技术。数据可视化涉及计算机图形学、图像处理、计算机视觉、计算机辅助设计等多个领域,成为研究数据表示、数据处理、决策分析等一系列问题的综合技术。有效的可视化可以帮助用户分析、推理数据。数据可视化使复杂的数据更容易理解和使用。
招聘网站职位分析可视化系统以JavaWeb为基础搭建,通过SSM(Spring、Springmvc、Mybatis)框架实现后端功能,前端在Jsp中使用Echarts实现可视化展示,前后端的数据交互是通过SpringMVC与AJAX交互实现。
-- 数据库jobdata
create database jobdata charset utf8 collate utf8_general_ci;
-- 职位所在城市的分布表
create table t_city_count(
city varchar(30),
count int(5)
)default charset=utf8;
-- 薪资分布表
create table t_salary_dist(
salary varchar(30),
count int(5)
)default charset=utf8;
-- 福利标签统计表
create table t_company_count(
company varchar(30),
count int(5)
)default charset=utf8;
-- 技能标签统计表
create table t_kill_count(
kills varchar(30),
count int(5)
)default charset=utf8;
需要在
sqoop
的lib
包中添加如下依赖:hive-common-2.3.3.jar
、hive-exec-2.3.3.jar
、mysql-connector-java-5.1.7-bin.jar
# 城市岗位统计表
sqoop export \
--connect jdbc:mysql://node:3306/jobdata?characterEncoding=UTF-8 \
--username root \
--password root \
--table t_city_count \
--columns "city,count" \
--fields-terminated-by ',' \
--export-dir /user/hive/warehouse/jobdata.db/t_city_detail
# 工资分布表
sqoop export \
--connect jdbc:mysql://node:3306/jobdata?characterEncoding=UTF-8 \
--username root \
--password root \
--table t_salary_dist \
--fields-terminated-by ',' \
--export-dir /user/hive/warehouse/jobdata.db/t_salary_detail
# 岗位福利统计表
sqoop export \
--connect jdbc:mysql://node:3306/jobdata?characterEncoding=UTF-8 \
--username root \
--password root \
--table t_company_count \
--fields-terminated-by ',' \
--export-dir /user/hive/warehouse/jobdata.db/t_company_detail
# 岗位技能统计表
sqoop export \
--connect jdbc:mysql://node:3306/jobdata?characterEncoding=UTF-8 \
--username root \
--password root \
--table t_kill_count \
--fields-terminated-by ',' \
--export-dir /user/hive/warehouse/jobdata.db/t_kill_detail
通过
MySQL客户端
工具验证数据是否成功导入MySQL
中。
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
每个基于 MyBatis
的应用都是以一个 SqlSessionFactory
的实例为核心的。SqlSessionFactory
的实例可以通过 SqlSessionFactoryBuilder
获得。而 SqlSessionFactoryBuilder
则可以从 XML
配置文件或一个预先配置的 Configuration
实例来构建出 SqlSessionFactory
实例。
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.43.134:3306/jobdata"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
configuration>
@Test
public void testSqlSessionFactory() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//从 SqlSessionFactory 中获取 SqlSession,相当于JDBC中的Connection
SqlSession session = sqlSessionFactory.openSession();
System.out.println(session); // org.apache.ibatis.session.defaults.DefaultSqlSession@cb5822
}
定义DML SQL语句既可以通过 XML 定义,也可以通过注解定义。我们先看看 XML 定义语句的方式,事实上 MyBatis 提供的所有特性都可以利用基于 XML 的映射语言来实现,这使得 MyBatis 在过去的数年间得以流行。
package org.apache.ssm;
// 数据库表的对象
public class CityCountEntity {
private String city;
private int count;
// 省略 getXxx setXxx toString 方法
}
package org.apache.ssm;
import org.apache.ibatis.annotations.Param;
import java.util.List;
// 接口:只有声明没有实现,专门用于定义规范,具体方法实现交由接口子实现类完成。相当于电脑的USB接口
// 电脑上提供了一个USB插槽,规定了USB的尺寸等,你想使用该功能只需要符合这个规范即可,具体实现由生产公司自己处理
public interface ICityCountMapper {
// 方法的定义只需要确定参数列表和返回值即可,其他的方法实现交由MyBatis去实现,可以是注解也可以是XML
List<CityCountEntity> selectAll();
// 参数注解@Param用于给Mapper文件打标记,方便参数注入
CityCountEntity selectByCount(@Param("num") int count);
}
<mapper namespace="org.apache.ssm.ICityCountMapper">
<select id="selectAll" resultType="org.apache.ssm.CityCountEntity">
select city,count from t_city_count
select>
<select id="selectByCount" parameterType="int" resultType="org.apache.ssm.CityCountEntity">
select city,count from t_city_count where count = #{num}
select>
mapper>
注意:需要把该实现类XML文件加入到主配置文件中进行注册,否则MyBatis找不到实现类,在mybatis-config.xml主配置文件中通过进行注册:
@Test
public void testSqlMapper() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
ICityCountMapper cityCountMapper = session.getMapper(ICityCountMapper.class);
// 查询所有
//List list = cityCountMapper.selectAll();
//list.forEach(System.out::println);
// 根据城市查询
CityCountEntity entity = cityCountMapper.selectByCount(145);
System.out.println(entity);
// 事物管理
// session.commit();
// session.rollback();
session.close();
}
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
注意:使用注解方式依然需要提供Mapper映射文件,只是其中没有具体方式实现而已。如果觉得提供Mapper麻烦也可以使用package指定接口所在位置即可。
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache.ssm.ICityCountMapper=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
DEBUG [main] - ==> Preparing: select city,count from t_city_count where count = ?
DEBUG [main] - ==> Parameters: 145(Integer)
DEBUG [main] - <== Total: 1
CityCountEntity{city='北京', count=145}
如果定义的数据库表对象属性名称和表字段列名不一致,则MyBatis无法正常映射数据到对象,这时候就需要手动指定映射,可以是XML也可以是注解,如下所示。
@Results(id = "userResult", value = {
@Result(property = "id", column = "uid", id = true),
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);
@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
int insertTable3(Name name);
Spring是分层的 Java 应用 full-stack
轻量级开源框架。提供了展现层 SpringMVC和持久层 Spring JDBCTemplate 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。
Spring 以 IOC(Inverse Of Control:反转控制)
和 AOP(Aspect Oriented Programming:面向切面编程)
为内核。
横切关注点
。在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里。问题:在学习MyBatis的时候,我们有一个困扰,就是每次执行SQL操作都需要先获取SqlSessionFacory工厂,通过工厂生产SqlSession去执行。能不能把工厂交给上级,下面那个对象需要工厂,你说一声,我直接送过去给给你,而你自己不需要去维护它???–>Spring IOC容器
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.14.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.14.RELEASEversion>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.6version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
package org.apache.ssm;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper //标注是Mapper,可以省略
public interface ICityCountMapper {
@Select("select * from t_city_count ")
List<CityCountEntity> selectAll();
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.43.134:3306/jobdata" />
<property name="username" value="root" />
<property name="password" value="root" />
bean>
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="druidDataSource" />
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sessionFactory" />
<property name="basePackage" value="org.apache.ssm" />
bean>
beans>
@Test
public void testCityCountMapper(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-context.xml");
// 在IOC容器中取出ICityCountMapper的实现类对象
ICityCountMapper cityCountMapper = context.getBean(ICityCountMapper.class);
List<CityCountEntity> list = cityCountMapper.selectAll();
list.forEach(System.out::println);
}
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
注解 | 说明 | 注解 | 说明 |
---|---|---|---|
@Service |
使用在service层类上用于实例化Bean | @Value |
注入普通属性 , 该属性需要在 IOC 容器中 |
@Repository/@Mapper |
使用在dao层类上用于实例化Bean | @Autowired |
使用在字段上用于根据类型依赖注入 |
@Component |
使用在类上用于实例化Bean | @Bean |
使用在方法上,标注将该方法的返回值存储到 Spring 容器中 |
@ComponentScan |
用于指定 Spring 在初始化容器时要扫描的包。把实例化Bean注解标注的所有类加入到IOC容器中 | ||
@Configuration |
用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解 |
package org.apache.ssm.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //标注当前类是一个配置类,类似于新建一个application-context.xml配置文件
@MapperScan(basePackages = "org.apache.ssm") //扫描Mybatis的Mapper接口
public class ApplicationContextConfig {
@Bean
public DruidDataSource druidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://192.168.43.134:3306/jobdata");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource druidDataSource){ // 通过属性进行自动注入
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(druidDataSource);
return factoryBean;
}
}
@Test
public void testCityCountMapper(){
// 通过注解方式启动IOC容器
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContextConfig.class);
// 在IOC容器中取出ICityCountMapper的实现类对象
ICityCountMapper cityCountMapper = context.getBean(ICityCountMapper.class);
List<CityCountEntity> list = cityCountMapper.selectAll();
list.forEach(System.out::println);
}
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.14.RELEASEversion>
dependency>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationContextConfig.class)
public class TestMain {
@Autowired
private ICityCountMapper cityCountMapper;
@Test
public void testCityCountMapper(){
List<CityCountEntity> list = cityCountMapper.selectAll();
list.forEach(System.out::println);
}
}
Spring Web MVC是基于Servlet API构建的原始Web框架,并且从一开始就已包含在Spring框架中。正式名称“ Spring Web MVC”,但它通常被称为“ Spring MVC”。
Spring MVC围绕前端控制器模式进行设计Servlet
,在Servlet 3.0+环境中,可以选择以编程方式配置Servlet容器。通过重写AbstractDispatcherServletInitializer
的抽象命名方法来指定servlet映射和DispatcherServlet
配置,轻松地进行注册 。
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.14.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.2version>
<configuration>
<port>80port>
<path>/path>
<uriEncoding>UTF-8uriEncoding>
configuration>
plugin>
plugins>
build>
@Controller // 标注是一个控制器类
public class HelloController {
@ResponseBody // 标注返回JSON数据
@GetMapping("/hello") // 请求映射
public String hello(){
return "Hello Spring MVC~"; // 响应数据
}
}
@Configuration
@EnableWebMvc // 开启SpringMVC默认配置
@ComponentScan("org.apache.ssm") // 扫描所有@Controller注解加入到IOC容器中
public class ApplicationMvcConfig {
}
使用代码的形式替代
web.xml
配置
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{ApplicationMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.14.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.40version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.14.RELEASEversion>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.6version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.20version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.2version>
<configuration>
<port>80port>
<path>/path>
<uriEncoding>UTF-8uriEncoding>
configuration>
plugin>
plugins>
build>
@Configuration
@MapperScan(basePackages = "org.apache.ssm")
public class ApplicationContextConfig {
@Bean
public DruidDataSource druidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://192.168.43.134:3306/jobdata");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource druidDataSource){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(druidDataSource);
return factoryBean;
}
}
@Configuration
@EnableWebMvc
@ComponentScan("org.apache.ssm")
public class ApplicationWebMvcConfig implements WebMvcConfigurer {
}
public class WebContextLoaderConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
//Spring容器,相当于加载 application-context.xml
return new Class[]{ApplicationContextConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
//servletContext, 相当于加载 application-mvc.xml
return new Class[]{ApplicationWebMvcConfig.class};
}
//servlet --> url-mapping
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
// 数据库表的对象
public class CityCountEntity {
private String city;
private int count;
public CityCountEntity() {}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "CityCountEntity{" +
"city='" + city + '\'' +
", count=" + count +
'}';
}
}
@Mapper
public interface ICityCountMapper {
@Select("select * from t_city_count ")
List<CityCountEntity> selectAll();
}
@RestController
public class CityCountController {
@Autowired
private ICityCountMapper cityCountMapper; // 这里工具会报错,不用管
@GetMapping("/list")
public List<CityCountEntity> hello(){
return cityCountMapper.selectAll();
}
}
下一章使用SpringBoot的方式来替代SSM的繁琐配置,并使用ECharts可视化工具进行数据图表呈现