zoukankan      html  css  js  c++  java
  • 超轻量级spring模板方案

       最近从事的工作是web方面的,主要j2ee,spring jsp这些内容,由于刚入门,很多的技术都不了解。所谓初生牛犊不怕虎,刚入门,各种不顺手,比如写jsp,总是重复很多的代码,各种不爽,然后就去看jsp的模板技术,

    看来看去也是各种不爽,于是就有了自己写一个工具的想法。

    ok,废话一堆。先说说jsp模板,最简单的include,成熟的解决有tiles,还有什么setmesh,当日还有更强大的什么fremaker,volocity(是这样写的吗,记不清楚)等等。

    include不说,实在太简陋,tiles其实是很不错的,不是很重,学习成本还算好,用的也比较广吧,当然要说广,肯定有后面那几个了。可是这些对我来说,都太重。我要的是什么样的?我记得rails里面的模板,大概就是layout里面写一句yield就ok了。

    没错,这就是我想要的。写好layout,把什么header、menu什么的搞定,内容里面一个div套着一个yield,你就可以专注于你的子视图了,框架自动把layout应用到你的视图上去。

    就这个简单的功能,为什么要那么复杂的框架、插件呢?

    不过jsp,看看好像还真没有。那就自己实现吧,反正我是初入门,什么都不知道,不知者无畏嘛。

       屁话一堆,总算到该说些正题了。

       那么,怎么实现呢?我的思路是,layout里面写好布局后,正文部分就用${yield}代替,

    当请求子视图的时候,自动的将子视图插入到layout中,替换${yield},然后生成一个新的合成视图,存入缓存文件中,由新的视图相应前端的请求。

      我们知道spring里面有个配置viewresolver的类,可以在有请求的时候,查找视图,构建视图,并返回给前端。我们就在这里做我们的事情。

      我们继承一个InternalResourceViewResolver,该resolver会根据视图查找相应的InternalResourceView来处理jsp视图。InternalResourceViewResolver有一个buildView的调用,该调用根据视图名称构建view。

    我们就重载这个方法,根据前面的思路,首先找到模板文件和子视图,然后替换掉模板文件中的${yield},写入到新的jsp文件,然后重定向到该文件,就ok了。具体看代码:

     1 package lin.layoutsample.framework;
     2 
     3 import lin.layoutsample.utils.FileUtils;
     4 import lin.layoutsample.utils.StringUtils;
     5 
     6 import org.springframework.web.servlet.view.AbstractUrlBasedView;
     7 import org.springframework.web.servlet.view.InternalResourceViewResolver;
     8 
     9 public class LayoutViewResolver extends InternalResourceViewResolver {
    10 
    11     private static String DEFUALT_YIELD_CMD = "${yield}";
    12     private static String DEFUALT_LAYOUT_TEMP_DIR = "/WEB-INF/layout/layout_temp";
    13     private static String DEFUALT_LAYOUT = "/WEB-INF/layout/layout.jsp";
    14 
    15     /**
    16      * layout文件。默认为/WEB-INF/layout/layout.jsp。
    17      * */
    18     private String layout = DEFUALT_LAYOUT;
    19 
    20     /**
    21      * 经过替换后的视图缓存目录,默认为/WEB-INF/layout/layout_temp。
    22      * */
    23     private String temp_path = DEFUALT_LAYOUT_TEMP_DIR;
    24 
    25     /**
    26      * 默认为${yield}。模板中该命令会被子视图替换。类似rails的yield。
    27      * */
    28     private String yield_cmd = DEFUALT_YIELD_CMD;
    29 
    30     /**
    31      * 
    32      * 函数首先根据指定的view在缓存区生成对应的文件,然后将模板文件(默认为layout.jsp)中的${yield}替换成视图的内容。
    33      * 再调用超类的buildview函数生成新的被视图并返回。这样就完成了模板的替换和重定向到新生成的视图。
    34      * */
    35     @Override
    36     protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    37         String url = getPrefix() + viewName + getSuffix();
    38         String target_view_real_path = super.getServletContext().getRealPath(
    39                 getTemp_path())
    40                 + url;
    41         FileUtils.createFile(target_view_real_path);
    42         String layout_real_path = super.getServletContext().getRealPath(
    43                 getLayout());
    44         String layout_content = FileUtils.read(layout_real_path);
    45         String view_content = FileUtils.read(super.getServletContext()
    46                 .getRealPath(url));
    47         String result_view_content = StringUtils.replace(layout_content, "\Q"
    48                 + getYield_cmd() + "\E", view_content);
    49         FileUtils.write(target_view_real_path, result_view_content);
    50 
    51         AbstractUrlBasedView view = super.buildView(getTemp_path() + getPrefix()+ viewName);
    52         return view;
    53     }
    54 
    55     public String getLayout() {
    56         return layout;
    57     }
    58 
    59     public void setLayout(String layout) {
    60         this.layout = layout;
    61     }
    62 
    63     public String getTemp_path() {
    64         return temp_path;
    65     }
    66 
    67     public void setTemp_path(String temp_path) {
    68         this.temp_path = temp_path;
    69     }
    70 
    71     public String getYield_cmd() {
    72         return yield_cmd;
    73     }
    74 
    75     public void setYield_cmd(String yield_cmd) {
    76         this.yield_cmd = yield_cmd;
    77     }
    78 }

    是不是很简单?只需要一个方法,然后就是在web的配置里面将默认的InternalResourceViewResolver 替换成我们的就可以了。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
     6     xmlns:security="http://www.springframework.org/schema/security"
     7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     8 http://www.springframework.org/schema/beans/spring-beans.xsd 
     9 http://www.springframework.org/schema/context 
    10 http://www.springframework.org/schema/context/spring-context.xsd 
    11 http://www.springframework.org/schema/mvc 
    12 http://www.springframework.org/schema/mvc/spring-mvc.xsd
    13 http://www.directwebremoting.org/schema/spring-dwr  
    14 http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd
    15 http://www.springframework.org/schema/security  
    16 http://www.springframework.org/schema/security/spring-security-3.2.xsd
    17 ">
    18 
    19     <!-- 自动扫描controller包下的所有类,使其认为spring mvc的控制器 -->
    20     <context:component-scan base-package="lin.layoutsample.controller" />
    21     
    22 
    23     <!-- 通过注解,把URL映射到Controller上,该标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
    24     <mvc:annotation-driven />
    25 
    26 
    27     <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
    28     <bean class="lin.layoutsample.framework.LayoutViewResolver">
    29         <property name="prefix" value="/" />
    30         <property name="suffix" value=".jsp" />
    31         <property name="layout" value="/WEB-INF/layout/layout.jsp" />
    32     </bean>
    33 </beans>

    这里我们可以配置我们的模板文件(一般叫layout.jsp)的路径,当然你也可以不用${yield}来占位,你可以自己配置成属性就行了。

    完整的layout.jsp文件如下,路径我一般放在/WEB-INF/layout/下面。

     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3     
     4 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
     5 
     6 <!DOCTYPE html>
     7 <html>
     8 <%
     9     String path = request.getContextPath();
    10     String basePath = request.getScheme() + "://"
    11             + request.getServerName() + ":" + request.getServerPort()
    12             + path + "/";
    13 %>
    14 <base href="<%=basePath%>">
    15 <head>
    16 <%@include file="/WEB-INF/layout/_include.jsp"%>
    17 <title>花花世界</title>
    18 </head>
    19 <body>
    20     <%@include file="/WEB-INF/layout/_header.jsp"%>
    21 
    22     <div class="container-fluid">
    23         <div class="row">
    24             <%@ include file="/WEB-INF/layout/_menu.jsp"%>
    25             <div class="page-content">
    26                 <div class="container-fluid" data-role="main">
    27                     <!-- Main component for a primary marketing message or call to action -->
    28 
    29                     ${yield}
    30 
    31                 </div>
    32                 <!-- container-fluid -->
    33             </div>
    34             <!-- page-content -->
    35         </div>
    36 
    37 
    38     </div>
    39     <!-- /container -->
    40 
    41     <%@include file="/WEB-INF/layout/_import.jsp"%>
    42 </body>
    43 </html>

    子视图就很简单了只需要一行示例代码就行了,文件say-hi.jsp如下。

    1 <h2>hi world!!</h2>

    我们的控制器完全不需要考虑模板的事情,新建一个子视图返回就行了。

     1 package lin.layoutsample.controller;
     2 
     3 import org.slf4j.Logger;
     4 import org.slf4j.LoggerFactory;
     5 import org.springframework.stereotype.Controller;
     6 import org.springframework.web.bind.annotation.RequestMapping;
     7 import org.springframework.web.servlet.ModelAndView;
     8 
     9 
    10 @Controller
    11 @RequestMapping("/hello")
    12 public class HelloController {
    13     private Logger logger = LoggerFactory.getLogger(HelloController.class);
    14     
    15     @RequestMapping("/say-hi")
    16     public ModelAndView sayHi(){
    17         logger.debug("HelloController:sayHi");
    18         ModelAndView mv = new ModelAndView("WEB-INF/views/say-hi");
    19         return mv;
    20     }
    21 }

    效果如下图:

    是不是很简单,对开发者来说,只需要配置一下,别的都不需要关心,就可以完成模板布局的应用了。

    不过我是初学,入门,哪些商业的模板工具自然有他得用武之地,我这个超轻量级的模板解决方案,写写小网页还是足够了。

    有兴趣的tx可以去github上下载我的代码https://github.com/linbirg/wish。

    欢迎大神批评指正。

  • 相关阅读:
    Verilog手绘FVH信号
    Verilog编码规范与时序收敛
    关于DDS的基础知识
    阅读ug949-vivado-design-methodology笔记
    在windows系统上使用pip命令安装python的第三方库
    pandas第一课
    视频外同步信号研究---fvh
    FPGA调试技巧
    关于FIFO异步复位的问题
    搭建一个microblaze的最小系统
  • 原文地址:https://www.cnblogs.com/linbirg/p/3956791.html
Copyright © 2011-2022 走看看