1. 简介
1.1 源起
我是星际2的忠实玩家。星际2原本有一个国服的天梯排行榜网站,也是由一位热心玩家写的。但是数据已经很久没有更新了。
所以星际2的国服天梯排行榜就成为了我心里想要完成的项目之一。
作为一个计算机专业的学生,我希望自己拥有制作网站的能力。同时这个暑假我参加了java web的培训(然而4天的培训并没有什么卵用,只是让我知道了做一个网站需要用什么工具以及大体的思路)。
那既然参加了培训,不如就做点东西出来吧。于是我决定在这个暑假开始写这个网站。
1.2 项目简介
最终效果可见:SC2Rank
这是一个星际争霸2的天梯玩家排行榜,可以查看天梯中所有玩家的组别、分数、胜率等等信息。可以按组别查询、还可以按玩家名字搜索玩家。
目前玩家数据还是手动更新。
1.3 项目环境
- JDK 8
- Maven 3.0.5
- Mysql 5.6
- Tomcat 8.5
- IDE: IntelliJ IDEA 2016.2.2
- SSM版本:
- Spring version: 4.3.2.RELEASE
- mybatis version: 3.4.1
- mybatis-spring: 1.3.0
2. 数据获取
2.1 暴雪api
星际2玩家天梯数据可以从暴雪官方提供的api获取。
BattleNetAPI
首先需要注册一个账号,得到一个Key,有了这个Key才可以使用暴雪api。
暴雪的接口提供了不同服务器的星际2数据,目前我只收集国服的数据。
查看API docs的时候需要挂vpn,然后可以看到每个接口需要访问的网址形式。
访问以后可以获得json对象,加以处理即可获得玩家数据。
但是暴雪api并不人性化。
它没有办法直接获得所有玩家的数据,只有有了玩家数字ID和名称以后才能查玩家数据,而如何获得玩家ID和名称呢?
此外还能通过天梯ID获取该天梯中的玩家。而天梯ID又无从取得。
幸好天梯ID是按照天梯创建时间来排序的,于是我可以按顺序一个一个试天梯ID,如果有这个天梯,那就把这个天梯ID存到数据库。
最后从天梯数据库中取出天梯ID,访问天梯api获得玩家的信息。
2.2 程序处理
一开始想用java去获取数据放入数据库。然后发现自己java水平太菜,用java处理json十分困难。
卡了一阵子之后还是用python来吧……
经过实践发现python比java不知道方便到哪里去了……java去死吧
代码先不贴了,写的一坨,往后还会优化。在github里可以找到。
贴一下数据库形式:
ladder:isCurrent表示是否是当前赛季的天梯
player:
3. 网站构建
3.1 构建基础
搭建这个SSM环境(Spring+SpringMVC+MyBatis)花了我好多天的时间……甚至一度想要放弃。
网上教程倒是很多,但是按照每个教程配下来好像都有错啊……
而且一开始也对SSM没什么了解,依葫芦画瓢。中间有一点出错就错了,而且还不知道错误在哪里。
最后经历了多天找bug和重做之后终于搭建起了SSM框架。
这里借鉴了两篇博文
Spring+Mybatis+SpringMVC+Maven+MySql搭建实例
IntelliJ IDEA + Maven + SpringMVC + Mybatis+ 整合 + 实例代码
3.2 网站构建
3.2.1 新建Maven项目
首先要新建一个Maven webapp项目,输入groupID和artifactID。这里idea自带maven3,可以直接创建maven项目。
然后修改pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.scarb.sc2rank</groupId>
<artifactId>sc2rank</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>ssm Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<!-- spring版本号 -->
<spring.version>4.3.2.RELEASE</spring.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.7.21</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<!-- junit版本号 -->
<junit.version>4.12</junit.version>
<!-- mybatis版本号 -->
<mybatis.version>3.4.1</mybatis.version>
</properties>
<dependencies>
<!-- 添加Spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--单元测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 日志文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!--spring单元测试依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>7.0.56</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>7.0.57</version>
<scope>provided</scope>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
<!--json lib-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.12.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.10.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.17</version>
</dependency>
<!--validator-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.1.Final</version>
</dependency>
</dependencies>
<build>
<finalName>SC2RankCN</finalName>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
等待idea自动下载所需要的包
包含了SpringMVC mybatis 以及他们的连接器,还有一些其他所用到的包
3.2.2 使用Mybatis-generator
先上一张文件目录:
Mybatis-generator可以根据数据库中表的类型自动生成符合mybatis规范的Mapper和model、dao文件。
可以看到pom.xml的plugin里面以及引入了该插件
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
然后在resources下新建一个
generatorConfig.xml
并根据目录和数据库进行配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<classPathEntry
location="C:\Users\scarb\.m2\repository\mysql\mysql-connector-java\5.1.39\mysql-connector-java-5.1.39.jar"/>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="false"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<!--<jdbcConnection driverClass="${jdbc.driver}"-->
<!--connectionURL="${jdbc.url}"-->
<!--userId="${jdbc.username}"-->
<!--password="${jdbc.password}">-->
<!--</jdbcConnection>-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/sc2rank?characterEncoding=UTF-8"
userId="root"
password="密码已隐去">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.scarb.model"
targetProject="src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="mapper"
targetProject="src\main\resources">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.scarb.dao"
targetProject="src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<!-- 指定数据库表 -->
<!--不生产Example文件-->
<table schema="general" tableName="ladder" domainObjectName="Ladder"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"></table>
<table schema="general" tableName="player" domainObjectName="Player"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
参考博客:
Mybatis 自动生成代码
然后用idea打开maven Projects 面板,找到mybatis-generator 运行。
之后会创建model、dao和Mapper
3.2.3 配置整个项目
java被称为配置之王,但是对于一知半解的我来说简直是一个噩梦。
按照教程尝试无数次之后终于配置成功了。下面是resources下的目录:
按照图中目录创建文件
mybatis-config.xml
其中配置了PageHelper,用于利用mybatis分页
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
<!-- 和startPage中的pageNum效果一样-->
<property name="offsetAsPageNum" value="true"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
<property name="rowBoundsWithCount" value="true"/>
<!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
<!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
<property name="pageSizeZero" value="true"/>
<!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
<property name="reasonable" value="false"/>
<!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
<!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
<!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 -->
<!-- 不理解该含义的前提下,不要随便复制该配置 -->
<property name="params" value="pageNum=start;pageSize=limit;"/>
</plugin>
</plugins>
<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://localhost:3306/sc2rank?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="621374as"/>
</dataSource>
</environment>
</environments>
<!--删除Mybatis.xml中的<mappers>标签所有内容。因为如果user-mapper.xml与namespace的接口在同一路径下,就不需要在mybaits.xml中再进行配置了。-->
<!--<mappers>-->
<!--<mapper resource="mapper/LadderMapper.xml"/>-->
<!--<mapper resource="mapper/PlayerMapper.xml"/>-->
<!--</mappers>-->
</configuration>
jdbc.properties
jdbc_driverClassName=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/sc2rank?useUnicode=true&characterEncoding=UTF-8
jdbc_username=root
jdbc_password=密码已隐去
app-context.xml
全称application context,app环境
app-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册-->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
</bean>
<!-- 引入jdbc配置文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/*.properties</value>
<!--要是有多个配置文件,只需在这里继续添加即可 -->
</list>
</property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--使用properties来配置-->
<property name="driverClassName">
<value>${jdbc_driverClassName}</value>
</property>
<property name="url">
<value>${jdbc_url}</value>
</property>
<property name="username">
<value>${jdbc_username}</value>
</property>
<property name="password">
<value>${jdbc_password}</value>
</property>
</bean>
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.scarb.service">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 激活annotation功能 -->
<context:annotation-config />
<!-- 激活annotation功能 -->
<context:spring-configured />
<!-- 类型转换及数据格式化 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
<!-- 自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,这样就不用一个一个手动配置Mpper的映射了,只要Mapper接口类和Mapper映射文件对应起来就可以了。 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage"
value="com.scarb.dao" />
</bean>
<!-- 配置Mybatis的文件 ,mapperLocations配置**Mapper.xml文件位置,configLocation配置mybatis-config文件位置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
<!-- <property name="typeAliasesPackage" value="com.tiantian.ckeditor.model"
/> -->
</bean>
</beans>
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 扫描controller(controller层注入) -->
<context:component-scan base-package="com.scarb.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<!-- 会自动注册了validator ConversionService -->
<mvc:annotation-driven validator="validator" conversion-service="conversionService" content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="true">
<!-- StringHttpMessageConverter编码为UTF-8,防止乱码 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
<property name = "supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text"/>
<constructor-arg index="1" value="plain"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="*"/>
<constructor-arg index="1" value="*"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<!--<property name="serializerFeature">-->
<!--这个地方加上这个功能吧,能自己配置一些东西,比如时间的格式化,null输出""等等-->
<!--</property>-->
</bean>
</mvc:message-converters>
<mvc:argument-resolvers>
<bean class="org.springframework.data.web.PageableHandlerMethodArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<!-- 内容协商管理器 -->
<!--1、首先检查路径扩展名(如my.pdf);2、其次检查Parameter(如my?format=pdf);3、检查Accept Header-->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
<property name="favorPathExtension" value="true"/>
<!-- 用于开启 /userinfo/123?format=json 的支持 -->
<property name="favorParameter" value="true"/>
<property name="parameterName" value="format"/>
<!-- 是否忽略Accept Header -->
<property name="ignoreAcceptHeader" value="false"/>
<property name="mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 -->
<value>
json=app-context/json
xml=app-context/xml
html=text/html
</value>
</property>
<!-- 默认的content type -->
<property name="defaultContentType" value="text/html"/>
</bean>
<!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 -->
<mvc:default-servlet-handler />
<!-- 静态资源映射 -->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
<mvc:resources mapping="/css/**" location="/WEB-INF/css/"/>
<mvc:resources mapping="/images/**" location="/WEB-INF/images/"/>
<mvc:resources mapping="/js/**" location="/WEB-INF/js/"/>
<!--<mvc:resources mapping="/images/**" location="/WEB-INF/images"/>-->
<!-- 对模型视图添加前后缀 -->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp" />
</bean>
<!--<!– 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 –>-->
<!--<bean id="multipartResolver"-->
<!--class="org.springframework.web.multipart.commons.CommonsMultipartResolver">-->
<!--<!– 默认编码 –>-->
<!--<property name="defaultEncoding" value="utf-8" />-->
<!--<!– 文件大小最大值 –>-->
<!--<property name="maxUploadSize" value="10485760000" />-->
<!--<!– 内存中的最大值 –>-->
<!--<property name="maxInMemorySize" value="40960" />-->
<!--</bean>-->
</beans>
log4j.properties
log4j配置,用于打印日志
log4j.rootLogger=DEBUG,Console,Stdout
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.appender.Stdout = org.apache.log4j.DailyRollingFileAppender
log4j.appender.Stdout.File = F://logs/sc2rank/log.log
log4j.appender.Stdout.Append = true
log4j.appender.Stdout.Threshold = DEBUG
log4j.appender.Stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Archetype Created Web Application</display-name>
<!-- 起始欢迎界面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 读取spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-context.xml</param-value>
</context-param>
<!--<!– 设计路径变量值 –>-->
<!--<context-param>-->
<!--<param-name>webAppRootKey</param-name>-->
<!--<param-value>springmvc.root</param-value>-->
<!--</context-param>-->
<!-- springMVC核心配置 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--spingMVC的配置路径 -->
<param-value>classpath:springmvc/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 拦截设置 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring字符集过滤器 -->
<filter>
<filter-name>SpringEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SpringEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 日志记录 -->
<context-param>
<!-- 日志配置文件路径 -->
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<!-- 日志页面的刷新间隔 -->
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--<!– 错误跳转页面 –>-->
<!--<error-page>-->
<!--<!– 路径不正确 –>-->
<!--<error-code>404</error-code>-->
<!--<location>/WEB-INF/errorpage/404.jsp</location>-->
<!--</error-page>-->
<!--<error-page>-->
<!--<!– 没有访问权限,访问被禁止 –>-->
<!--<error-code>405</error-code>-->
<!--<location>/WEB-INF/errorpage/405.jsp</location>-->
<!--</error-page>-->
<!--<error-page>-->
<!--<!– 内部错误 –>-->
<!--<error-code>500</error-code>-->
<!--<location>/WEB-INF/errorpage/500.jsp</location>-->
<!--</error-page>-->
</web-app>
3.2.4 分页实现
这里参考了这篇博客:
Spring+Mybatis+SpringMVC后台与前台分页展示实例(附工程)
基本是照抄,这里就不重复写了。
3.2.5 网站逻辑
新建PlayerService.java
用来处理玩家信息。
package com.scarb.service;
import com.scarb.model.Player;
import com.scarb.util.PagedResult;
import java.util.List;
/**
* Created by Scarb on 9/14/2016.
*/
public interface PlayerService {
public Player selectPlayerById(Integer playerId);
public List<Player> selectPlayerByName(String playerName);
public List<Player> selectPlayerByClanTag(String clanTag);
public List<Player> selectPlayerByLeague(String league);
PagedResult<Player> queryNameByPage(String playerName, Integer pageNo, Integer pageSize);
PagedResult<Player> queryClanTagByPage(String clanTag, Integer pageNo, Integer pageSize);
PagedResult<Player> queryLeagueByPage(String league, Integer pageNo, Integer pageSize);
}
PlayerServiceImpl.java
package com.scarb.service.impl;
import com.github.pagehelper.PageHelper;
import com.scarb.dao.PlayerMapper;
import com.scarb.model.Player;
import com.scarb.service.PlayerService;
import com.scarb.util.BeanUtil;
import com.scarb.util.PagedResult;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* Created by Scarb on 9/16/2016.
*/
@Service
public class PlayerServiceImpl implements PlayerService{
@Resource
private PlayerMapper playerDao; // 这里playerDao注入会报错,不管它就行。
@Override
public Player selectPlayerById(Integer playerId) {
return playerDao.selectByPrimaryKey(playerId);
}
@Override
public List<Player> selectPlayerByName(String playerName) {
return playerDao.selectPlayerByName(playerName);
}
@Override
public List<Player> selectPlayerByClanTag(String clanTag) {
return playerDao.selectPlayerByClanTag(clanTag);
}
@Override
public List<Player> selectPlayerByLeague(String league) {
return playerDao.selectPlayerByLeague(league);
}
@Override
public PagedResult<Player> queryNameByPage(String playerName, Integer pageNo, Integer pageSize) {
pageNo = pageNo == null ? 1 : pageNo;
pageSize = pageSize == null ? 10 : pageSize;
PageHelper.startPage(pageNo, pageSize); // startPage告诉拦截器开始分页,分页参数是这两个
return BeanUtil.toPagedResult(playerDao.selectPlayerByName(playerName));
}
@Override
public PagedResult<Player> queryClanTagByPage(String clanTag, Integer pageNo, Integer pageSize) {
pageNo = pageNo == null ? 1 : pageNo;
pageSize = pageSize == null ? 10 : pageSize;
PageHelper.startPage(pageNo, pageSize); // startPage告诉拦截器开始分页,分页参数是这两个
return BeanUtil.toPagedResult(playerDao.selectPlayerByClanTag(clanTag));
}
@Override
public PagedResult<Player> queryLeagueByPage(String league, Integer pageNo, Integer pageSize) {
pageNo = pageNo == null ? 1 : pageNo;
pageSize = pageSize == null ? 10 : pageSize;
PageHelper.startPage(pageNo, pageSize); // startPage告诉拦截器开始分页,分页参数是这两个
return BeanUtil.toPagedResult(playerDao.selectPlayerByLeague(league));
}
}
然后是Controller
PlayerController.java
package com.scarb.controller;
import com.scarb.model.Player;
import com.scarb.service.LadderService;
import com.scarb.service.PlayerService;
import com.scarb.util.PagedResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
/**
* Created by Scarb on 9/14/2016.
*/
@Controller
public class PlayerController extends BaseController{
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private PlayerService playerService;
@RequestMapping("/")
public String getIndex(){
// ModelAndView mav = new ModelAndView("index");
// Player player = playerService.selectPlayerById(1);
// mav.addObject("player", player);
// return mav;
return "index";
}
@RequestMapping("/test")
public String Test(){
return "test";
}
@RequestMapping("/about")
public String about(){
return "about";
}
@RequestMapping("/grandmaster")
public String grandmaster(){
return "grandmaster";
}
@RequestMapping("/master")
public String master(){
return "master";
}
@RequestMapping("/diamond")
public String diamond(){
return "diamond";
}
@RequestMapping("platinum")
public String platinum(){
return "platinum";
}
@RequestMapping("gold")
public String gold(){
return "gold";
}
@RequestMapping("silver")
public String silver(){
return "silver";
}
@RequestMapping("bronze")
public String bronze(){
return "bronze";
}
@RequestMapping("noleague")
public String noleague(){
return "noleague";
}
@RequestMapping(value = "/list", method = RequestMethod.POST,produces = "text/html;charset=UTF-8") // springmvc 发送ajax中文乱码的几种解决办法 http://wxynxyo.iteye.com/blog/2000327
@ResponseBody
public String list(Integer pageNumber, Integer pageSize, String name){
logger.info("分页查询玩家信息列表请求入参:pageNumber{}, pageSize{}", pageNumber, pageSize);
try {
PagedResult<Player> pageResult = playerService.queryNameByPage(name, pageNumber, pageSize);
return responseSuccess(pageResult);
} catch (Exception e) {
return responseFail(e.getMessage());
}
}
@RequestMapping(value = "/listleague", method = RequestMethod.POST,produces = "text/html;charset=UTF-8") // springmvc 发送ajax中文乱码的几种解决办法 http://wxynxyo.iteye.com/blog/2000327
@ResponseBody
public String listByLeague(Integer pageNumber, Integer pageSize, String league){
logger.info("分页查询玩家信息列表请求入参:pageNumber{}, pageSize{}", pageNumber, pageSize);
try {
PagedResult<Player> pageResult = playerService.queryLeagueByPage(league, pageNumber, pageSize);
return responseSuccess(pageResult);
} catch (Exception e) {
return responseFail(e.getMessage());
}
}
}
3.2.6 前台页面
用ajax动态显示玩家表格,就贴个js,jsp文件就不一一贴出了
showTable.js
var PAGESIZE = 50;
var options = {
currentPage: 1, //当前页数
totalPages: 10, //总页数,这里只是暂时的,后头会根据查出来的条件进行更改
size:"large",
alignment:"center",
itemTexts: function (type, page, current) {
switch (type) {
case "first":
return "<<";
case "prev":
return "<";
case "next":
return ">";
case "last":
return ">>";
case "page":
return page;
}
},
onPageClicked: function (e, originalEvent, type, page) {
var param = $("#textInput").val(); //取内容
buildTable(param,page,PAGESIZE);//默认每页最多10条
}
}
//获取当前项目的路径
var urlRootContext = (function () {
var strPath = window.document.location.pathname;
var postPath = strPath.substring(0, strPath.substr(1).indexOf('/') + 1);
return postPath;
})();
//生成表格
function buildTable(name,pageNumber,pageSize) {
var url = urlRootContext + "/list"; //请求的网址
var reqParams = {'name':name, 'pageNumber':pageNumber,'pageSize':pageSize};//请求数据
$(function () {
$.ajax({
size:"large",
type:"POST",
url:url,
data:reqParams,
async:false,
dataType:"json",
success: function(data){
if(data.isError == false) {
// options.totalPages = data.pages;
var newoptions = {
currentPage: data.currentPage, //当前页数
totalPages: data.pages== 0 ? 1 : data.pages, //总页数
size:"normal",
alignment:"center",
itemTexts: function (type, page, current) {
switch (type) {
case "first":
return "<<";
case "prev":
return "<";
case "next":
return ">";
case "last":
return ">>";
case "page":
return page;
}
},
onPageClicked: function (e, originalEvent, type, page) {
var name = $("#textInput").val(); //取内容
buildTable(name,page,PAGESIZE);//默认每页最多10条
}
}
$('#bottomTab').bootstrapPaginator("setOptions",newoptions); //重新设置总页面数目
var dataList = data.dataList;
$("#tableBody").empty();//清空表格内容
if (dataList.length > 0 ) {
$(dataList).each(function(){//重新生成
var date = new Date(Number(this.jointime) * 1000);
$("#tableBody").append('<tr>');
$("#tableBody").append('<td>' + this.rank + '</td>');
// 组别
if (this.league == "GRANDMASTER")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade7.png">' + '</td>');
else if (this.league == "MASTER")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade6.png">' + '</td>');
else if (this.league == "DIAMOND")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade5.png">' + '</td>');
else if (this.league == "PLATINUM")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade4.png">' + '</td>');
else if (this.league == "GOLD")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade3.png">' + '</td>');
else if (this.league == "SILVER")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade2.png">' + '</td>');
else if (this.league == "BRONZE")
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/grade1.png">' + '</td>');
else
$("#tableBody").append('<td>' + '</td>');
// 种族
if(this.favoriterace == 'TERRAN')
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/race_t.png">' + '</td>');
else if (this.favoriterace == 'PROTOSS')
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/race_p.png">' + '</td>');
else if (this.favoriterace == 'ZERG')
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/race_z.png">' + '</td>');
else if (this.favoriterace == 'RANDOM')
$("#tableBody").append('<td>' + '<img src="' + urlRootContext + '/images/race_r.png">' + '</td>');
else
$("#tableBody").append('<td>' + '</td>');
// 名字
if (this.clantag != '')
$("#tableBody").append('<td> <a href="http://www.battlenet.com.cn/sc2/zh' + this.profilepath + '" target="_blank">' +
'[' + this.clantag + ']' + this.name + '</a> </td>');
else
$("#tableBody").append('<td> <a href="http://www.battlenet.com.cn/sc2/zh' + this.profilepath + '" target="_blank">' +
this.name + '</a> </td>');
$("#tableBody").append('<td>' + this.points + '</td>');
$("#tableBody").append('<td>' + this.wins + '</td>');
$("#tableBody").append('<td>' + this.losses + '</td>');
$("#tableBody").append('<td>' + this.winrate + '%</td>');
$("#tableBody").append('<td>' + date.toLocaleDateString() + '</td>');
$("#tableBody").append('</tr>');
});
} else {
$("#tableBody").append('<tr><th colspan ="4"><center>查询无数据</center></th></tr>');
}
}else{
alert(data.errorMsg);
}
},
error: function(e){
alert("查询失败:" + e);
}
});
});
}
4. 功能拓展
YY一下想要实现的其他功能
4.1 注册登录
注册账号并且登录。还要能够绑定战网账号。
4.2 留言板、论坛
目前想有一个简易的留言板,供玩家提建议以及吹比。
4.3 其他服务器
其他服务器数据获取方式和国服差不多,就是做一些重复劳动而已。不过我比较厌恶重复劳动……
4.4 多人天梯
优先级排在比较后面
4.5 扫码功能
这个可以有,不过要等到有韩服数据了以后……
4.6 优化数据获取代码
完