缓存第五篇:无框架的自定义页面缓存---从后台到页面

本文介绍了一种不依赖框架的前端页面缓存方法,详细展示了如何利用Java代码处理和缓存下拉框数据,包括数据结构调整、使用Shiro Session存储及从前台到后台的数据流过程。

前几篇讲的缓存都是后台缓存,并且思路都是与mybatis结合的sql持久化层的缓存,用的redis或者ehache缓存框架。今天我们讲一个前台页面缓存,没有任何框架,纯java代码,并且很实用和灵活。是从我们项目中抽离出来的分享给大家。

1.前台页面缓存主要用在什么地方?

我们这里主要是用在下拉框数据显示上,和前端工程师的静态页面缓存没任何关联。如果用户登录成功进入功能页面,一些预先加载的数据中,查询条件的下拉数据是绝对要先加载好的。

2.下拉数据缓存的数据结构

下拉数据的结构设计直接影响取值和级联效果的开发难以程度。非常重要。下拉的数据最合理的结构之一如下:

[{id:"真实值",name:"显示值"},{id:"真实值",name:"显示值"},...]
比如[{id:"A",name:"北京分公司"},{id:"B",name:"湖北分公司"}]

那这些数据结构如何构造出来的呢?
我们在执行查询语句的Service层,对查询出来的数据进行结构调整。下面这个可以先简单看下,和后面的具体步骤结合更好理解。

sql:SELECT DISTINCT MANAGECOMCODE AS ID,NAME,MANAGECOM FROM.....
//查询语句
List<Map<String,String>> list=appDao.queryForMapList("SOA.DataDict.getBranchByUserId",param);
//执行查询出来的数据结构为List<Map<String,String>>,比如[{"A":"北京分公司","ID":"10","NAME":"北京分支"},{"B":"湖北分公司","ID":"20","NAME":"十堰分支"},...];要让这数据拆成[{id:"A",name:"北京分公司"},{id:"B",name:"湖北分公司"}]
Map<String,List<Map<String,String>>> data=new HashMap<String,List<Map<String,String>>>();
//防止字典表数据重复,也为了拆分map值。用到HashSet
Set<String> keySet =new HashSet<String>();
for(Map<String,String> map:list){
    //把所有公司码都作为key先放到set集合中,也有去重复作用。
    keySet.add(map.get("MANAGECOM"));
}
//然后根据公司码遍历出公司名。重新构造数据结构
for(String key:keySet){
    List<Map<String,String>> cd=new ArrayList<Map<String,String>>();
    for(Map<String,String> map:list){
        if(map.get("MANAGECOM").equals(key)){
            Map<String,String> org=new HashMap<String,String>();
            org.put("id",map.get("ID"));
            org.put("name",map.get("NAME"));
            cd.add(org);
        }
    }
data.put(key,cd);
}
return data;

3.用的什么来缓存数据?

shiro的Session来存储数据。因为用户登录用到shiro,验证通过就可以加载缓存。

4.数据缓存从后台到前台页面的流程

1.查询出数据,进行数据结构调整。—service层

2.将数据进一步区分,放到公共的缓存HashMap中—cache层,相当于service层

3.用户登录成功,创建session,并把公共的缓存setAttribute进session中。

4.到加载菜单页面的公共页面取出缓存数据,并转数据类型为json

5.在单独一个js中对json缓存数据进行按key区分,取出数据封装下拉框公共方法

6.在各个子页面引入公共方法和公共页面,展示出数据。

5.具体实现步骤(看思路,代码供参考,不具备复现价值)

项目框架:ssm
现在我们要实现一个省市区中省份的下拉数据展示,则依它来了解数据流如何从数据库到下拉菜单的。

5.1 数据库中省的单表数据结构如下图 ,表名称:soa_province,表字段有PROVINCE , NAME , ENABLED , ADDUSER , ADDTIME .

这里写图片描述

5.2 mapper文件的SQL查询语句,这就开始注意数据结构的id,name字段

<select id="getProvince" resultMap="BaseResultMap">
    SELECT PROVINCE AS ID,NAME FROM SOA_PROVINCE WHERE ENABLED='Y'
</select>

5.3 service层执行查询的语句,调整数据结构

@Service(DataDictSerice.service_ID)
public class DataDictServiceImpl extends BaseServiceImpl implements DataDictSerice{
    public List<Map<String,String>> getProvince(){
        List<Map<String,String>> list=appDAO.queryForMapList("SOA.getProvince",new HashMap());
        List<Map<String,String>> data=new ArrayList<Map<String,String>>();
        Map<String,String> map;
        final String ID="id";
        final String NAME="name";
        for(Map<String,String> map:list){
            map=new HashMap<String,String>();
            map.put(ID,map.get("ID"));
            map.put(NAME,map.get("NAME"));
            data.add(map);
        }
    return data;
    }
}

5.4 对数据进一步处理,并存放到HashMap中。

@Service("CommonCacheMap")
public class CommonCacheMap{

    @Resource(name=DataDictService.SERVICE_ID)
    private DataDictService dataDictService;

    public static final Map<String,Object> baseData=new HashMap<String,Object>();

    //系统启动时就加载好各缓存
    @PostConstruct
    public void afterPropertiesSet() throws Exception{
        SoaDataDictProvince();
        SoaDataDictCity();
        ...
    }
    private static Map<String,String> PROVINCE=new ConcurrentHashMap<String,String>();
    private void SoaDataDictProvince(){
        PROVINCE.clear();
        List<Map<String,String>> data=dataDictService.getProvince()
        for(Map<String,String> map:data){
            PROVINCE.put(map.get("id"),map.get("name"))
        }
        baseData.put("province",data);
    }

}

5.5 在用户登录时把HashMap中的数据放到session中返回前台菜单公共页面

@Controller("mainController")
@RequestMapping(value="")
public class MainController extends BaseController{
    @Resource(name=ISystemService.SERVICE_ID)
    private ISystemService systemAction;
    @RequestMapping("/importFunction")
    public ModelAndView main(HttpServletRequest request){
        LoginUser user=UserUtils.getUser(); 
        UserBo userInfo=user.getUser();
        Map<String,Object> baseData=CommonCacheMap.baseData;
        Session session=SecurityUtils.getSubject().getSession();
        session.setAttribute("baseData",baseData);
        session.setAttribute("currentUser",user);
        ModelAndVilw modelAndView=new ModelAndView();
        //用modelandvilw实现转跳到main.jsp页面
        modelAndView.setViewName("main");
        return modelAndView;
    }

}

5.6 main.jsp公共页面处理缓存数据,转换为json数据。

在main.jsp中并没有直接处理数据js代码,但是main.jsp引入了别的jsp页面来处理后台传过来的数据
这里写图片描述
在include.jsp公共页面中。确实有处理的代码。

第一步:取到baseData

<%
String baseData="";
Object base=session.getAttribute("baseData");
if(base !=null){
    baseData=JSONUtils.toJOSNString(base);
}
%>
第二步  赋值给jsp变量并转换数据类型。
<script type="text/javascript">
    var baseData;
    var bb="<%=baseData%>";
    if(bb){
        baseData=eval("("+bb+")")
    }
</script>

下图为强转后的数据结构:
这里写图片描述
在这个include.jsp页面处理完缓存后才能引入data.js文件。注意按先后顺序加载!

5.7 封装缓存为公共方法,供子页面调用。在data.js这个js文件中实现。
//定义全局变量

var comObj,saleCom,center,city,dept,group,branch,province,....;
if(baseData){
    province=baseData.province;//省
    city=baseData.city;//市
}
//为下拉显示加上全部这个字段。
function getAllProvince(){
    if([]!=province){
        var temp=$.extend(true,[],province);
        temp.unshift({'id':'','name':'全部'});
        return temp;
    }
}

function getAllCity(key){
    if([] !=city[key]){
        var temp=$.extend(true,[],city[key]);
        temp.unshift({'id':'','name':"全部"});
        return temp;
    }

}

5.8 在子页面引用封装的方法,easyui框架来实现下拉。

<input class="easyui-combobox" id="transProv" name="transProv"/>

//省市区下拉列表
$("#transProv").combobox({
    editable:false;
    data:getAllProvince(),
    valueField:"id",
    textFileld:"name",
    onSelect:function(current){
        $("#transCity").combobox({
            editable:false;
            data:getAllCity(current.id),
            valueField:"id",
            textField:"name",
            onSelect:function(currentd){
                $("#transDisr").combobox({
                    editable:false,
                    data:getAllDist(currentd.id),
                    valueField:"id",
                    textField:"name"
                })
            }
        })
$("#transDistr").combobox('setValue','');
$("#transDistr").combobox('loadData',[]);
    }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万米高空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值