Spring MVC 学习总结之FreeMarker模板引擎与动态页面静态化

目录

    一、FreeMarker简介
    二、第一个FreeMark示例
        2.1、新建一个Maven项目
        2.2、添加依赖
        2.3、添加存放模板的文件夹
         2.4、添加模板
        2.5、解析模板
        2.6、运行结果
    三、动态页面静态化
        3.1、动态页面静态化的优点
        3.2、动态页面静态化的问题
        3.3、实现动态页面静态化
            3.3.1、新建一个基于Maven的Web项目
            3.3.2、添加依赖
            3.3.3、创建文章POJO类
            3.3.4、创建文章业务类
            3.3.5、添加模板
            3.3.6、添加Servlet生成静态页
            3.3.7、运行结果
    四、FreeMarker模板语法
        4.0、模板文件的4个组成部分
        4.1、FTL指令规则
        4.2、 插值规则
        4.3、表达式
            4.3.1、直接指定值
            4.3.2、输出变量值
            4.3.3、字符串操作
            4.3.4、集合连接运算符
            4.3.5、Map连接运算符
            4.3.6、算术运算符
            4.3.7、比较运算符
            4.3.8、逻辑运算符
            4.3.9、内建函数
            4.3.10、空值处理运算符
            4.3.11、运算符的优先级
        4.4、FreeMarker的常用指令
            4.4.1、if指令
            4.4.2、switch , case , default , break指令
            4.4.3、list, break指令
            4.4.4、include指令
            4.4.5、import指令
            4.4.6、noparse指令
            4.4.7、escape , noescape指令
            4.4.8、assign指令
            4.4.9、setting指令
            4.4.10、macro , nested , return指令
    五、示例下载

模板引擎可以让程序实现界面与数据分离,业务代码与逻辑代码的分离,这就提升了开发效率,良好的设计也使得代码复用变得更加容易。一般的模板引擎都包含一个模板解析器和一套标记语言,好的模板引擎有简洁的语法规则、强大的功能、高效的渲染效率、详尽的帮助说明与不断的更新与维护。常见的前端模板引擎有:

Spring MVC 学习总结之FreeMarker模板引擎与动态页面静态化_第1张图片

常用的java后台模板引擎:jsp、FreeMarker、Velocity等。

Spring MVC 学习总结之FreeMarker模板引擎与动态页面静态化_第2张图片

请不要迷恋速度,为了推广的测试可能是片面的,好的模板引擎经得起时间考验,建议大家选择成熟的、常用的模板引擎。另外不管前后端的模板引擎原理都差不多,不外乎在模板中定义一些特别的标签后台正则匹配后替换,所以这里就以FreeMarker为例简介一下模板引擎的使用。另外我个人觉得ASP.NET MVC中使用的razor模板引擎非常好用,如果java有一款类似的就好了。

一、FreeMarker简介

FreeMarker是一款模板引擎,即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
模板编写为FreeMarkerTemplateLanguage(FTL)。它是简单的,专用的语言,不是像PHP那样成熟的编程语言。那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据,而在模板之外可以专注于要展示什么数据。

这种方式通常被称为MVC(模型视图控制器)模式,对于动态网页来说,是一种特别流行的模式。它帮助从开发人员(Java程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑,在没有程序员来修改或重新编译代码时,也可以修改页面的样式。

而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中。

特征与亮点:

功能强大的模板语言:有条件的块,迭代,赋值,字符串和算术运算和格式化,宏和函数,编码等更多的功能;

多用途且轻量:零依赖,输出任何格式,可以从任何地方加载模板(可插拔),配置选项丰富;

智能的国际化和本地化:对区域设置和日期/时间格式敏感。

XML处理功能:将dom-s放入到XML数据模型并遍历它们,甚至处理他们的声明

通用的数据模型:通过可插拔适配器将java对象暴露于模板作为变量树。

FreeMarker是免费的,基于Apache许可证2.0版本发布。

获得FreeMarker

官网:http://freemarker.org/

中文帮助文档:https://sourceforge.net/projects/freemarker/files/chinese-manual/

下载FreeMarker jar包:下载地址http://freemarker.org/freemarkerdownload.html

中文网:http://freemarker.foofun.cn/

使用Maven依赖jar包:

复制代码
<dependency>
  <groupId>org.freemarkergroupId>
  <artifactId>freemarker-gaeartifactId>
  <version>2.3.25-incubatingversion>
dependency>
复制代码

FreeMarker用途

生成HTML Web页面,如作为MVC框架的视图

动态页面静态化等

代码生成器

二、第一个FreeMark示例

模板 + 数据模型 = 输出,FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念,他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据。总之实现了数据与表现的分离。

2.1、新建一个Maven项目

新建一个简单Maven项目,不要选择内置模板,设置jdk版本为1.7。

2.2、添加依赖

修改pom.xml配置文件,增加freemark、junit依赖,修改后的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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.zhangguogroupId>
    <artifactId>FreeMarkerDemoartifactId>
    <version>0.0.1version>
    <dependencies>
        <dependency>
            <groupId>org.freemarkergroupId>
            <artifactId>freemarkerartifactId>
            <version>2.3.23version>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.10version>
        dependency>
    dependencies>
project>
复制代码

2.3、添加存放模板的文件夹

在src/main/java的包下添加一个名为“templates”目录(包),用于存放所有的freemarker模板。

 2.4、添加模板

在src/main/java/templates目录下添加名为“product.ftl”的FreeMarker模板,模板的内容如下:

复制代码
----------产品详细----------
产品名称:${name}
产品价格:${price}
设计作者:<#list users as user> ${user} 
------------------------------
复制代码

模板中一般分为不可变部分与可变部分,如“产品名称:”这些常量内容就是不可以变化的,而${}与<#>这些内容是可以根据数据动态变化的。

2.5、解析模板

使用FreeMarker可以读取到模板内容,将数据与模板绑定并渲染出结果,很好的实现了表现与数据分离。新建一个测试类,代码如下:

复制代码
package com.zhangguo.freemarkerdemo;

import java.io.File;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class Test {

    public static void main(String[] args) throws Exception {
        
        //创建一个freemarker.template.Configuration实例,它是存储 FreeMarker 应用级设置的核心部分
        //指定版本号
        Configuration cfg=new Configuration(Configuration.VERSION_2_3_22);
        //设置模板目录
        cfg.setDirectoryForTemplateLoading(new File("src/main/java/templates"));
        //设置默认编码格式
        cfg.setDefaultEncoding("UTF-8");
        
        //数据
        Map product = new HashMap<>();
        product.put("name", "Huwei P8");
        product.put("price", "3985.7");
        product.put("users", new String[]{"Tom","Jack","Rose"});
        
        //从设置的目录中获得模板
        Template temp = cfg.getTemplate("product.ftl");
        
        //合并模板和数据模型
        Writer out = new OutputStreamWriter(System.out);
        temp.process(product, out);
        
        //关闭
        out.flush();
        out.close();
    }
}
复制代码

2.6、运行结果

三、动态页面静态化

动态页面静态化是指使用服务器后台技术将用户原来请求的动态页面变成静态内容缓存于服务器文件中,比如网站有一篇新闻名为由hot.jsp页面展示,默认情况下每当有客户端从服务器请求该新闻时服务器会解析hot.jsp页面渲染出静态内容响应给客户端,这样有一些问题,首先是每次请求都要解析服务器压力大,其次新闻的内容并没有真的存储在hot.jsp文件中而是存储在数据库里,对搜索引擎的爬虫不友好,不便SEO,另外访问动态的内容可能存在安全风险,如sql注入,XSS等网络攻击。解决办法是将hot.jsp页面静态化成一个叫hot.html的文件,服务器不再执行动态内容直接把静态页面响应给客户端,因为是纯静态的服务器压力会减轻,不担心网络安全问题;文章的内容直接存储在html文件中,对SEO友好。

3.1、动态页面静态化的优点

a) 利于搜索引擎优化(SEO)

b) 减轻服务器压力

c) 提高了网站的安全性

d) 加快了客户端的访问速度

3.2、动态页面静态化的问题

a) 页面过期与内容更新问题

如果一个页面的内容需要经常更新,就会要不断的生成新的静态页面,不是所有的页面都适合静态化。

b) 页面生成的问题

什么时候生成静态页面合适,有客户端第一次请求生成的,有定时生成的,也有后台管理时批量生成的。

c) 页面中部分内容是静态的,部分内容是动态的,如一篇文章的评论,访问次数,这些肯定不能静态。我暂时想到的办法是ajax和内嵌框架(iframe)

3.3、实现动态页面静态化

实现动态页面静态化的办法多种多样,这里使用FreeMarker,仅仅提供思路,代码没有封装与优化。

3.3.1、新建一个基于Maven的Web项目

 

3.3.2、添加依赖

这里没有使用MVC,只需依赖FreeMarker、Servlet与JSP核心包就可以了,修改后的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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.zhangguogroupId>
    <artifactId>SpringMVC71artifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>warpackaging>
    <dependencies>
        
        <dependency>
            <groupId>org.freemarkergroupId>
            <artifactId>freemarker-gaeartifactId>
            <version>2.3.25-incubatingversion>
        dependency>
        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.0.1version>
            <scope>providedscope>
        dependency>
        
        <dependency>
            <groupId>javax.servlet.jspgroupId>
            <artifactId>jsp-apiartifactId>
            <version>2.1version>
            <scope>providedscope>
        dependency>
    dependencies>
project>
复制代码

依赖成功的结果:

3.3.3、创建文章POJO类

在src/main/java源代码目录下创建Article.java文件,该类代表文章,代码如下:

复制代码
package com.zhangguo.springmvc71.entities;

/**
 * 文章
 *
 */
public class Article {
    /*
     * 编号
     */
    private int id;
    /*
     * 标题
     */
    private String title;
    /*
     * 内容
     */
    private String content;

    public Article() {
    }

    public Article(int id, String title, String content) {
        super();
        this.id = id;
        this.title = title;
        this.content = content;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
    }
}
复制代码

3.3.4、创建文章业务类

在src/main/java源代码目录下创建ArticleService.java文件,该类代表文章业务,主要提供文章数据,定义了一个文章集合中,初始化时向集合中随意添加了5个文章对象,代码如下:

复制代码
package com.zhangguo.springmvc71.Services;

import java.util.ArrayList;
import java.util.List;
import com.zhangguo.springmvc71.entities.Article;

/**
 * 文章业务类(模拟)
 *
 */
public class ArticleService {
    private static List
articles; static { articles = new ArrayList
(); articles.add(new Article(20160701, "不明真相的美国人被UFO惊呆了 其实是长征7号","据美国《洛杉矶时报》报道,当地时间周三晚(北京时间周四),在美国中西部的犹他州、内华达州、加利福利亚州,数千人被划过夜空的神秘火球吓到")); articles.add(new Article(20160702, "法国巴黎圣母院为教堂恐袭案遇害神父举行大弥撒", "而据美国战略司令部证实,其实这是中国长征七号火箭重新进入大气层,刚好经过加利福利亚附近。")); articles.add(new Article(20160703, "日东京知事候选人小池百合子回击石原:浓妆可以", "然而昨晚的美国人民可不明真相,有些人甚至怀疑这些火球是飞机解体,还有些人猜测是流星雨。")); articles.add(new Article(20160704, "日资慰安妇基金在首尔成立 韩国示威者闯入抗议","美国战略司令部发言人表示,到目前为止还没有任何受损报告,他说类似物体通常在大气中就会消失,这也解释了为何出现一道道光痕,这一切都并未造成什么威胁。")); articles.add(new Article(20160705, "中日关系正处十字路口日应寻求减少与华冲突","中国长征七号火箭6月25日在海南文昌航天发射中心首次发射,并成功升空进入轨道。有学者指出长征七号第二级火箭一直在地球低轨运行,一个月后重新进入大气层。")); } /** * 所有的文章 */ public List
getArticles() { return articles; } /* * 获得文章通过文章编号 */ public Article getArticle(int id) { for (Article article : articles) { if (article.getId() == id) { return article; } } return null; } }
复制代码

3.3.5、添加模板

在src/main/java源代码目录的templates包下添加两个模板,一个名为newsList.ftl用于生成新闻列表,另一个名为news.ftl用于生成单篇新闻,newsList.ftl文件内容如下:

复制代码
DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>新闻焦点title>
head>
<body>
    <div id="container">
    <h2>新闻焦点h2>
    <#setting number_format="#">
    <ul>
        <#list articles as article>
        <li>
            <a href="news/${article.id}.html">${article.title}a>
        li>
        #list>
    ul>
    div>
    <style>
       #container{
          font-family:"microsoft yahei";
          width:800px;
          margin:0 auto;
       }
       a{
         color:#333;
         text-decoration:none;
       }
       li{
         height:26px;
         line-height:26px;
       }
    style>
body>
html>
复制代码

文件中使用了FreeMarker标记,具体语法可以看第四点;news.ftl文件内容如下:

复制代码
DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${article.title}title>
head>
<body>
    <div id="container">
    <h2>${article.title}h2>
    <p>
         ${article.content}
    p>
    div>
    <style>
       #container{
          font-family:"microsoft yahei";
          width:800px;
          margin:0 auto;
       }
    style>
body>
html>
复制代码

3.3.6、添加Servlet生成静态页

新增一个名为News的Servlet类,当Servlet收到客户端请求时会查看系统中是否存在index.html(新闻列表)静态页面,如果存在直接转发,如果不存在则生成新闻列表静态页面及子页面。创建好的Servlet代码如下所示:

复制代码
package com.zhangguo.springmvc71.actions;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhangguo.springmvc71.Services.ArticleService;
import com.zhangguo.springmvc71.entities.Article;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 *新闻列表
 */
@WebServlet("/News")
public class News extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    ArticleService articleService=new ArticleService();
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        //设置编码格式与MIME类型
        response.setContentType("text/html; charset=UTF-8");
        
        //首页新闻列表路径
        String indexPath=request.getServletContext().getRealPath("/index.html");
        
        //文件是否存在
        File file=new File(indexPath);
        if(!file.exists()){
            //如果新闻列表不存在,生成新闻列表
            
            //创建一个freemarker.template.Configuration实例,它是存储 FreeMarker 应用级设置的核心部分
            //指定版本号
            Configuration cfg=new Configuration(Configuration.VERSION_2_3_22);
            //获得模板文件路径
            String templatePath=this.getClass().getClassLoader().getResource("/templates").getPath();
            //设置模板目录
            cfg.setDirectoryForTemplateLoading(new File(templatePath));
            //设置默认编码格式
            cfg.setDefaultEncoding("UTF-8");
            
            //数据
            Map articleData = new HashMap<>();
            List
articles=articleService.getArticles(); articleData.put("articles", articles); //从设置的目录中获得模板 Template template = cfg.getTemplate("newsList.ftl"); //合并模板和数据模型 try { //将数据与模板渲染的结果写入文件中 Writer writer=new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); template.process(articleData, writer); writer.flush(); articleData.clear(); template = cfg.getTemplate("news.ftl"); //生成单个新闻文件 for (Article article : articles) { articleData.put("article", article); //单个新闻文件 file=new File(request.getServletContext().getRealPath("/news/"+article.getId()+".html")); //文件输出流写入器 writer=new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); //将模板+数据生成的结果写入文件中,得到一个静态文件 template.process(articleData, writer); writer.flush(); } writer.close(); } catch (TemplateException e) { e.printStackTrace(); } } //如果新闻单页下存在,生成新闻单页 request.getRequestDispatcher("index.html").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
复制代码

从代码中可以看出生成的单篇文章全部存放在news目录下,要记得在webapp根目录下创建news目录。这里只是示例代码,如果要在项目中应用,应该把FreeMarker,文件操作的内容分Servlet分开。另外web.xml文件中添加index.html为第1个欢迎页,这样做的目的是当首页被生成时直接让服务器响应index.html。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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <welcome-file-list>
        <welcome-file>index.htmlwelcome-file>
        <welcome-file>index.jspwelcome-file>
    welcome-file-list>
web-app>
复制代码

index.jsp直接转发到News Servlet中,文件内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<jsp:forward page="News">jsp:forward>

3.3.7、运行结果

3.3.8、小结

再次强调这只是一个示例;另外你可能会想到FreeMarker在这里的作用感觉不大,如果我们使用一些特别的标记嵌套在静态的页面中,然后后台替换其实同样可以做到,确实这样也可以,但对于复杂的内容FreeMarker替换的方式要更加优雅,效率要更高,如果你使用jsp作为模板效果也是一样的,只是他们的侧重点不一样而已,有点想念razor了。

四、FreeMarker模板语法

要编写复杂的模板需要熟悉FreeMarker语法规则,官网有详细说明,中文帮助也比较详细了,下面这些内容是从网上收罗来的,感谢网友的分享,经过整理与修改的内容如下。建议直接看官网的文档。

4.0、模板文件的4个组成部分

FreeMarker模板文件主要由如下4个部分组成:

1,文本:直接输出的部分

2,注释:<#-- ... -->格式部分,不会输出

3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出

4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出

下面是一个FreeMarker模板的例子,包含了以上所说的4个部分

复制代码
<html>
<head>
<title>Welcome!title>
head>
<body>
<#--下面是文本将直接输出-->
Hello FreeMarker
<#-- 注释部分 -->
<#-- 下面使用插值 -->
<h1>Welcome ${user} !h1>
<u1>
<#-- 使用FTL指令 -->
<#list animals as being>
   <li>${being.name} for ${being.price} Euros
<#list>
<u1>
body>
html>
复制代码

4.1、FTL指令规则

在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的.
1.开始标签:<#指令名 参数> 如<#list users as user>
2.结束标签:
3.单标签:<#指令名 参数/>

实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号.
使用FTL标签时,应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是< , /> 和指令之间不允许有空白字符.

4.2、 插值规则

FreeMarker的插值有如下两种类型:

1、通用插值${expr};

2、数字格式化插值:#{expr}或#{expr;format}

可以简单理解为输出表达式

4.2.1 通用插值

对于通用插值,又可以分为以下4种情况:

1、插值结果为字符串值:直接输出表达式结果

2、插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:

<#setting number_format="currency"/> <#-- 设置数字格式为货币 -->

<#assign answer=42/>  <#-- 赋值 -->

${answer} <#-- 输出 -->

${answer?string} <#-- 输出格式为字符类型,与上面相同-->

${answer?string.number} <#-- 输出格式为数字类型-->

${answer?string.currency} <#-- 输出格式为货币类型-->

${answer?string.percent} <#-- 输出格式为百分比类型-->

输出结果是:

$42.00

$42.00

42

$42.00

4,200%

3,插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:

${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}

${lastUpdated?string("EEE, MMM d, ''yy")}

${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}

输出结果是:

2008-04-08 08:08:08 Pacific Daylight Time

Tue, Apr 8, '03

Tuesday, April 08, 2003, 08:08:08 PM (PDT)

4,插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:

<#assign foo=true/>
${foo?string("yes", "no")}
输出结果是:
yes

4.2.2 数字格式化插值

数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:
mX:小数部分最小X位
MX:小数部分最大X位
如下面的例子:
<#assign x=2.582/>
<#assign y=4/>
#{x; M2}
#{y; M2}
#{x; m2}
#{y; m2}
#{x; m1M2}
#{x; m1M2} 

输出结果:

2.58
4
2.58
4.00
2.58
2.58

4.3、表达式

表达式是FreeMarker模板的核心功能,表达式放置在插值语法${}之中时,表明需要输出表达式的值;表达式语法也可与FreeMarker标签结合,用于控制输出.实际上FreeMarker的表达式功能非常强大,它不仅支持直接指定值,输出变量值,也支持字符串格式化输出和集合访问等功能.

4.3.1、直接指定值

使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象.

1,字符串
直接指定字符串值使用单引号或双引号限定,如果字符串值中包含特殊字符需要转义,看下面的例子:
   

{'我名字是\"annlee\"'}
输出结果是: 
我的文件保存在C:\盘
我名字是"annlee"

FreeMarker支持如下转义字符:
\";双引号(u0022)
\';单引号(u0027)
\\;反斜杠(u005C)
\n;换行(u000A)
\r;回车(u000D)
\t;Tab(u0009)
\b;退格键(u0008)
\f;Form feed(u000C)
\l;<
\g;>
\a;&
\{;{
\xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.

如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码:
 

{r"C:\foo\bar"}
输出结果是:
${foo}
C:\foo\bar

2、数值
表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker目前还不支持科学计数法,所以"1E3"是错误的.在FreeMarker表达式中使用数值需要注意以下几点:
1、数值不能省略小数点前面的0,所以".5"是错误的写法
2、数值8 , +8 , 8.00都是相同的

3、布尔值
直接使用true和false,不使用引号.

4、集合
集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子:
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as week>
${week}

输出结果是:
星期一
星期二
星期三
星期四
星期五
星期六
星期天

除此之外,集合元素也可以是表达式,例子如下:
[2 + 2, [1, 2, 3, 4], "whatnot"]

还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..2

5,Map对象
Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子:
{"语文":78, "数学":80}
Map对象的key和value都是表达式,但是key必须是字符串

4.3.2、输出变量值

FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况

1、顶层变量
所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:
Map root = new HashMap();   //创建数据模型
root.put("name","annlee");   //name是一个顶层变量

对于顶层变量,直接使用线 

,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法:
${name}

2、输出集合元素
如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引:
["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法:
${week[2]}   //输出第三个集合元素

此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法:
week[3..5]   //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素

3、输出Map元素
这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:
Map root = new HashMap();
Book book = new Book();
Author author = new Author();
author.setName("annlee");
author.setAddress("gz");
book.setName("struts2");
book.setAuthor(author);
root.put("info","struts");
root.put("book", book);

为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法:
book.author.name    //全部使用点语法
book["author"].name
book.author["name"]    //混合使用点语法和方括号语法
book["author"]["name"]   //全部使用方括号语法

使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.

4.3.3、字符串操作

FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等.

字符串连接有两种语法:
1、使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接.
2、直接使用连接运算符+来连接字符串

例如有如下数据模型:
Map root = new HashMap();

root.put("user","annlee");
下面将user变量和常量连接起来:
使 

{"hello, " + user + "!"} //使用+号来连接
上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样.

值得注意的是,{..}只能用于文本部分,不能用于表达式,下面的代码是错误的: <#if

{isBig}>Wow!
<#if "${isBig}">Wow!
应该写成:<#if isBig>Wow!

截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型:
Map root = new HashMap();

root.put("book","struts2,freemarker");
可以通过如下语法来截取子串:
 

{book[4]}   //结果是st
${book[1..4]}     //结果是trut

4.3.4、集合连接运算符

这里所说的集合运算符是将两个集合连接成一个新的集合,连接集合的运算符是+,看如下的例子:
<#list ["星期一","星期二","星期三"] + ["星期四","星期五","星期六","星期天"] as week>
${week}

输出结果是:星期一 星期二 星期三 星期四 星期五 星期六 星期天

4.3.5、Map连接运算符

Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:
<#assign scores = {"语文":86,"数学":78} + {"数学":87,"Java":93}>
语文成绩是 

{scores.数学}
Java成绩是${scores.Java}

输出结果是:

语文成绩是86
数学成绩是87
Java成绩是93

4.3.6、算术运算符

FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , % 看如下的代码:
<#assign x=5>
 

{ x /2 }
${ 12 %10 }
输出结果是:

-75
2.5
2

在表达式中使用算术运算符时要注意以下几点:
1、运算符两边的运算数字必须是数字
2、使用+运算符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串再连接,如:${3 + "5"},结果是:35

使用内建的int函数可对数值取整,如:
<#assign x=5>
 

{ 1.1?int }
 

{ -1.1?int }
${ -1.999?int }
结果是:

2
1
1
-1
-1

4.3.7、比较运算符

表达式中支持的比较运算符有如下几个:
1,=或者==:判断两个值是否相等.
2,!=:判断两个值是否不等.
3,>或者gt:判断左边值是否大于右边值
4,>=或者gte:判断左边值是否大于等于右边值
5,<或者lt:判断左边值是否小于右边值
6,<=或者lte:判断左边值是否小于等于右边值

注意:=和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>

4.3.8、逻辑运算符

逻辑运算符有如下几个:
逻辑与:&&
逻辑或:||
逻辑非:!
逻辑运算符只能作用于布尔值,否则将产生错误

4.3.9、内建函数

FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来轮换输出变量.下面是常用的内建的字符串函数:
html:对字符串进行HTML编码
cap_first:使字符串第一个字母大写
lower_case:将字符串转换成小写
upper_case:将字符串转换成大写
trim:去掉字符串前后的空白字符

下面是集合的常用内建函数
size:获取序列中元素的个数

下面是数字值的常用内建函数
int:取得数字的整数部分,结果带符号

例如:
<#assign test="Tom & Jerry">
 

{test?upper_case?html}
结果是:

Tom & Jerry
TOM & JERRY

4.3.10、空值处理运算符

FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同.

为了处理缺失变量,FreeMarker提供了两个运算符:
!:指定缺失变量的默认值
??:判断某个变量是否存在

其中,!运算符的用法有如下两种:
variable!或variable!defaultValue,第一种用法不给缺失的变量指定默认值,表明默认值是空字符串,长度为0的集合,或者长度为0的Map对象.

使用!指定默认值时,并不要求默认值的类型和变量类型相同.使用??运算符非常简单,它总是返回一个布尔值,用法为:variable??,如果该变量存在,返回true,否则返回false

示例:

${tom!"tom is missed"}
<#if !jack??>jack is missed

输出:

tom is missed
jack is missed

4.3.11、运算符的优先级

FreeMarker中的运算符优先级如下(由高到低排列):
1,一元运算符:!
2,内建函数:?
3,乘除法:*, / , %
4,加减法:- , +
5,比较:> , < , >= , <= (lt , lte , gt , gte)
6,相等:== , = , !=
7,逻辑与:&&
8,逻辑或:||
9,数字范围:..

实际上,我们在开发过程中应该使用括号来严格区分,这样的可读性好,出错少

4.4、FreeMarker的常用指令

FreeMarker的FTL指令也是模板的重要组成部分,这些指令可实现对数据模型所包含数据的抚今迭代,分支控制.除此之外,还有一些重要的功能,也是通过FTL指令来实现的.

4.4.1、if指令

这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:
<#if condition>...
<#elseif condition>...
<#elseif condition>...
<#else> ...

例子如下:
<#assign age=23>
<#if (age>60)>老年人
<#elseif (age>40)>中年人
<#elseif (age>20)>青年人
<#else> 少年人

输出结果是:青年人
上面的代码中的逻辑表达式用括号括起来主要是因为里面有>符号,由于FreeMarker会将>符号当成标签的结束字符,可能导致程序出错,为了避免这种情况,我们应该在凡是出现这些符号的地方都使用括号.

4.4.2、switch , case , default , break指令

这些指令显然是分支指令,作用类似于Java的switch语句,switch指令的语法结构如下:
<#switch value>
<#case refValue>...<#break>
<#case refValue>...<#break>
<#default>...

示例:

<#assign level=1>
<#switch level>
<#case 1>A级<#break>
<#case 2>B级<#break>
<#case 3>C级<#break>
<#default>未知级别

输出:

A级

4.4.3、list, break指令

list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:
<#list sequence as item>
...

上面的语法格式中,sequence就是一个集合对象,也可以是一个表达式,但该表达式将返回一个集合对象,而item是一个任意的名字,就是被迭代输出的集合元素.此外,迭代集合对象时,还包含两个特殊的循环变量:
item_index:当前变量的索引值
item_has_next:是否存在下一个对象
也可以使用<#break>指令跳出迭代

示例:

<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as week>
   

{week}<#if week_has_next>,
<#if week="星期四"><#break>

输出结果:

1.星期一,
2.星期二,
3.星期三,
4.星期四,

4.4.4、include指令

include指令的作用类似于JSP的包含指令,用于包含指定页.include指令的语法格式如下:
<#include filename [options]>
在上面的语法格式中,两个参数的解释如下:
filename:该参数指定被包含的模板文件
options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,其中encoding指定包含页面时所用的解码集,而parse指定被包含文件是否作为FTL文件来解析,如果省略了parse选项值,则该选项默认是true.

4.4.5、import指令

该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import指令的语法格式如下:
<#import "/lib/common.ftl" as com>
上面的代码将导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中.

4.4.6、noparse指令

noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:
<#noparse>...

看如下的例子:
<#noparse>
<#list books as book>
    

{book.author}


输出如下:
<#list books as book>
    

{book.author}

4.4.7、escape , noescape指令

escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:
<#escape identifier as expression>...
<#noescape>...

看如下的代码:
<#escape x as x?html>
First name: 

{lastName}
Maiden name: {maidenName}  上面的代码等同于: First name:{firstName?html}
Last name:  

{maidenName?html}

escape指令在解析模板时起作用而不是在运行时起作用,除此之外,escape指令也嵌套使用,子escape继承父escape的规则,如下例子:
<#escape x as x?html>
Customer Name:{customerName} Items to ship; <#escape x as itemCodeToNameMap[x]>

{itemCode1}
    {itemCode3}
   {itemCode4}   上面的代码类似于: Customer Name:{customerName?html}
Items to ship;
 {itemCodeToNameMap[itemCode2]?html}
 

{itemCodeToNameMap[itemCode4]?html}

对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape指令中的插值将不会添加escape表达式.

4.4.8、assign指令

assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign指令的用法有多种,包含创建或替换一个顶层变量,或者创建或替换多个变量等,它的最简单的语法如下:<#assign name=value [in namespacehash]>,这个用法用于指定一个名为name的变量,该变量的值为value,此外,FreeMarker允许在使用assign指令里增加in子句,in子句用于将创建的name变量放入namespacehash命名空间中.

assign指令还有如下用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>,这个语法可以同时创建或替换多个顶层变量,此外,还有一种复杂的用法,如果需要创建或替换的变量值是一个复杂的表达式,则可以使用如下语法格式:<#assign name [in namespacehash]>capture this,在这个语法中,是指将assign指令的内容赋值给name变量.如下例子:
<#assign weeks>
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
{n}  

{weeks}
上面的代码将产生如下输出:星期一 星期二 星期三 星期四 星期五 星期六 星期天

虽然assign指定了这种复杂变量值的用法,但是我们也不要滥用这种用法,如下例子:<#assign x>Hello {user}!,以上代码改为如下写法更合适:<#assign x="Hello

{user}!">

4.4.9、setting指令

该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
locale:该选项指定该模板所用的国家/语言选项
number_format:指定格式化输出数字的格式
boolean_format:指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format:指定格式化输出日期的格式
time_zone:设置格式化输出日期时所使用的时区

4.4.10、macro , nested , return指令

macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:
<#macro name param1 param2 ... paramN>
...
<#nested loopvar1, loopvar2, ..., loopvarN>
...
<#return>
...

在上面的格式片段中,包含了如下几个部分:
name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
nested指令:nested标签输出使用自定义指令时的中间部分
nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板
return指令:该指令可用于随时结束该自定义指令.

看如下的例子:
<#macro book>   //定义一个自定义指令
j2ee

<@book />    //使用刚才定义的指令
上面的代码输出结果为:j2ee

在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:
<#macro book booklist>     //定义一个自定义指令booklist是参数
<#list booklist as book>
   ${book}


<@book booklist=["spring","j2ee"] />   //使用刚刚定义的指令
上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:spring j2ee

不仅如此,还可以在自定义指令时使用nested指令来输出自定义指令的中间部分,看如下例子:
<#macro page title>


   FreeMarker示例页面 - <span class="MathJax"><span class="math" style="width:26.002em;"><span style="width:20.8em;height:0px;font-size:125%;"><span class="mrow"><span class="texatom"><span class="mrow"><span class="mi"><img src="http://img.e-com-net.com/image/info8/f27980ad1e244245814d0c58b1e00d0b.png" style="width:7px;height:11px;margin-right:.029em;" alt="" width="6" height="10"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f31d8223214241b08aa43ce88c575890.png" style="width:6px;height:12px;margin-right:.041em;" alt="" width="5" height="11"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f27980ad1e244245814d0c58b1e00d0b.png" style="width:7px;height:11px;margin-right:.029em;" alt="" width="6" height="10"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/8cd4ce894a8b4e4689a4deecf3af5cc1.png" style="width:6px;height:13px;margin-right:.03em;" alt="" width="5" height="12"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/b532503f7c53496195667b334850bf8b.png" style="width:9px;height:8px;margin-right:.035em;" alt="" width="8" height="7"></span><span class="mo"><img src="http://img.e-com-net.com/image/info8/cfa0b4488c54443383ce3f26bd81e997.png" style="width:8px;height:13px;margin-right:.053em;" alt="" width="7" height="12"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/0fded78197184fd88c7e42ac48afd377.png" style="width:11px;height:12px;margin-right:.02em;" alt="" width="10" height="11"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f27980ad1e244245814d0c58b1e00d0b.png" style="width:7px;height:11px;margin-right:.029em;" alt="" width="6" height="10"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/b8f91c81e9df414ca65a1e651b273a6b.png" style="width:17px;height:8px;margin-right:.02em;" alt="" width="15" height="7"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/8cd4ce894a8b4e4689a4deecf3af5cc1.png" style="width:6px;height:13px;margin-right:.03em;" alt="" width="5" height="12"></span></span></span><span class="mo" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/90e7458e35fe488daea7025fe3362acd.png" style="width:13px;height:12px;margin-right:.079em;" alt="" width="12" height="11"></span><span class="texatom" style="padding-left:.278em;"><span class="mrow"><span class="mo"><img src="http://img.e-com-net.com/image/info8/1e3436fb11e644a59046de7e321a123a.png" style="width:9px;height:20px;vertical-align:-4px;margin-right:.052em;" alt="" width="0" height="0"></span></span></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f27980ad1e244245814d0c58b1e00d0b.png" style="width:7px;height:11px;margin-right:.029em;" alt="" width="6" height="10"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f31d8223214241b08aa43ce88c575890.png" style="width:6px;height:12px;margin-right:.041em;" alt="" width="5" height="11"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/f27980ad1e244245814d0c58b1e00d0b.png" style="width:7px;height:11px;margin-right:.029em;" alt="" width="6" height="10"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/8cd4ce894a8b4e4689a4deecf3af5cc1.png" style="width:6px;height:13px;margin-right:.03em;" alt="" width="5" height="12"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/b532503f7c53496195667b334850bf8b.png" style="width:9px;height:8px;margin-right:.035em;" alt="" width="8" height="7"></span><span class="mo" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/21d553d0b93c41ebb4249e0788a4a415.png" style="width:13px;height:12px;vertical-align:-1px;margin-right:.079em;" alt="" width="12" height="11"><img src="http://img.e-com-net.com/image/info8/90e7458e35fe488daea7025fe3362acd.png" style="width:13px;height:12px;margin-right:.079em;" alt="" width="12" height="11"></span><span class="texatom" style="padding-left:.278em;"><span class="mrow"><span class="mo"><img src="http://img.e-com-net.com/image/info8/1e3436fb11e644a59046de7e321a123a.png" style="width:9px;height:20px;vertical-align:-4px;margin-right:.052em;" alt="" width="0" height="0"></span></span></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/0fded78197184fd88c7e42ac48afd377.png" style="width:11px;height:12px;margin-right:.02em;" alt="" width="10" height="11"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/b532503f7c53496195667b334850bf8b.png" style="width:9px;height:8px;margin-right:.035em;" alt="" width="8" height="7"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/b41aaf60082346519b13c74224ee180e.png" style="width:10px;height:8px;margin-right:.022em;" alt="" width="9" height="7"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/5044c4e0629a490d813ab5998f76fd9f.png" style="width:10px;height:12px;margin-right:-.003em;" alt="" width="9" height="11"><span style="height:1px;width:.003em;"></span></span><span class="mo" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/21d553d0b93c41ebb4249e0788a4a415.png" style="width:13px;height:12px;vertical-align:-1px;margin-right:.079em;" alt="" width="12" height="11"><img src="http://img.e-com-net.com/image/info8/90e7458e35fe488daea7025fe3362acd.png" style="width:13px;height:12px;margin-right:.079em;" alt="" width="12" height="11"></span><span class="mi" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/a94ebf95c62242b68d99f4231e6dfb9b.png" style="width:8px;height:12px;margin-right:.007em;" alt="" width="7" height="11"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/79bd6177cecc4a2497546b925791759a.png" style="width:9px;height:8px;margin-right:.009em;" alt="" width="8" height="7"></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/5044c4e0629a490d813ab5998f76fd9f.png" style="width:10px;height:12px;margin-right:-.003em;" alt="" width="9" height="11"><span style="height:1px;width:.003em;"></span></span><span class="mi"><img src="http://img.e-com-net.com/image/info8/cdcc82b7c42e4d0bbbc1ed8879e80f8b.png" style="width:10px;height:11px;vertical-align:-3px;margin-right:-.006em;" alt="" width="9" height="10"><span style="height:1px;width:.006em;"></span></span><span class="mo" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/21d553d0b93c41ebb4249e0788a4a415.png" style="width:13px;height:12px;vertical-align:-1px;margin-right:.079em;" alt="" width="12" height="11"><img src="http://img.e-com-net.com/image/info8/90e7458e35fe488daea7025fe3362acd.png" style="width:13px;height:12px;margin-right:.079em;" alt="" width="12" height="11"></span><span class="mi" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/0fded78197184fd88c7e42ac48afd377.png" style="width:11px;height:12px;margin-right:.02em;" alt="" width="10" height="11"></span><span class="mn"><img src="http://img.e-com-net.com/image/info8/eed9cd29bedf4c718d7a8e1493222ae0.png" style="width:9px;height:13px;margin-right:.069em;" alt="" width="8" height="12"></span><span class="mo" style="padding-left:.278em;"><img src="http://img.e-com-net.com/image/info8/21d553d0b93c41ebb4249e0788a4a415.png" style="width:13px;height:12px;vertical-align:-1px;margin-right:.079em;" alt="" width="12" height="11"></span></span> <span style="width:0px;height:2.35em;"></span></span><span style="vertical-align:-.358em;border-left:0px solid;width:0px;height:1.306em;"></span></span></span></p> <p>{title?html}</h1><br>   <#nested>      //用于引入用户自定义指令的标签体<br></body><br></html><br></#macro><br>上面的代码将一个HTML页面模板定义成一个page指令,则可以在其他页面中如此page指令:<br><#import "/common.ftl" as com>     //假设上面的模板页面名为common.ftl,导入页面<br><@com.page title="book list"><br><u1><br><li>spring</li><br><li>j2ee</li><br></ul><br></@com.page></p> <p>从上面的例子可以看出,使用macro和nested指令可以非常容易地实现页面装饰效果,此外,还可以在使用nested指令时,指定一个或多个循环变量,看如下代码:<br><#macro book><br><#nested 1>      //使用book指令时指定了一个循环变量值<br><#nested 2><br></#macro><br><@book ;x> ${x} .图书</@book><br>当使用nested指令传入变量值时,在使用该自定义指令时,就需要使用一个占位符(如book指令后的;x).上面的代码输出文本如下:<br>1 .图书    2 .图书</p> <p>在nested指令中使用循环变量时,可以使用多个循环变量,看如下代码:</p> <p><#macro repeat count><br><#list 1..count as x> <br> <#nested x, x/2, x==count><br></#list><br></#macro></p> <p><@repeat count=4 ;c,halfc,last><br><span class="MathJax"><span class="math" style="width:.352em;"><span style="width:.25em;height:0px;font-size:125%;"><span class="mrow"><span class="texatom"><span class="mrow"><span class="mi"><img src="http://img.e-com-net.com/image/info8/903d8aab07a34ab7a56a442176c90cbf.png" style="width:9px;height:8px;margin-right:.004em;" alt="" width="8" height="7"></span></span></span><span class="mo"><img src="http://img.e-com-net.com/image/info8/db525c82c2e54a59a02738476bb50537.png" style="width:4px;height:3px;margin-right:.075em;" alt="" width="4" height="3"></span></span> <span style="width:0px;height:2.35em;"></span></span><span style="vertical-align:-.075em;border-left:0px solid;width:0px;height:.66em;"></span></span></span></p> <p>{halfc}<#if last> Last! </#if><br></@repeat></p> <p><br>输出结果:</p> <p>1. 0.5<br>2. 1<br>3. 1.5<br>4. 2 Last! </p> <p>return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容,看如下代码:<br><#macro book><br>spring<br><#return><br>j2ee<br></#macro><br><@book /><br>上面的代码输出:spring,而j2ee位于return指令之后,不会输出。</p> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1697650678773657600"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(spring,mvc)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1835513551624695808.htm" title="【iOS】MVC设计模式" target="_blank">【iOS】MVC设计模式</a> <span class="text-muted">Magnetic_h</span> <a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/objective-c/1.htm">objective-c</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a> <div>MVC前言如何设计一个程序的结构,这是一门专门的学问,叫做"架构模式"(architecturalpattern),属于编程的方法论。MVC模式就是架构模式的一种。它是Apple官方推荐的App开发架构,也是一般开发者最先遇到、最经典的架构。MVC各层controller层Controller/ViewController/VC(控制器)负责协调Model和View,处理大部分逻辑它将数据从Mod</div> </li> <li><a href="/article/1835479758033481728.htm" title="SpringBlade dict-biz/list 接口 SQL 注入漏洞" target="_blank">SpringBlade dict-biz/list 接口 SQL 注入漏洞</a> <span class="text-muted">文章永久免费只为良心</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>SpringBladedict-biz/list接口SQL注入漏洞POC:构造请求包查看返回包你的网址/api/blade-system/dict-biz/list?updatexml(1,concat(0x7e,md5(1),0x7e),1)=1漏洞概述在SpringBlade框架中,如果dict-biz/list接口的后台处理逻辑没有正确地对用户输入进行过滤或参数化查询(PreparedSta</div> </li> <li><a href="/article/1835458199755517952.htm" title="spring如何整合druid连接池?" target="_blank">spring如何整合druid连接池?</a> <span class="text-muted">惜.己</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/junit/1.htm">junit</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/idea/1.htm">idea</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a> <div>目录spring整合druid连接池1.新建maven项目2.新建mavenModule3.导入相关依赖4.配置log4j2.xml5.配置druid.xml1)xml中如何引入properties2)下面是配置文件6.准备jdbc.propertiesJDBC配置项解释7.配置druid8.测试spring整合druid连接池1.新建maven项目打开IDE(比如IntelliJIDEA,Ecl</div> </li> <li><a href="/article/1835449364223455232.htm" title="SpringCloudAlibaba—Sentinel(限流)" target="_blank">SpringCloudAlibaba—Sentinel(限流)</a> <span class="text-muted">菜鸟爪哇</span> <div>前言:自己在学习过程的记录,借鉴别人文章,记录自己实现的步骤。借鉴文章:https://blog.csdn.net/u014494148/article/details/105484410Sentinel介绍Sentinel诞生于阿里巴巴,其主要目标是流量控制和服务熔断。Sentinel是通过限制并发线程的数量(即信号隔离)来减少不稳定资源的影响,而不是使用线程池,省去了线程切换的性能开销。当资源</div> </li> <li><a href="/article/1835448238103162880.htm" title="springboot+vue项目实战一-创建SpringBoot简单项目" target="_blank">springboot+vue项目实战一-创建SpringBoot简单项目</a> <span class="text-muted">苹果酱0567</span> <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E9%97%B4%E4%BB%B6/1.htm">中间件</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>这段时间抽空给女朋友搭建一个个人博客,想着记录一下建站的过程,就当做笔记吧。虽然复制zjblog只要一个小时就可以搞定一个网站,或者用cms系统,三四个小时就可以做出一个前后台都有的网站,而且想做成啥样也都行。但是就是要从新做,自己做的意义不一样,更何况,俺就是专门干这个的,嘿嘿嘿要做一个网站,而且从零开始,首先呢就是技术选型了,经过一番思量决定选择-SpringBoot做后端,前端使用Vue做一</div> </li> <li><a href="/article/1835443569968640000.htm" title="Spring MVC 全面指南:从入门到精通的详细解析" target="_blank">Spring MVC 全面指南:从入门到精通的详细解析</a> <span class="text-muted">一杯梅子酱</span> <a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%A0%88%E5%AD%A6%E4%B9%A0/1.htm">技术栈学习</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>引言:SpringMVC,作为Spring框架的一个重要模块,为构建Web应用提供了强大的功能和灵活性。无论是初学者还是有一定经验的开发者,掌握SpringMVC都将显著提升你的Web开发技能。本文旨在为初学者提供一个全面且易于理解的学习路径,通过详细的知识点分析和实际案例,帮助你快速上手SpringMVC,让学习过程既深刻又高效。一、SpringMVC简介1.1什么是SpringMVC?Spri</div> </li> <li><a href="/article/1835438028768768000.htm" title="Spring Boot中实现跨域请求" target="_blank">Spring Boot中实现跨域请求</a> <span class="text-muted">BABA8891</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>在SpringBoot中实现跨域请求(CORS,Cross-OriginResourceSharing)可以通过多种方式,以下是几种常见的方法:1.使用@CrossOrigin注解在SpringBoot中,你可以在控制器或者具体的请求处理方法上使用@CrossOrigin注解来允许跨域请求。在控制器上应用:importorg.springframework.web.bind.annotation.</div> </li> <li><a href="/article/1835437775344726016.htm" title="博客网站制作教程" target="_blank">博客网站制作教程</a> <span class="text-muted">2401_85194651</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>首先就是技术框架:后端:Java+SpringBoot数据库:MySQL前端:Vue.js数据库连接:JPA(JavaPersistenceAPI)1.项目结构blog-app/├──backend/│├──src/main/java/com/example/blogapp/││├──BlogApplication.java││├──config/│││└──DatabaseConfig.java</div> </li> <li><a href="/article/1835428695603507200.htm" title="RabbitMQ生产者重复机制与确认机制" target="_blank">RabbitMQ生产者重复机制与确认机制</a> <span class="text-muted">java炒饭小能手</span> <a class="tag" taget="_blank" href="/search/java-rabbitmq/1.htm">java-rabbitmq</a><a class="tag" taget="_blank" href="/search/rabbitmq/1.htm">rabbitmq</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>重复机制生产者发送消息时,出现了网络故障,导致与MQ的连接中断。为了解决这个问题,SpringAMQP提供的消息发送时的重试机制。即:当RabbitTemplate与MQ连接超时后,多次重试。需要修该发送端模块的application.yaml文件,添加下面的内容:spring:rabbitmq:connection-timeout:1s#设置MQ的连接超时时间template:retry:ena</div> </li> <li><a href="/article/1835388481887629312.htm" title="【Java】已解决:org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException" target="_blank">【Java】已解决:org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException</a> <span class="text-muted">屿小夏</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>文章目录一、分析问题背景问题背景描述出现问题的场景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项已解决:org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException在使用Spring框架进行开发时,数据源的配置和使用是非常关键的一环。然而,有时候我们可能会遇到org.springframewo</div> </li> <li><a href="/article/1835380041006018560.htm" title="SpringBoot和SpringMVC是什么关系?SpringBoot替代SpringMVC了吗?" target="_blank">SpringBoot和SpringMVC是什么关系?SpringBoot替代SpringMVC了吗?</a> <span class="text-muted">瑞金彭于晏</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/MVC/1.htm">MVC</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>SpringBoot和SpringMVC都是SpringFramework生态系统中的一部分,但它们各自扮演着不同的角色和提供不同的功能集。理解它们之间的关系,首先需要了解SpringFramework本身。SpringFrameworkSpringFramework是一个全面的、开源的应用程序开发框架,它提供了广泛的功能来支持企业应用开发的几乎所有方面。SpringFramework的核心特性之</div> </li> <li><a href="/article/1835379153730367488.htm" title="spring mvc @RequestBody String类型参数" target="_blank">spring mvc @RequestBody String类型参数</a> <span class="text-muted">zoyation</span> <a class="tag" taget="_blank" href="/search/spring-mvc/1.htm">spring-mvc</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a> <div>通过如下配置:text/html;charset=UTF-8application/json;charset=UTF-8在springmvc的Controller层使用@RequestBody接收Content-Type为application/json的数据时,默认支持Map方式和对象方式参数@RequestMapping(value="/{code}/saveUser",method=Requ</div> </li> <li><a href="/article/1835373226490949632.htm" title="Java -jar 如何在后台运行项目" target="_blank">Java -jar 如何在后台运行项目</a> <span class="text-muted">vincent_hahaha</span> <div>撸了今年阿里、头条和美团的面试,我有一个重要发现.......>>>说到运行jar包通常我们都会以下面的方式运行:java-jarspringboot-0.0.1-SNAPSHOT.jar这样运行的话会有一个问题,就是我们一关闭当前窗口就会停止运行项目,要想解决这个问题,就需要在后台运行。nohupjava-jarbabyshark-0.0.1-SNAPSHOT.jar >log.file 2>&</div> </li> <li><a href="/article/1835372847959207936.htm" title="spring security中几大组件的作用和执行顺序" target="_blank">spring security中几大组件的作用和执行顺序</a> <span class="text-muted">阿信在这里</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>springsecurity中几大组件的作用和执行顺序在SpringSecurity中,AuthenticationProvider、GroupPermissionEvaluator、PermissionEvaluator、AbstractAuthenticationProcessingFilter、DefaultMethodSecurityExpressionHandler和ManageSecu</div> </li> <li><a href="/article/1835362136054919168.htm" title="探索Zebra4J:构建高效企业级Web应用的微服务框架" target="_blank">探索Zebra4J:构建高效企业级Web应用的微服务框架</a> <span class="text-muted">叶准鑫Natalie</span> <div>探索Zebra4J:构建高效企业级Web应用的微服务框架ZebraZebra4J/Zebra4Js基于SpringBoot的JavaWeb/Nodejs框架项目地址:https://gitcode.com/gh_mirrors/zebra/Zebra项目介绍在当今快速发展的技术环境中,构建高效、可扩展的企业级Web应用是每个开发团队的追求。Zebra4J作为一款基于SpringBoot的全新微服务</div> </li> <li><a href="/article/1835360363776929792.htm" title="MySQL事务隔离级别和MVCC" target="_blank">MySQL事务隔离级别和MVCC</a> <span class="text-muted">简书徐小耳</span> <div>MySQL事务隔离级别和MVCC参考:https://mp.weixin.qq.com/s/Jeg8656gGtkPteYWrG5_Nw1.MVCC只对读已提交和可重复的读有效果,而未提交读和串行则无意义。2.每条记录都会有trx_id(事务修改记录的id)和roll_pointer是一个指针指向旧版本的undo日志链表(row_id不是必必要的,如果有主键存在就不需要了)3.版本链的头结点就是记</div> </li> <li><a href="/article/1835344485802930176.htm" title="基于JavaWeb开发的Java+SpringMvc+vue+element实现上海汽车博物馆平台" target="_blank">基于JavaWeb开发的Java+SpringMvc+vue+element实现上海汽车博物馆平台</a> <span class="text-muted">网顺技术团队</span> <a class="tag" taget="_blank" href="/search/%E6%88%90%E5%93%81%E7%A8%8B%E5%BA%8F%E9%A1%B9%E7%9B%AE/1.htm">成品程序项目</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E6%B1%BD%E8%BD%A6/1.htm">汽车</a><a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a> <div>基于JavaWeb开发的Java+SpringMvc+vue+element实现上海汽车博物馆平台作者主页网顺技术团队欢迎点赞收藏⭐留言文末获取源码联系方式查看下方微信号获取联系方式承接各种定制系统精彩系列推荐精彩专栏推荐订阅不然下次找不到哟Java毕设项目精品实战案例《1000套》感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人文章目录基</div> </li> <li><a href="/article/1835343473629294592.htm" title="分布式锁和spring事务管理" target="_blank">分布式锁和spring事务管理</a> <span class="text-muted">暴躁的鱼</span> <a class="tag" taget="_blank" href="/search/%E9%94%81%E5%8F%8A%E4%BA%8B%E5%8A%A1/1.htm">锁及事务</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>最近开发一个小程序遇到一个需求需要实现分布式事务管理业务需求用户在使用小程序的过程中可以查看景点,对景点地区或者城市标记是否想去,那么需要统计一个地点被标记的人数,以及记录某个用户对某个地点是否标记为想去,用两个表存储数据,一个地点表记录改地点被标记的次数,一个用户意向表记录某个用户对某个地点是否标记为想去。由于可能有多个用户同时标记一个地点,每个用户在前端点击想去按钮之后,后台接收到请求,从数据</div> </li> <li><a href="/article/1835310380474265600.htm" title="Java面试笔记记录6" target="_blank">Java面试笔记记录6</a> <span class="text-muted">今天背八股了吗</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>1.Spring是什么?特性?有哪些模块?Spring是一个轻量级、非入侵式的控制反转Ioc和面向切面AOP的框架。特性:1.Ioc和DISpring的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成Bean,并且管理Bean的生命周期,实现高内聚低耦合的设计理念。2.AOP编程Spring提供面向切面编程,可以方便实现对程序进行权限拦截、运行监控等切面功能。3</div> </li> <li><a href="/article/1835292113768640512.htm" title="Sentinel" target="_blank">Sentinel</a> <span class="text-muted">眼泪落在琴弦</span> <a class="tag" taget="_blank" href="/search/springcloud/1.htm">springcloud</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>Sentinel(服务熔断降级限流)1.引入spring-cloud-starter-alibaba-sentinel2.下载sentinel服务器3.配置application地址信息4.在控制台调整参数【默认所以流控设置保存在内存中,重启失效】5.想实时监控需每个微服务导入actuator,并配置application暴露所有端口6.自定义sentinel流控返回数据7.配置sentinel类</div> </li> <li><a href="/article/1835278504103604224.htm" title="Spring @Async 深度解读:默认线程池执行器的配置与优化" target="_blank">Spring @Async 深度解读:默认线程池执行器的配置与优化</a> <span class="text-muted">小码快撩</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>在Spring中,@Async注解用于异步执行方法。默认情况下,@Async注解的任务是由一个线程池执行的。然而,这个默认的线程池是如何初始化的呢?本文将深入探讨这一过程,帮助你理解Spring异步任务背后的线程池执行器的初始化原理。1.@Async的基本使用首先,让我们快速回顾一下@Async的基本用法。@Async通常用于标注在需要异步执行的方法上,比如:@Servicepublicclass</div> </li> <li><a href="/article/1835277244763828224.htm" title="Sentinel实时监控不展示问题" target="_blank">Sentinel实时监控不展示问题</a> <span class="text-muted">朱杰jjj</span> <a class="tag" taget="_blank" href="/search/sentinel/1.htm">sentinel</a><a class="tag" taget="_blank" href="/search/sentinel/1.htm">sentinel</a> <div>问题官方插件Endpoint支持,可以实时统计出SpringBoot的健康状况和请求的调用信息在使用Endpoint特性之前需要在Maven中添加spring-boot-starter-actuator依赖,并在配置中允许Endpoints的访问。SpringBoot1.x中添加配置management.security.enabled=false。暴露的endpoint路径为/sentinelS</div> </li> <li><a href="/article/1835273340084908032.htm" title="36. MyBatis如何支持多数据库操作?如何配置不同的数据源?" target="_blank">36. MyBatis如何支持多数据库操作?如何配置不同的数据源?</a> <span class="text-muted">这孩子叫逆</span> <a class="tag" taget="_blank" href="/search/Mybatis%E7%AC%94%E8%AE%B0/1.htm">Mybatis笔记</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>在许多企业级应用中,可能需要访问多个数据库。MyBatis可以通过配置多个数据源和动态切换数据源来支持多数据库操作。下面介绍如何在MyBatis中配置和使用多个数据源。1.多数据源的基本配置1.1配置多个数据源要支持多个数据源,首先需要在Spring或SpringBoot中配置不同的数据源。假设我们要连接两个数据库db1和db2,可以通过以下步骤进行配置。SpringBoot示例:applicat</div> </li> <li><a href="/article/1835262244313722880.htm" title="SpringBoot整合ES搜索引擎 实现网站热搜词及热度计算" target="_blank">SpringBoot整合ES搜索引擎 实现网站热搜词及热度计算</a> <span class="text-muted">码踏云端</span> <a class="tag" taget="_blank" href="/search/springboot/1.htm">springboot</a><a class="tag" taget="_blank" href="/search/Elasticsearch/1.htm">Elasticsearch</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/elasticsearch/1.htm">elasticsearch</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E7%83%AD%E6%90%9C%E8%AF%8D/1.htm">热搜词</a><a class="tag" taget="_blank" href="/search/%E7%83%AD%E5%BA%A6%E8%AE%A1%E7%AE%97/1.htm">热度计算</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>博主简介:历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于</div> </li> <li><a href="/article/1835260978816708608.htm" title="数据库系统 第53节 数据库并发控制" target="_blank">数据库系统 第53节 数据库并发控制</a> <span class="text-muted">hummhumm</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/database/1.htm">database</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>数据库并发控制是确保在多个用户或进程同时访问数据库时,数据的完整性和一致性得到维护的一种机制。并发控制技术主要分为两大类:乐观并发控制和悲观并发控制。下面将详细叙述这两种技术,以及多版本并发控制(MVCC),这是一种在数据库系统中广泛使用的并发控制方法。乐观并发控制(OptimisticConcurrencyControl,OCC)乐观并发控制的核心思想是假设事务之间的冲突发生的概率较低,因此它允</div> </li> <li><a href="/article/1835244090057388032.htm" title="Spring Security静态资源过滤(11)" target="_blank">Spring Security静态资源过滤(11)</a> <span class="text-muted">小黑屋说YYDS</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>在一个实际项目中,并非所有的请求都需要经过SpringSecurity过滤器,有一些特殊的请求,例如静态资源等,一般来说并不需要经过SpringSecurity过滤器链,用户如果访问这些静态资源,直接返回对应的资源即可。回顾关于WebSecurity的讲解,提到它里边维护了一个ignoredRequests变量,该变量,记录的就是所有需要被忽略的请求,这些被忽略的请求将不再经过SpringSecu</div> </li> <li><a href="/article/1835243963653648384.htm" title="Spring Security定义多个过滤器链(10)" target="_blank">Spring Security定义多个过滤器链(10)</a> <span class="text-muted">小黑屋说YYDS</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>在SpringSecurity中可以同时存在多个过滤器链,一个WebSecurityConfigurerAdapter的实例就可以配置一条过滤器链。我们来看如下一个案例:@ConfigurationpublicclassSecurityConfig{@BeanUserDetailsServiceus(){InMemoryUserDetailsManagerusers=newInMemoryUser</div> </li> <li><a href="/article/1835233629056364544.htm" title="java 技术 架构 相关文档" target="_blank">java 技术 架构 相关文档</a> <span class="text-muted">圣心</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>在Java中,有许多不同的技术和架构,这里我将列举一些常见的Java技术和架构,并提供一些相关的文档资源。SpringFrameworkSpring是一个开源的Java/JavaEE全功能框架,以Apache许可证形式发布,提供了一种实现企业级应用的方法。官方文档:SpringFrameworkSpringBootSpringBoot是Spring的一个子项目,旨在简化创建生产级的Spring应用</div> </li> <li><a href="/article/1835229467124002816.htm" title="SpringSecurity初学总结" target="_blank">SpringSecurity初学总结</a> <span class="text-muted">weixin_66442229</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>springSecurity安全框架基于Java的安全框架主要有:SpringSecurity和Shiro介绍基础概念安全框架是对用户访问权限的控制,保证应用的安全性。其主要的工作是用户认证和用户授权|鉴权主要应用于Spring的企业应用系统,提供声明式的安全访问控制解决方案。它提供了一组可以在Spring应用上下文中配置的Bean能很好的结合Spring的DI依赖注入和AOP面向切面编程功能应用</div> </li> <li><a href="/article/1835225687028494336.htm" title="java获取applicationcontext,SpringBoot获取ApplicationContext的3种方式" target="_blank">java获取applicationcontext,SpringBoot获取ApplicationContext的3种方式</a> <span class="text-muted">花儿街参考</span> <div>ApplicationContext是什么?简单来说就是Spring中的容器,可以用来获取容器中的各种bean组件,注册监听事件,加载资源文件等功能。ApplicationContext获取的几种方式1直接使用Autowired注入@ComponentpublicclassBook1{@AutowiredprivateApplicationContextapplicationContext;pub</div> </li> <li><a href="/article/74.htm" title="sql统计相同项个数并按名次显示" target="_blank">sql统计相同项个数并按名次显示</a> <span class="text-muted">朱辉辉33</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a> <div>现在有如下这样一个表: A表 ID Name time ------------------------------ 0001 aaa 2006-11-18 0002 ccc 2006-11-18 0003 eee 2006-11-18 0004 aaa 2006-11-18 0005 eee 2006-11-18 0004 aaa 2006-11-18 0002 ccc 20</div> </li> <li><a href="/article/201.htm" title="Android+Jquery Mobile学习系列-目录" target="_blank">Android+Jquery Mobile学习系列-目录</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/JQuery+Mobile/1.htm">JQuery Mobile</a> <div>最近在研究学习基于Android的移动应用开发,准备给家里人做一个应用程序用用。向公司手机移动团队咨询了下,觉得使用Android的WebView上手最快,因为WebView等于是一个内置浏览器,可以基于html页面开发,不用去学习Android自带的七七八八的控件。然后加上Jquery mobile的样式渲染和事件等,就能非常方便的做动态应用了。   从现在起,往后一段时间,我打算</div> </li> <li><a href="/article/328.htm" title="如何给线程池命名" target="_blank">如何给线程池命名</a> <span class="text-muted">daysinsun</span> <a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B%E6%B1%A0/1.htm">线程池</a> <div>        在系统运行后,在线程快照里总是看到线程池的名字为pool-xx,这样导致很不好定位,怎么给线程池一个有意义的名字呢。参照ThreadPoolExecutor类的ThreadFactory,自己实现ThreadFactory接口,重写newThread方法即可。参考代码如下:     public class Named</div> </li> <li><a href="/article/455.htm" title="IE 中"HTML Parsing Error:Unable to modify the parent container element before the" target="_blank">IE 中"HTML Parsing Error:Unable to modify the parent container element before the</a> <span class="text-muted">周凡杨</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E8%A7%A3%E6%9E%90/1.htm">解析</a><a class="tag" taget="_blank" href="/search/error/1.htm">error</a><a class="tag" taget="_blank" href="/search/readyState/1.htm">readyState</a> <div>  错误: IE 中"HTML Parsing Error:Unable to modify the parent container element before the child element is closed"     现象: 同事之间几个IE 测试情况下,有的报这个错,有的不报。经查询资料后,可归纳以下原因。</div> </li> <li><a href="/article/582.htm" title="java上传" target="_blank">java上传</a> <span class="text-muted">g21121</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>我们在做web项目中通常会遇到上传文件的情况,用struts等框架的会直接用的自带的标签和组件,今天说的是利用servlet来完成上传。 我们这里利用到commons-fileupload组件,相关jar包可以取apache官网下载:http://commons.apache.org/ 下面是servlet的代码: //定义一个磁盘文件工厂 DiskFileItemFactory fact</div> </li> <li><a href="/article/709.htm" title="SpringMVC配置学习" target="_blank">SpringMVC配置学习</a> <span class="text-muted">510888780</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a> <div>spring MVC配置详解 现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。   一、Spring MVC环境搭建:(Spring 2.5.6 + Hi</div> </li> <li><a href="/article/836.htm" title="spring mvc-jfreeChart 柱图(1)" target="_blank">spring mvc-jfreeChart 柱图(1)</a> <span class="text-muted">布衣凌宇</span> <a class="tag" taget="_blank" href="/search/jfreechart/1.htm">jfreechart</a> <div>第一步:下载jfreeChart包,注意是jfreeChart文件lib目录下的,jcommon-1.0.23.jar和jfreechart-1.0.19.jar两个包即可; 第二步:配置web.xml; web.xml代码如下 <servlet>     <servlet-name>jfreechart</servlet-nam</div> </li> <li><a href="/article/963.htm" title="我的spring学习笔记13-容器扩展点之PropertyPlaceholderConfigurer" target="_blank">我的spring学习笔记13-容器扩展点之PropertyPlaceholderConfigurer</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/Spring3/1.htm">Spring3</a> <div>PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是BeanFactoryPostProcessor接口的一个实现。关于BeanFactoryPostProcessor和BeanPostProcessor类似。我会在其他地方介绍。PropertyPlaceholderConfigurer可以将上下文(配置文件)中的属性值放在另一个单独的标准java P</div> </li> <li><a href="/article/1090.htm" title="java 线程池使用 Runnable&Callable&Future" target="_blank">java 线程池使用 Runnable&Callable&Future</a> <span class="text-muted">antlove</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a><a class="tag" taget="_blank" href="/search/Runnable/1.htm">Runnable</a><a class="tag" taget="_blank" href="/search/callable/1.htm">callable</a><a class="tag" taget="_blank" href="/search/future/1.htm">future</a> <div>1. 创建线程池 ExecutorService executorService = Executors.newCachedThreadPool();   2. 执行一次线程,调用Runnable接口实现 Future<?> future = executorService.submit(new DefaultRunnable()); System.out.prin</div> </li> <li><a href="/article/1217.htm" title="XML语法元素结构的总结" target="_blank">XML语法元素结构的总结</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a><a class="tag" taget="_blank" href="/search/%E6%A0%91%E7%BB%93%E6%9E%84/1.htm">树结构</a> <div>1.XML介绍1969年   gml (主要目的是要在不同的机器进行通信的数据规范)1985年   sgml  standard generralized markup language1993年   html(www网)1998年  xml   extensible markup language</div> </li> <li><a href="/article/1344.htm" title="改变eclipse编码格式" target="_blank">改变eclipse编码格式</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A0%81%E6%A0%BC%E5%BC%8F/1.htm">编码格式</a> <div>1.改变整个工作空间的编码格式         改变整个工作空间的编码格式,这样以后新建的文件也是新设置的编码格式。         Eclipse->window->preferences->General->workspace-</div> </li> <li><a href="/article/1471.htm" title="javascript中return的设计缺陷" target="_blank">javascript中return的设计缺陷</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/AngularJS/1.htm">AngularJS</a> <div>代码1: <script> var gisService = (function(window) { return { name:function () { alert(1); } }; })(this); gisService.name(); &l</div> </li> <li><a href="/article/1598.htm" title="【持久化框架MyBatis3八】Spring集成MyBatis3" target="_blank">【持久化框架MyBatis3八】Spring集成MyBatis3</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/Mybatis3/1.htm">Mybatis3</a> <div>pom.xml配置 Maven的pom中主要包括: MyBatis MyBatis-Spring Spring MySQL-Connector-Java Druid applicationContext.xml配置   <?xml version="1.0" encoding="UTF-8"?> &</div> </li> <li><a href="/article/1725.htm" title="java web项目启动时自动加载自定义properties文件" target="_blank">java web项目启动时自动加载自定义properties文件</a> <span class="text-muted">bitray</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E7%9B%91%E5%90%AC%E5%99%A8/1.htm">监听器</a><a class="tag" taget="_blank" href="/search/%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84/1.htm">相对路径</a> <div>创建一个类 public class ContextInitListener implements ServletContextListener 使得该类成为一个监听器。用于监听整个容器生命周期的,主要是初始化和销毁的。 类创建后要在web.xml配置文件中增加一个简单的监听器配置,即刚才我们定义的类。 <listener> <des</div> </li> <li><a href="/article/1852.htm" title="用nginx区分文件大小做出不同响应" target="_blank">用nginx区分文件大小做出不同响应</a> <span class="text-muted">ronin47</span> <div>昨晚和前21v的同事聊天,说到我离职后一些技术上的更新。其中有个给某大客户(游戏下载类)的特殊需求设计,因为文件大小差距很大——估计是大版本和补丁的区别——又走的是同一个域名,而squid在响应比较大的文件时,尤其是初次下载的时候,性能比较差,所以拆成两组服务器,squid服务于较小的文件,通过pull方式从peer层获取,nginx服务于较大的文件,通过push方式由peer层分发同步。外部发布</div> </li> <li><a href="/article/1979.htm" title="java-67-扑克牌的顺子.从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2-10为数字本身,A为1,J为11,Q为12,K为13,而大" target="_blank">java-67-扑克牌的顺子.从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2-10为数字本身,A为1,J为11,Q为12,K为13,而大</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>package com.ljn.base; import java.util.Arrays; import java.util.Random; public class ContinuousPoker { /** * Q67 扑克牌的顺子 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。 * 2-10为数字本身,A为1,J为1</div> </li> <li><a href="/article/2106.htm" title="翟鸿燊老师语录" target="_blank">翟鸿燊老师语录</a> <span class="text-muted">ccii</span> <a class="tag" taget="_blank" href="/search/%E7%BF%9F%E9%B8%BF%E7%87%8A/1.htm">翟鸿燊</a> <div>一、国学应用智慧TAT之亮剑精神A 1. 角色就是人格     就像你一回家的时候,你一进屋里面,你已经是儿子,是姑娘啦,给老爸老妈倒怀水吧,你还觉得你是老总呢?还拿派呢?就像今天一样,你们往这儿一坐,你们之间是什么,同学,是朋友。     还有下属最忌讳的就是领导向他询问情况的时候,什么我不知道,我不清楚,该你知道的你凭什么不知道</div> </li> <li><a href="/article/2233.htm" title="[光速与宇宙]进行光速飞行的一些问题" target="_blank">[光速与宇宙]进行光速飞行的一些问题</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E9%97%AE%E9%A2%98/1.htm">问题</a> <div>      在人类整体进入宇宙时代,即将开展深空宇宙探索之前,我有几个猜想想告诉大家     仅仅是猜想。。。未经官方证实      1:要在宇宙中进行光速飞行,必须首先获得宇宙中的航行通行证,而这个航行通行证并不是我们平常认为的那种带钢印的证书,是什么呢? 下面我来告诉</div> </li> <li><a href="/article/2360.htm" title="oracle undo解析" target="_blank">oracle undo解析</a> <span class="text-muted">cwqcwqmax9</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a> <div>oracle undo解析2012-09-24 09:02:01     我来说两句       作者:虫师收藏    我要投稿 Undo是干嘛用的?         &nb</div> </li> <li><a href="/article/2487.htm" title="java中各种集合的详细介绍" target="_blank">java中各种集合的详细介绍</a> <span class="text-muted">dashuaifu</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9B%86%E5%90%88/1.htm">集合</a> <div>一,java中各种集合的关系图 Collection       接口的接口     对象的集合  ├ List           子接口   &n</div> </li> <li><a href="/article/2614.htm" title="卸载windows服务的方法" target="_blank">卸载windows服务的方法</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a><a class="tag" taget="_blank" href="/search/service/1.htm">service</a> <div>卸载Windows服务的方法 在Windows中,有一类程序称为服务,在操作系统内核加载完成后就开始加载。这里程序往往运行在操作系统的底层,因此资源占用比较大、执行效率比较高,比较有代表性的就是杀毒软件。但是一旦因为特殊原因不能正确卸载这些程序了,其加载在Windows内的服务就不容易删除了。即便是删除注册表中的相 应项目,虽然不启动了,但是系统中仍然存在此项服务,只是没有加载而已。如果安装其他</div> </li> <li><a href="/article/2741.htm" title="Warning: The Copy Bundle Resources build phase contains this target's Info.plist" target="_blank">Warning: The Copy Bundle Resources build phase contains this target's Info.plist</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/xcode/1.htm">xcode</a> <div>    http://developer.apple.com/iphone/library/qa/qa2009/qa1649.html Excerpt: You are getting this warning because you probably added your Info.plist file to your Copy Bundle </div> </li> <li><a href="/article/2868.htm" title="2014之C++学习笔记(一)" target="_blank">2014之C++学习笔记(一)</a> <span class="text-muted">Etwo</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/Etwo/1.htm">Etwo</a><a class="tag" taget="_blank" href="/search/Etwo/1.htm">Etwo</a><a class="tag" taget="_blank" href="/search/iterator/1.htm">iterator</a><a class="tag" taget="_blank" href="/search/%E8%BF%AD%E4%BB%A3%E5%99%A8/1.htm">迭代器</a> <div>        已经有很长一段时间没有写博客了,可能大家已经淡忘了Etwo这个人的存在,这一年多以来,本人从事了AS的相关开发工作,但最近一段时间,AS在天朝的没落,相信有很多码农也都清楚,现在的页游基本上达到饱和,手机上的游戏基本被unity3D与cocos占据,AS基本没有容身之处。so。。。最近我并不打算直接转型</div> </li> <li><a href="/article/2995.htm" title="js跨越获取数据问题记录" target="_blank">js跨越获取数据问题记录</a> <span class="text-muted">haifengwuch</span> <a class="tag" taget="_blank" href="/search/jsonp/1.htm">jsonp</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/Ajax/1.htm">Ajax</a> <div>js的跨越问题,普通的ajax无法获取服务器返回的值。   第一种解决方案,通过getson,后台配合方式,实现。 Java后台代码: protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String ca</div> </li> <li><a href="/article/3122.htm" title="蓝色jQuery导航条" target="_blank">蓝色jQuery导航条</a> <span class="text-muted">ini</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a> <div>效果体验:http://keleyi.com/keleyi/phtml/jqtexiao/39.htmHTML文件代码: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>jQuery鼠标悬停上下滑动导航条 - 柯乐义<</div> </li> <li><a href="/article/3249.htm" title="linux部署jdk,tomcat,mysql" target="_blank">linux部署jdk,tomcat,mysql</a> <span class="text-muted">kerryg</span> <a class="tag" taget="_blank" href="/search/jdk/1.htm">jdk</a><a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>1、安装java环境jdk:     一般系统都会默认自带的JDK,但是不太好用,都会卸载了,然后重新安装。    1.1)、卸载:      (rpm -qa :查询已经安装哪些软件包;        rmp -q 软件包:查询指定包是否已</div> </li> <li><a href="/article/3376.htm" title="DOMContentLoaded VS onload VS onreadystatechange" target="_blank">DOMContentLoaded VS onload VS onreadystatechange</a> <span class="text-muted">mutongwu</span> <a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a> <div>1. DOMContentLoaded 在页面html、script、style加载完毕即可触发,无需等待所有资源(image/iframe)加载完毕。(IE9+) 2. onload是最早支持的事件,要求所有资源加载完毕触发。 3. onreadystatechange 开始在IE引入,后来其它浏览器也有一定的实现。涉及以下 document , applet, embed, fra</div> </li> <li><a href="/article/3503.htm" title="sql批量插入数据" target="_blank">sql批量插入数据</a> <span class="text-muted">qifeifei</span> <a class="tag" taget="_blank" href="/search/%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5/1.htm">批量插入</a> <div>hi,   自己在做工程的时候,遇到批量插入数据的数据修复场景。我的思路是在插入前准备一个临时表,临时表的整理就看当时的选择条件了,临时表就是要插入的数据集,最后再批量插入到数据库中。    WITH tempT AS ( SELECT item_id AS combo_id, item_id, now() AS create_date FROM a</div> </li> <li><a href="/article/3630.htm" title="log4j打印日志文件 如何实现相对路径到 项目工程下" target="_blank">log4j打印日志文件 如何实现相对路径到 项目工程下</a> <span class="text-muted">thinkfreer</span> <a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/%E6%97%A5%E5%BF%97/1.htm">日志</a> <div>最近为了实现统计一个网站的访问量,记录用户的登录信息,以方便站长实时了解自己网站的访问情况,选择了Apache 的log4j,但是在选择相对路径那块 卡主了,X度了好多方法(其实大多都是一样的内用,还一个字都不差的),都没有能解决问题,无奈搞了2天终于解决了,与大家分享一下 需求: 用户登录该网站时,把用户的登录名,ip,时间。统计到一个txt文档里,以方便其他系统调用此txt。项目名</div> </li> <li><a href="/article/3757.htm" title="linux下mysql-5.6.23.tar.gz安装与配置" target="_blank">linux下mysql-5.6.23.tar.gz安装与配置</a> <span class="text-muted">笑我痴狂</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/unix/1.htm">unix</a> <div>1.卸载系统默认的mysql [root@localhost ~]# rpm -qa | grep mysql mysql-libs-5.1.66-2.el6_3.x86_64 mysql-devel-5.1.66-2.el6_3.x86_64 mysql-5.1.66-2.el6_3.x86_64 [root@localhost ~]# rpm -e mysql-libs-5.1</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>