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/1943221886557155328.htm" title="Hutool TreeUtil快速构建树形数据结构" target="_blank">Hutool TreeUtil快速构建树形数据结构</a> <span class="text-muted">yifanghub</span> <a class="tag" taget="_blank" href="/search/%E5%B7%A5%E5%85%B7%E7%B1%BB/1.htm">工具类</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>在管理菜单、部门结构等场景时,我们经常需要将数据库中的层级数据转换为树形结构。本文将通过Hutool的TreeUtil工具类,实现零递归快速构建树形结构。一、环境准备JDK1.8+SpringBoot2.xHutool5.8.16MySQL8.0二、数据准备--创建部门表CREATETABLE`sys_dept`(`id`intNOTNULLAUTO_INCREMENT,`dept_name`va</div> </li> <li><a href="/article/1943220751242948608.htm" title="4.服务注册发现:微服务的神经系统" target="_blank">4.服务注册发现:微服务的神经系统</a> <span class="text-muted"></span> <div>在微服务架构中,服务之间不再是固定连接,而是高度动态、短暂存在的。如何让每个服务准确找到彼此,是分布式系统治理的核心问题之一。服务注册发现机制,正如神经系统之于人体,承担着连接、协调、感知变化的关键角色。本文将围绕Netflix开源的服务注册发现组件Eureka展开,深入剖析其原理,并以SpringCloud实战为导向,帮助你掌握服务治理的第一步。一、为什么需要服务注册发现?在单体架构中,服务调用</div> </li> <li><a href="/article/1943220624952455168.htm" title="2.Spring Cloud生态全景解析:核心组件、能力边界与定位" target="_blank">2.Spring Cloud生态全景解析:核心组件、能力边界与定位</a> <span class="text-muted">碎风影</span> <a class="tag" taget="_blank" href="/search/SpringCloud%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90/1.htm">SpringCloud深度解析</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/cloud/1.htm">cloud</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>导语:SpringCloud并非单一框架,而是基于SpringBoot构建的分布式系统工具集。它通过标准化封装,将服务发现、配置管理、熔断限流等复杂基础设施转化为开箱即用的组件,让开发者聚焦业务逻辑。本文将系统解析其核心组成、与SpringBoot的共生关系,并客观审视其能力边界,助您构建清晰的微服务技术选型地图。一、核心基石:SpringBoot与SpringCloud的共生关系关键结论:Spr</div> </li> <li><a href="/article/1943218356928704512.htm" title="SpringBoot3+JPA+MySQL实现多数据源的读写分离(基于EntityManagerFactory)" target="_blank">SpringBoot3+JPA+MySQL实现多数据源的读写分离(基于EntityManagerFactory)</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/%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E6%8A%80%E6%9C%AF%E5%AE%9E%E6%88%98%E4%B8%93%E6%A0%8F/1.htm">软件开发技术实战专栏</a><a class="tag" taget="_blank" href="/search/SpringBoot3/1.htm">SpringBoot3</a><a class="tag" taget="_blank" href="/search/JPA/1.htm">JPA</a><a class="tag" taget="_blank" href="/search/MySQL/1.htm">MySQL</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90/1.htm">多数据源</a><a class="tag" taget="_blank" href="/search/%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/1.htm">读写分离</a> <div>1、简介在SpringBoot中配置多个数据源并实现自动切换EntityManager,这里我编写了一个RoutingEntityManagerFactory和AOP(面向切面编程)的方式来实现。这里我配置了两个数据源:primary和secondary,其中primary主数据源用来写入数据,secondary从数据源用来读取数据。注意1:使用Springboot3的读写分离,首先要保证主库和从</div> </li> <li><a href="/article/1943217977772011520.htm" title="微服务世界的“导航仪”!Spring Cloud五大注册中心选型指南,从此不再迷路!" target="_blank">微服务世界的“导航仪”!Spring Cloud五大注册中心选型指南,从此不再迷路!</a> <span class="text-muted">码农技术栈</span> <a class="tag" taget="_blank" href="/search/%E5%BE%AE%E6%9C%8D%E5%8A%A1/1.htm">微服务</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E6%9C%8D%E5%8A%A1/1.htm">微服务</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/cloud/1.htm">cloud</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/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/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>引言:为什么微服务需要“导航仪”?想象一下,你走进一座巨大的迷宫(微服务集群),里面有成百上千个房间(服务实例),每个房间都在动态变化位置(服务扩缩容)。注册中心就像迷宫里的导航仪,实时记录所有房间的位置,告诉你怎么最快找到目标。没有它?你可能会永远迷失在“服务调用”的迷宫里!注册中心的核心作用服务注册:服务启动时,主动上报自己的地址和状态。服务发现:调用方通过注册中心查询目标服务的位置。健康监测</div> </li> <li><a href="/article/1943216966424653824.htm" title="spring-data-jpa+spring+hibernate+druid配置" target="_blank">spring-data-jpa+spring+hibernate+druid配置</a> <span class="text-muted"></span> <div>参考链接:http://doc.okbase.net/liuyitian/archive/109276.htmlhttp://my.oschina.net/u/1859292/blog/312188最新公司的web项目需要用到spring-data-jpa作为JPA的实现框架,同时使用阿里巴巴的开源数据库连接池druid。关于这两种框架的介绍我在这里就不多赘述。直接进入配置页面:spring的配置</div> </li> <li><a href="/article/1943215957870702592.htm" title="Spring Data Jpa +alibaba druid+query dsl 实现多数据源" target="_blank">Spring Data Jpa +alibaba druid+query dsl 实现多数据源</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/data/1.htm">data</a><a class="tag" taget="_blank" href="/search/jpa/1.htm">jpa</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>SpringDataJpa+alibabadruid+querydsl实现多数据源,主要通过配置来实现多个数据源的操作,无需动态切换1.maven配置org.springframework.bootspring-boot-starter-data-jpa2.3.12.RELEASEcom.alibabadruid-spring-boot-starter1.1.24com.querydslquery</div> </li> <li><a href="/article/1943215452465459200.htm" title="Spring Boot + Spring JPA + JDBC + Druid实现动态数据源切换" target="_blank">Spring Boot + Spring JPA + JDBC + Druid实现动态数据源切换</a> <span class="text-muted">Apr01Chell</span> <a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81%E7%89%87%E6%AE%B5/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><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>SpringBoot+SpringJPA+JDBC+Druid实现动态数据源切换目录SpringBoot+SpringJPA+JDBC+Druid实现动态数据源切换AbstractRoutingDataSource源码分析需求代码实现DynamicDataSourceDBContextHolderDruidDbConfigDataSourcePropertiesAllDataSourcesExec</div> </li> <li><a href="/article/1943212049039421440.htm" title="Spring框架中的Component与Bean注解" target="_blank">Spring框架中的Component与Bean注解</a> <span class="text-muted"></span> <div>SpringBoot中的@Bean与@Component![](https://pic4.zhimg.com/v2-f957e9ec5412c87a66ccb021410eaae9_14...)Spring的@Component和@Bean注解的关键区别在于:@Bean注解可用于暴露您自己编写的JavaBeans,而@Component注解可用于暴露源代码由他人维护的JavaBeans。Sprin</div> </li> <li><a href="/article/1943208267865976832.htm" title="Flex与Spring集成" target="_blank">Flex与Spring集成</a> <span class="text-muted">hkmw</span> <a class="tag" taget="_blank" href="/search/Flex/1.htm">Flex</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE/1.htm">配置</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/flex/1.htm">flex</a><a class="tag" taget="_blank" href="/search/application/1.htm">application</a><a class="tag" taget="_blank" href="/search/dependencies/1.htm">dependencies</a><a class="tag" taget="_blank" href="/search/components/1.htm">components</a><a class="tag" taget="_blank" href="/search/access/1.htm">access</a> <div>Flex与Spring集成UsingFlexwithSpringUPDATE(1/12/2007):IputtogetheraTomcat-basedTestDriveServerthatincludesthesamplesdescribedbelowrunningout-of-thebox.Readthispostformoreinfo.WhatisSpring?Springisoneofthe</div> </li> <li><a href="/article/1943207762251018240.htm" title="【视频观看系统】- 技术与架构选型" target="_blank">【视频观看系统】- 技术与架构选型</a> <span class="text-muted"></span> <div>✅项目技术选型方案一、整体架构风格项目层级技术选型说明架构风格微服务架构(SpringCloud)独立部署、易扩展、易维护服务通信HTTP(RestTemplate或Feign)+RocketMQ同步调用+异步事件注册中心Nacos服务注册、发现、配置中心配置中心Nacos配置管理多服务统一配置API网关SpringCloudGateway路由转发、权限验证、限流服务监控SpringBootAdm</div> </li> <li><a href="/article/1943200953868021760.htm" title="SpringBoot ThreadLocal 全局动态变量设置" target="_blank">SpringBoot ThreadLocal 全局动态变量设置</a> <span class="text-muted">xdscode</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/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/ThreadLocal/1.htm">ThreadLocal</a> <div>需求说明:现有一个游戏后台管理系统,该系统可管理多个大区的数据,但是需要使用大区id实现数据隔离,并且提供了大区选择功能,先择大区后展示对应的数据。需要实现一下几点:1.前端请求时,area_id是必传的1.数据隔离,包括查询及增删改:使用mybatis拦截器实现2.多个用户同时操作互不影响3.非前端调用场景的处理:定时任务、mq1.前端决定area_id为了解决多个用户可以互不影响的使用不同的a</div> </li> <li><a href="/article/1943196291844599808.htm" title="实操 SpringBoot+MCP!" target="_blank">实操 SpringBoot+MCP!</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/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>引言随着人工智能的飞速发展,大语言模型(LLM)正在革命性地重塑用户与软件的交互范式。想象一下这样的场景:用户无需钻研复杂的API文档或者在繁琐的表单间来回切换,只需通过自然语言直接与系统对话——“帮我查找所有2023年出版的图书”、“创建一个新用户叫张三,邮箱是zhangsan@example.com”。这种直观、流畅的交互方式不仅能显著降低新用户的学习曲线,更能大幅削减B端系统的培训成本和实施</div> </li> <li><a href="/article/1943196165524746240.htm" title="【SpringBoot】Spring Boot 高并发优化终极指南,涵盖线程模型、JVM 调优、数据库访问、缓存策略等 15+ 核心模块" target="_blank">【SpringBoot】Spring Boot 高并发优化终极指南,涵盖线程模型、JVM 调优、数据库访问、缓存策略等 15+ 核心模块</a> <span class="text-muted">夜雨hiyeyu.com</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><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</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><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a> <div>SpringBoot高并发优化终极指南,涵盖线程模型、JVM调优、数据库访问、缓存策略等15+核心模块一、线程模型深度调优(核心瓶颈突破)1.Tomcat线程池原子级配置2.异步任务线程池隔离策略二、JVM层终极调参(G1GC深度优化)1.内存分配策略2.GC日志分析技巧三、缓存策略原子级优化1.三级缓存架构实现2.缓存穿透/雪崩防护四、数据库访问极致优化1.连接池死亡参数配置2.分页查询深度优化</div> </li> <li><a href="/article/1943194650974154752.htm" title="SpringBoot+AOP+自定义注解,实现日志记录" target="_blank">SpringBoot+AOP+自定义注解,实现日志记录</a> <span class="text-muted"></span> <div>一.定义自定义注解importjava.lang.annotation.*;/***@authorawen*定义注解目的想让他当作切点*/@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)//.java.class字节码@Documentedpublic@interfaceLog{/***处理类型**@return{@l</div> </li> <li><a href="/article/1943194272480161792.htm" title="spring boot使用mybatis-plus实现分页功能" target="_blank">spring boot使用mybatis-plus实现分页功能</a> <span class="text-muted">kong@react</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/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>使用MyBatis-Plus实现分页功能MyBatis-Plus提供了内置的分页插件,可以轻松实现分页查询功能。以下是实现分页的具体方法:配置分页插件在SpringBoot项目中,需要在配置类中注册分页插件:@ConfigurationpublicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormybatisPlusIntercept</div> </li> <li><a href="/article/1943193139422490624.htm" title="springboot通过aop实现全局日志(是否自定义注解都可以)" target="_blank">springboot通过aop实现全局日志(是否自定义注解都可以)</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/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%23aop/1.htm">#aop</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/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/aop/1.htm">aop</a><a class="tag" taget="_blank" href="/search/%E5%85%A8%E5%B1%80%E6%97%A5%E5%BF%97/1.htm">全局日志</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3/1.htm">自定义注解</a> <div>内容参考自以下两个链接1、springboot中使用AOP切面完成全局日志_aop全局日志_邹飞鸣的博客-CSDN博客使用AOP记录日志_aop日志_trusause的博客-CSDN博客第一个链接思路很清晰,讲的也很详细,第二个链接讲了自定义注解为了便于自己理解做了以下整理目录1.aspectj基本概念2.添加aop依赖3.进行切面处理(1)切面类(2)自定义注解(3)controller和ser</div> </li> <li><a href="/article/1943189987646304256.htm" title="SpringBoot AOP+注解 全局日志记录" target="_blank">SpringBoot AOP+注解 全局日志记录</a> <span class="text-muted">xdscode</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/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/AOP/1.htm">AOP</a> <div>一、需求描述如何优雅地记录用户操作日志?网站后台,功能开发完成后,新增了一个需求,即需要记录用户的各种操作记录。由于是在开发后期,如果针对每一个功能都去添加一段记录日志的代码,工作量较大、代码侵入性太强,因此采用AOP+注解的方式实现。可读性大大提高,且便于维护和扩展。AOP:面向切面编程,在不修改现有逻辑代码的情况下,增强功能,恰好体现了spring的理念:无入侵式自定义注解:当被注解的方法执行</div> </li> <li><a href="/article/1943175616496988160.htm" title="Spring Bean 生命周期 SmartLifecycle接口介绍和使用场景 和 Lifecycle对比" target="_blank">Spring Bean 生命周期 SmartLifecycle接口介绍和使用场景 和 Lifecycle对比</a> <span class="text-muted">极光雨雨</span> <a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/Spring/1.htm">Spring</a><a class="tag" taget="_blank" href="/search/%E5%85%A8%E5%AE%B6/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>在SpringBoot中,SmartLifecycle是org.springframework.context.Lifecycle接口的一个扩展接口,它提供了更细粒度的控制生命周期的方法。Spring容器管理Bean的生命周期时,可以通过实现SmartLifecycle接口来定义自定义的启动和关闭逻辑。一、使用前提需要在Spring容器启动完成后执行某些初始化操作。需要在应用关闭前做一些清理工作(</div> </li> <li><a href="/article/1943172465710657536.htm" title="Java程序设计(二十七):基于SSM框架的OA办公自动化管理平台的设计与实现" target="_blank">Java程序设计(二十七):基于SSM框架的OA办公自动化管理平台的设计与实现</a> <span class="text-muted">人工智能_SYBH</span> <a class="tag" taget="_blank" href="/search/2025%E5%B9%B4java%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/1.htm">2025年java程序设计</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/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><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/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>1.项目概述办公自动化(OA,OfficeAutomation)管理平台是企业实现内部管理信息化的重要工具。本文提出并实现了一个基于Java的OA办公自动化管理平台。该平台基于SSM架构(Spring+SpringMVC+MyBatis),数据库采用MySQL,并通过HTML、CSS、JavaScript等技术实现用户界面。1.1平台功能简介平台提供了管理员、普通用户和部门三类角色,分别具有不同的</div> </li> <li><a href="/article/1943148639413137408.htm" title="【人工智能】Spring AI Alibaba,一个面向 Java 开发者的开源框架,它旨在简化将人工智能(AI)功能集成到应用程序中的过程。" target="_blank">【人工智能】Spring AI Alibaba,一个面向 Java 开发者的开源框架,它旨在简化将人工智能(AI)功能集成到应用程序中的过程。</a> <span class="text-muted">本本本添哥</span> <a class="tag" taget="_blank" href="/search/A/1.htm">A</a><a class="tag" taget="_blank" href="/search/-/1.htm">-</a><a class="tag" taget="_blank" href="/search/AIGC/1.htm">AIGC</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%A8%A1%E5%9E%8B/1.htm">大模型</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><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>一、SpringAIAlibaba介绍SpringAIAlibaba是一个面向Java开发者的开源框架,它旨在简化将人工智能(AI)功能集成到应用程序中的过程。该项目基于SpringAI构建,并且是阿里云通义系列模型及服务在JavaAI应用开发领域的最佳实践。SpringAIAlibaba的目标是为开发者提供一套高层次的AIAPI抽象以及与云原生基础设施的深度集成方案,从而帮助他们快速构建智能应用</div> </li> <li><a href="/article/1943145867548618752.htm" title="SpringAI Alibaba 正式版发布!四个问题让你彻底拿捏它" target="_blank">SpringAI Alibaba 正式版发布!四个问题让你彻底拿捏它</a> <span class="text-muted">小付爱coding</span> <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>SpringAIAlibaba正式版发布!四个问题让你彻底拿捏它作者:XXX|发布时间:2025年4月最近,SpringAIAlibaba正式版重磅上线了!作为一个Java开发者,如果你还没听说过它,那你可能真的要掉队了。别急,今天我就用最通俗的方式带你搞懂这玩意儿到底是个啥、为啥要学它、学什么、能干啥!一、SpringAIAlibaba到底是个啥?一句话总结:SpringAIAlibaba是一个</div> </li> <li><a href="/article/1943140197222903808.htm" title="Spring Data Neo4j 与后端人工智能算法的数据交互" target="_blank">Spring Data Neo4j 与后端人工智能算法的数据交互</a> <span class="text-muted">AI大模型应用实战</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/neo4j/1.htm">neo4j</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>SpringDataNeo4j与后端人工智能算法的数据交互关键词:SpringDataNeo4j、图数据库、人工智能算法、数据交互、知识图谱、图神经网络、数据集成摘要:本文深入探讨了如何利用SpringDataNeo4j框架实现后端人工智能算法与图数据库的高效数据交互。文章首先介绍了图数据库和人工智能算法的基本概念,然后详细解析了SpringDataNeo4j的核心架构和原理。接着,通过实际代码示</div> </li> <li><a href="/article/1943138179548770304.htm" title="SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:整体布局、架构调整(二)" target="_blank">SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:整体布局、架构调整(二)</a> <span class="text-muted">喜欢敲代码的程序员</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E5%90%8E%E7%AB%AF%E5%88%86%E7%A6%BB/1.htm">前后端分离</a><a class="tag" taget="_blank" href="/search/SpringBoot/1.htm">SpringBoot</a><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/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/elementui/1.htm">elementui</a> <div>目录一、前言二、后端调整1.实体类调整2.菜单相关接口3.用户相关接口4.新增工具类5.新增菜单树返回类6.配置类、拦截器三、前端调整1.请求调整2.页面布局、样式调整1.user.vue2.index.vue3.请求拦截四、开发过程中的问题五、附:源码1.源码下载地址六、结语一、前言此文章在上次的基础上进行了部分调整,并根据用户体验(我自己)确认了页面整体布局和数据呈现,暂定就先这样,后续有需要</div> </li> <li><a href="/article/1943132383410712576.htm" title="Spring Security:认证与授权的实现原理及实践" target="_blank">Spring Security:认证与授权的实现原理及实践</a> <span class="text-muted"></span> <div>SpringSecurity是Spring生态中强大的安全框架,用于为Java应用提供认证(Authentication)和授权(Authorization)功能。根据2024年StackOverflow开发者调查,SpringBoot是Java开发者中最流行的框架,约60%的Java开发者使用它构建微服务,而SpringSecurity是其首选安全解决方案。本文深入剖析SpringSecurit</div> </li> <li><a href="/article/1943128852578496512.htm" title="创建 TransactionStatus" target="_blank">创建 TransactionStatus</a> <span class="text-muted">悟能不能悟</span> <a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a><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>在Spring框架中,TransactionStatus是一个接口,通常由事务管理器(如PlatformTransactionManager)在开启事务时自动创建,而不是由开发者直接实例化。如果你需要在代码中操作事务状态,应通过以下标准方式:正确获取TransactionStatus的步骤:注入事务管理器在SpringBean中注入PlatformTransactionManager(如DataS</div> </li> <li><a href="/article/1943126454996889600.htm" title="[3-02-01].第14节:三方整合 - SpringData整合Redis集群" target="_blank">[3-02-01].第14节:三方整合 - SpringData整合Redis集群</a> <span class="text-muted">1.01^1000</span> <a class="tag" taget="_blank" href="/search/%E9%98%B6%E6%AE%B503%EF%BC%9A%E4%BC%81%E4%B8%9A%E6%A1%86%E6%9E%B6/1.htm">阶段03:企业框架</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>Redis大纲一、SpringBoot整合主从架构的Redis:1.1.问题说明:1.在Sentinel集群监管下的Redis哨兵架构中,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息2.SpringBoot中的RedisTemplate底层利用lettuce实现了节点的感知和自动切换,我们需要进行配置才可以实现这种动态上下线的情况。下面,我们通过一个测试</div> </li> <li><a href="/article/1943111589477543936.htm" title="IDEA Maven报错 无法解析 com.taobao:parent:pom:1.0.1【100%解决 此类型问题】" target="_blank">IDEA Maven报错 无法解析 com.taobao:parent:pom:1.0.1【100%解决 此类型问题】</a> <span class="text-muted">Dolphin_Home</span> <a class="tag" taget="_blank" href="/search/%E7%A7%81%E6%9C%89_%E6%A1%88%E4%BE%8B%E5%88%86%E6%9E%90/1.htm">私有_案例分析</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83_%E5%9C%BA%E6%99%AF%E6%8A%BD%E8%B1%A1/1.htm">生产环境_场景抽象</a><a class="tag" taget="_blank" href="/search/Debug/1.htm">Debug</a><a class="tag" taget="_blank" href="/search/intellij-idea/1.htm">intellij-idea</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>IDEAMaven报错无法解析com.taobao:parent:pom:1.0.1【100%解决此类型问题】报错日志PSD:\Learn_Materials\IDEA_WorkSpace\Demo\spring_test_demo>mvncleaninstall-U[INFO]Scanningforprojects...[WARNING][WARNING]Someproblemswereenco</div> </li> <li><a href="/article/1943086123010027520.htm" title="大模型之Spring AI实战系列(三十二):Spring Boot + DeepSeek 实战指南:工具函数(Function Call)实战应用" target="_blank">大模型之Spring AI实战系列(三十二):Spring Boot + DeepSeek 实战指南:工具函数(Function Call)实战应用</a> <span class="text-muted"></span> <div>系列篇章No.文章1大模型之SpringAI实战系列(一):基础认知篇-开启智能应用开发之旅2大模型之SpringAI实战系列(二):SpringBoot+OpenAI打造聊天应用全攻略3大模型之SpringAI实战系列(三):SpringBoot+OpenAI实现聊天应用上下文记忆功能4大模型之SpringAI实战系列(四):SpringBoot+OpenAI使用OpenAIEmbedding实</div> </li> <li><a href="/article/1943080707383422976.htm" title="SpringBoot-19-企业云端开发实践之web开发晋级" target="_blank">SpringBoot-19-企业云端开发实践之web开发晋级</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/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%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>文章目录1静态资源访问1.1static静态资源目录1.2application.properties(过滤规则)2文件上传2.1文件上传原理2.2SprintBoot文件上传功能2.3FileUploadController.java2.4配置访问上传的文件3拦截器3.1interceptor/LoginInterceptor3.2config/WebConfig4RESTful服务和Swagg</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>