数据提取到页面展示

Posted on By Guanzhou Song

数据到页面

公司项目中有一个部分是数据的提取与展示,虽然这可能是一项很常规的任务,但对我来说也算是一个巨大的挑战吧。

做完这个部分其实涉及的东西很多,包括html与json,jquery等等,还有数据库和后端的一大堆知识,同时也为了高tou效lan而学习了代码生成器。

需求

产品经理的要求很简单,从数据库里取出数据,分门别类的展示在html页面上。就如下图:

那么理一下思路,大概是这样的过程:

Repository从数据库提取数据–>Service层处理数据–>Controller层发送给页面(JSON格式的数据)–>html页面获取并展示数据

看上去好简单啊,但是对我这个菜鸟来说到处都是坑。

后端

Repository持久层

第一步是取出数据,数据库的sql很简单,Mapper.xml里面写进去就好。

ALL OR SOME

但是在取数据时,还是有一些疑虑。在最初的版本里,我只是取出了所有的数据。我的本意是能够方便后期的维护,比如修改显示字段什么的。但是后来发现,这样做的下场就是慢,真的很慢。因此改进后的代码只是把需要的数据取出。

SQL=函数

但是在参考了前辈的代码以后,发现还有一些小技巧,可以省略很多sql语句。

发现SELECT * from DB 这样的语句完全不必要写,只需要利用函数select

这个函数在包含在framework.Mybatis.mapper.base.select,应该是一个Mybatis自带的函数,通过传入带有某些参数的model类,获得相应的数据。

图中的例子是通过一个法人唯一标识frwybs查找对应的一条数据,Mapper.select(model)等价于

SELECT ALL from xxxDB a WHERE a.frwybs = frwybs

另外还有selectOne,selectKey等函数可以用,下次记得去Mybatis官网仔细查询

传参

既然是个动态页面,每次需要的sql语句也是不同的,就需要将查询的参数传给Mapper.xml。

单参数的传递很简单,用#{paraname}就可以了。但是如果有多个参数要传入,就可以用下面三种方法:

DAO层传递
Public User selectUser(String name,String area);

<select id="selectUser" resultMap="BaseResultMap">
    select  *  from user_user_t   where user_name = #{0} and user_area=#{1}
</select>

#{0}表示第一个参数

Map传参
Public User selectUser(Map paramMap);

<select id=" selectUser" resultMap="BaseResultMap">
   select  *  from user_user_t   where user_name = #{userName,jdbcType=VARCHAR} and user_area=#{userArea,jdbcType=VARCHAR}
</select>

Private User xxxSelectUser(){
Map paramMap=new hashMap();
paramMap.put(“userName”,”对应具体的参数值”);
paramMap.put(“userArea”,”对应具体的参数值”);
User user=xxx. selectUser(paramMap);}

这种方法在公司的代码中用的很多,但我认为这种方法不但代码复杂,还要利用多余的资源去创建一个map再读取,有点性能浪费

DAO层传递Improve
Public User selectUser(@param(“userName”)Stringname,@param(“userArea”)String area);

<select id=" selectUser" resultMap="BaseResultMap">
   select  *  from user_user_t   where user_name = #{userName,jdbcType=VARCHAR} and user_area=#{userArea,jdbcType=VARCHAR}
</select>

这样代码就比较简洁,也知道哪些参数对应mapper中的哪些值

Service层

Service层其实和Repository层是互相配合的,主要作用就是从数据库中取出JSON格式的List

通过这样创建一个HashMap,将不同表中取出的数据存放在Map对应的Key中,接下来在页面中只需要利用${Mapname[Key]}取出该List。

Controller层

链接页面与后台的主要地方,也是我迷惑最久的。 首先来看注解

RequestMapping是当页面请求的时候,该方法就会启动,在这个例子中,某个页面通过 <li class="tab-selected"><span class="tab-item"><a href="<c:url value='/data/frdetail/admission/${frwybs}'/>">许可、资质与荣誉</a></span>请求了/data/frdetail/admission/${frwybs},调用了这个对应的方法。

而这个${frwybs}到底是哪里来的?作为查询的主要条件,贯穿了页面与后台。其实frwybs是通过 @PathVariable(value = "frwybs") String frwybs 输入的。 本地测试环境下输入http://localhost:8082/data/frdetail/admission/11330127739902694G 即可查询得到frwybs为11330127739902694G的Admission Info,也就是从请求/admission/{frwybs}中获得frwybs,并在方法中利用model.addAttribute("frwybs", frwybs);将其放入Model中,返回以后就可以直接调用${frwybs}得到字段。

前端

后台大致已经完成取数据,打包传递的过程,接下来就需要页面对数据进行读取然后显示。

以这段代码为例

<div class="light-info mt10 center pos-rel">
    <i class="flex-icon"></i>行政许可信息
</div>
<c:choose>
<c:when test="${empty xzxkxx.xkrq}">
  <table class="table-row nowrap" width="100%" cellpadding="0" cellspacing="0" border="0">
    <thead>
        <tr>
            <th>暂无相关数据</th>
        </tr>
    </thead>
</table>
</c:when>
<c:otherwise>
<table class="table-row nowrap" width="100%" cellpadding="0" cellspacing="0" border="0">
    <thead>
        <tr>
            <th>序号</th>
            <th>行政许可文(证)编号</th>
            <th>行政许可内容</th>
            <th>行政许可核发机关名称</th>
            <th>行政许可核发机关日期</th>
            <th>许可证状态</th>
            <th>行政许可有效期自</th>
            <th>行政许可有效期至</th>
        </tr>
    </thead>
    <tbody>
    <c:forEach var="List" varStatus="status" items="${xkxx['xzxkxx']}">
        <tr>
            <td>${status.index+1}</td>
            <td>${List.xkzsbh}</td>
            <td>${List.xknr}</td>
            <td>${List.xkjg}</td>
            <td><fmt:formatDate value="${List.xkrq}" pattern="yyyy年MM月dd日"/></td>
            <td>${List.xkzt}</td>
            <td><fmt:formatDate value="${List.xkqs}" pattern="yyyy年MM月dd日"/></td>
            <td><fmt:formatDate value="${List.xkjz}" pattern="yyyy年MM月dd日"/></td>
        </tr>
    </c:forEach>
    </tbody>
</table>
</c:otherwise>
</c:choose>

数据提取

<c:forEach var="List" varStatus="status" items="${xkxx['xzxkxx']}">

后台传来的数据中有一个name=xkxx的map,而key=xzxkxx对应的list就是我们需要的信息,因此提取并命名为var=List。

之后便可以利用List.xkzsbh等得到对应字段的数据并填充在表格中。

Big C

在html里面用处可以说是非常广,可以像java一样if…else等判断,也可以做个循环。

<c:forEach>可以遍历所有的数据,类似于for(data:List);

if…else也是很有用的,具体格式为

  <c:choose>
    <c:when test="">
    </c:when>

    <c:otherwise>
    </c:otherwise>
  </c:choose>

JSP?叫爸爸

JSP与HTML到底有什么区别?

JSP页面是动态页,有JSP容器执行该页面的Java代码部分然后实时生成的页面.

HTML页面是静态页面,也就是事先由用户写好放在服务器上,由web服务器向客户端发送.

总的来说就是JSP是动态的,能够根据实际情况生成HTML。也就是爸爸。

代码生成器

Repository层中,每个Model对应一张表,每个字段需要这些代码:

//Model中
@(column="xxx")
private String xxx;
public getxxx();
public setxxx(String xxx);

//Mapper.xml中
<resultMap id="BaseResultMap" type="ModelName">
     <result property="id" column="id"/>
</resultMap>

这么有规律的代码,还要我手写?要知道公司数据库一百多张表,每张表30个字段,一个个写是不可能的。因此这就要用到代码生成器来代劳啦。

之所以选择rapid-generator是因为这个工具可以独立运行,直接下载独立运行版。

下载地址:http://code.google.com/p/rapid-generator/downloads/list。

照着里面的运行说明和生成器特性简要说明,很快就可以测试成功(注意需要配置java环境变量),进而就可以根据自己需求进行配置,自动生成代码了。

基本就是3个步骤,1. 修改generator.xml文件里的数据库配置;2. 按需修改template文件夹里的内容;3. 运行rapid-gen.bat

generator.xml

基本就是一些DB的配置,测试一下能连接上就好

template

Template真是个好东西,能够按照你自己的意思大批量生成文件,.java,.xml, 甚至是.jsp。

package ${basepackage}.model;
<#include "/macro.include"/>
<#include "/java_imports.include"/>
<#include "/java_copyright.include">
<#assign className = table.className>
<#assign classNameLower = className?uncap_first>

/**
 * ${table.remarks}
 * @author
 */
public class ${className}  implements java.io.Serializable{

	private static final long serialVersionUID = 5454155825314635342L;

	//columns START
	<#list table.columns as column>
	//${column.remarks}
	private ${column.javaType} ${column.columnNameLower};
	</#list>
	//columns END
<@generateJavaColumns/>
}

<#macro generateJavaColumns>
	<#list table.columns as column>

	public void set${column.columnName}(${column.javaType} value) {
		this.${column.columnNameLower} = value;
	}

	public ${column.javaType} get${column.columnName}() {
		return this.${column.columnNameLower};
	}
	</#list>
</#macro>

生成符合公司规定的model文件模板

<?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">

<!-- 不使用namespace的话sql搜索定位会比较方便 -->
<mapper namespace="com.icinfo.frk.business.mapper.${table.className}Mapper" >
	<resultMap id="BaseResultMap" type="com.icinfo.frk.business.model.${table.className}">
        <#list table.columns as column>
        <result property="${column.columnNameLower}" column="${column.sqlName}"/>
				</#list>
	</resultMap>
</mapper>

.xml一样能够生成

Run!

之后在rapid-gen.bat中运行就行啦,复制粘贴到项目里就行了。

小结

至此大概就完成了一整个的流程:

Repository从数据库提取数据–>Service层处理数据–>Controller层发送给页面(JSON格式的数据)–>html页面获取并展示数据

Controller收到页面请求,提取出关键信息frwybs,传递给Service;

Service利用frwybs,命令Repository去进行数据库操作;

Repository提取数据,分别从一个表中得到一个List,返回给Service;

Service收集List以后,统一放置在Map中,返回给Controller;

Controller收到Map,与其他信息一起放置在Model中,返回指定的jsp;

JSP根据得到的数据,动态生成HTML页面。