SC2Rank 星际2天梯排行榜 SpringMVC + Spring + Mybatis + Mysql + Maven java web项目

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>

    <!--&lt;!&ndash; 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 &ndash;&gt;-->
    <!--<bean id="multipartResolver"-->
    <!--class="org.springframework.web.multipart.commons.CommonsMultipartResolver">-->
    <!--&lt;!&ndash; 默认编码 &ndash;&gt;-->
    <!--<property name="defaultEncoding" value="utf-8" />-->
    <!--&lt;!&ndash; 文件大小最大值 &ndash;&gt;-->
    <!--<property name="maxUploadSize" value="10485760000" />-->
    <!--&lt;!&ndash; 内存中的最大值 &ndash;&gt;-->
    <!--<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>
  <!--&lt;!&ndash; 设计路径变量值 &ndash;&gt;-->
  <!--<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>


  <!--&lt;!&ndash; 错误跳转页面 &ndash;&gt;-->
  <!--<error-page>-->
  <!--&lt;!&ndash; 路径不正确 &ndash;&gt;-->
  <!--<error-code>404</error-code>-->
  <!--<location>/WEB-INF/errorpage/404.jsp</location>-->
  <!--</error-page>-->
  <!--<error-page>-->
  <!--&lt;!&ndash; 没有访问权限,访问被禁止 &ndash;&gt;-->
  <!--<error-code>405</error-code>-->
  <!--<location>/WEB-INF/errorpage/405.jsp</location>-->
  <!--</error-page>-->
  <!--<error-page>-->
  <!--&lt;!&ndash; 内部错误 &ndash;&gt;-->
  <!--<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 优化数据获取代码

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值