`
drinkjava2
  • 浏览: 41879 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

一种利用注释让Java支持多行字符串的方法

阅读更多
(2018.1.21注:本文已过时,又找到一种好一点的利用注释支持多行字符串的方法,见https://my.oschina.net/drinkjava2/blog/1611028 )

从BeetlSql项目将SQL全放在Beetl模板里得到启发,又想到一个比较偏门的用法。以下代码实测通过,详见jSqlBox项目的test\examples\multipleLineSQL\SqlTemplateDemo.java源程序,此示例特殊点在于:运行时必须将此源程序拷贝一份在类根目录(或Maven管理的Resource目录下), 并将后缀".java"改为".sql"

public class SqlTemplateDemo extends TestBase {

	//@formatter:off	
	public static class InsertUser extends SqlTemplate {
		public InsertUser(Object name, Object address, Object age){ 
		/* insert into 
		   users 
		   (username, address, age) */ empty(name,address,age);
		/* values  (?,?,?)*/ 
		}
	}
	
	public static class FindUsers extends SqlTemplate  {
		public FindUsers(Object name, Object age){ 
		/* select count(*) 
		   from
		   users
		  where */
		/* username=? */empty(name); 
		/* and age>? */empty(age);
		/* order by username */  
		}
	}

    public static class GetUserCount extends SqlTemplate  {    
        /* select count(*) 
           from users  */    
    }   
    
	public static class SqlTemplateEndTag{}
	
	@Test
	public void doTest() { 
		Dao.executeInsert(new InsertUser("Tom","BeiJing",10).toString());
		Dao.executeInsert(new InsertUser("Sam","ShangHai",20).toString());
		Assert.assertEquals((Integer) 1,  Dao.queryForInteger(new FindUsers("Sam",15).toString()));
		Assert.assertEquals((Integer) 2,  Dao.queryForInteger(new GetUserCount().toString())); 
	} 	
}

以上代码是利用Java源程序作为模板文件来统一放置SQL,以便于DBA管理。其优点在于:

1)没有引入第三方模板,直接用Java作为模板文件
2)支持多行字符串, 且没有引入IDE插件或Maven编译插件等,通用性好。
3)支持Java方法和模板混用,模板负责存储SQL,Java负责赋值(利用ThreadLocal),互不干拢。
4)public static class的类名即为SQL ID,便于重命名重构和SQL的快速定位(Ctrl+鼠标左键即可),这是文本方式模板无法做到的,后者必须用文本搜索功能才能定位SQL。
缺点是:
1)每次模板更改后,还必须手工拷贝一份同样的文件放在类根目录作为资源文件
2)因为SQL写在注释中, 所以必须利用标记 //@formatter:off 来关闭IDE(我用Eclipse)的格式化功能,防止IDE误格式化。
3)从SQL管理角度出发,模板文件中要注意不要放入过多除SQL以外的无关代码。

以上方法主要应用于SQL模板,但是其它场合如需要用到Java支持多行字符串的,也可以借签。

注:2017.5.17再更新一下,以下是一个通用的支持多行字符串的基类,实现了在开发阶段从源码读取(TextSupport类或其子类在getJavaSrcFolder方法返回值中要给出源码目录),布署阶段从资源文件读取(布署时改一下getJavaSrcFolder方法使其返回空值并拷贝Java模板到类根目类,并改为.txt后缀):

package util;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

/**
 * TextSupport is base class for Java text(multiple line Strings) template.
 */
public class TextSupport {

	public String getJavaSrcFolder() {
		return "F:/your_project_folder/src/test/java/";
	}

	@Override
	public String toString() {
		try {
			if (StringUtils.isEmpty(getJavaSrcFolder()))
				return extractTextFromComments(getTextFromResourceFile());
			else
				return extractTextFromComments(getTextFromJavaFile());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private String extractTextFromComments(String templateText) {
		String thisPublicStaticClassName = this.getClass().getSimpleName();
		String classText = StringUtils.substringBetween(templateText,
				"public static class " + thisPublicStaticClassName, "*/}");
		if (StringUtils.isEmpty(classText))
			throw new RuntimeException("Can not find text between \"public static class " + thisPublicStaticClassName
					+ " and end tag \"*/}\"");
		StringBuilder sb = new StringBuilder();
		for (String str : StringUtils.substringsBetween(classText + "*/", "/*", "*/"))
			sb.append(str);
		return sb.toString();
	}

	private String getTextFromJavaFile() throws IOException {
		String className = this.getClass().getName(); // aaa.bbb.CCC$DDD
		String fileName = getJavaSrcFolder()
				+ StringUtils.replace(StringUtils.substringBeforeLast(className, "$"), ".", "/") + ".java";
		return FileUtils.readFileToString(new File(fileName));
	}

	private String getTextFromResourceFile() throws IOException {
		String className = StringUtils.substringAfterLast("." + this.getClass().getName(), ".");// CCC$DDD
		String resFile = StringUtils.substringBefore(className, "$") + ".txt";// CCC.txt
		URL url = this.getClass().getResource("/" + resFile);
		if (url == null)
			throw new RuntimeException("Can not find resource file \"" + resFile + "\"");
		return FileUtils.readFileToString(new File(url.getFile()));
	}

	public static void main(String[] args) {
		System.out.println("Text=" + new DemoString());
	}

	//@formatter:off
	public static class DemoString extends TextSupport{   
	 /*   
	  Hello,
	  This is multiple line strings demo
     */} 	
}


分享到:
评论

相关推荐

    多行批量字符替换 可替换任何文件里的字符串 特色在多行替换

    "多行批量字符替换"是一种高效的方法,可以极大地提升工作效率。这个工具或技术的核心在于它能一次性替换文件或多个文件中的特定字符串,而不仅仅局限于单个字符或一行内容的替换,这在处理大量文本数据时尤其有用。...

    过滤Java多行注释

    在这个例子中,`filterComments`方法接收源代码字符串,`inComment`标志跟踪是否处于注释状态。当遇到`/*`时,进入注释状态;遇到`*/`时,退出注释状态。在非注释状态下,将字符添加到过滤后的代码中。 3. **第三方...

    2.Golang的基础语法(分隔符,注释,标识符,字符串拼接,空格)1

    本文将深入探讨四个主要概念:分隔符、注释、标识符以及字符串拼接,同时也会提及空格的使用。 首先,让我们来了解分隔符。与许多其他编程语言(如JAVA和PHP)不同,Golang不需要在每一行末尾添加英文分号(;)。这...

    java高亮例子 简单易懂

    总的来说,Java代码高亮是一种提高代码可读性的技术,它通过改变关键字、运算符、数字、字符串和注释的颜色或样式来帮助程序员更快地理解代码结构。无论你是新手还是经验丰富的开发者,都应该充分利用这一工具,提升...

    java中有三种书写注释的方式.doc

    Java 中的三种注释方式 Java 语言中有三种书写注释的方式,分别是 “//”、“/*...*/” 和 “/...*/”。这些注释方式在编程中扮演着重要的角色,能够提高代码的可读性和可维护性。 一、“//” 注释方式 “//” 是...

    Java概述、环境变量、注释、关键字、标识符、常量

    Java 中有两种类型的注释,一种是单行注释,使用双斜线:///,另一种是多行注释,使用estar 和 */。关键字是 Java 中的保留字,不能用于变量名或方法名,例如:public、private、static 等。 Java 中的标识符是指...

    java期末复习题

    根据给定的文件信息,我们可以总结出一系列与Java编程语言相关的知识点,这些知识点涵盖了Java的基础概念、语法特性、数据类型、运算符、流操作、事件处理、容器组件、类的声明以及字符串操作等方面。 1. **Java...

    java代码-编写一个程序找出字符串

    Java支持单行注释`//`和多行注释`/*...*/`。 通过理解以上知识点,你可以编写一个Java程序来找出字符串中的特定信息。例如,你可以创建一个程序来计算某个字符在字符串中出现的次数,或者找出所有以特定前缀开头的...

    大数据必学Java基础(八):简单介绍API和注释

    例如,当你需要处理字符串时,可以查找`java.lang.String`类,了解其提供的各种操作字符串的方法,如`substring()`、`indexOf()`等。 理解API的关键在于熟悉其组织结构和命名约定。Java API按照包(package)进行...

    Java 删除项目里面的注释所用到的包.zip

    一种常见的方法是使用Java的`java.io`和`java.nio.file`包来读取和修改源代码文件,结合`java.util.regex`包进行字符串匹配和替换。此外,有些第三方库,如JavaCC或ANTLR,可以解析Java语法,更精确地找到并移除注释...

    正则统计代码中空行、注释行、代码行纯JAVA

    正则表达式(Regular Expression)是一种强大的文本处理工具,能够匹配、查找、替换等操作,对于处理字符串非常有用。 首先,我们需要了解Java中处理字符串的主要工具:`java.util.regex`包。这个包提供了`Pattern`...

    Ruby自学笔记

    字符串的表示方法有多种,包括最简单的单引号和双引号包裹字符串、使用分界符表示的字符串、heredoc构建多行字符串等。例如,%q用于表示单引号字符串,%Q和%用于表示双引号字符串。此外,Ruby提供了heredoc语法,...

    Python删除Java源文件中全部注释的实现方法

    正则表达式(Regular Expression)是一种用于匹配字符串中字符组合的模式。在Python中,`re`模块提供了对正则表达式的支持。正则表达式可以用来检查一个字符串是否与某种模式匹配,也可用于字符串的搜索、替换等操作...

    Perl中的单行注释和多行注释语法

    除了基本的注释语法,Perl还支持一些高级特性,比如在文档字符串中使用多行注释。例如,Perl模块经常使用`__PACKAGE__`和`__END__`之间的区域来存储文档字符串,这可以被`perldoc`工具解析并显示为帮助文本。 在...

    java习题汇编.docx

    Java 中有三种注释方式:单行注释(//)、多行注释(/* */)和文档注释(/ */)。 文档注释可以使用 javadoc 命令生成文档。 9. Java 数据类型转换 Java 中的数据类型转换可以是隐式转换或强制类型转换。 强制类型...

    Java教学设计.pdf

    Java 是一种广泛应用于软件开发的编程语言,本节课程将从 Java 的基本语法、变量、运算符、方法、结构语句和数组等方面进行讲解。 一、Java 基本语法 Java 语言是严格区分大小写的,每条功能执行语句的最后都必须...

    java菜鸟学习第一步-java基础语法

    Java是一种广泛应用于Android开发、Web开发、企业软件开发等领域的编程语言。本文将从Java的起源、特点、文件说明、语法等方面对Java基础语法进行详细介绍。 Java的起源 Java语言的前身是Oak语言,由Sun公司开发,...

    Java中高级核心知识全面解析.pdf

    Java 中高级核心知识全面解析 ...Java 语言是一种功能强大且广泛应用的编程语言,本文对 Java 中的高级核心知识进行了全面解析,涵盖了基础知识到高级特性,旨在帮助读者更好地理解和掌握 Java 语言。

    Java 批量删除html中注释内容的方法

    `deleteCommentInLine`方法需要完成实际的注释删除操作,这通常涉及字符串的切分、拼接等操作。具体实现可能因需求而异,例如,可以使用正则表达式来匹配和替换注释内容。 这种方法虽然简单,但可能无法处理所有...

Global site tag (gtag.js) - Google Analytics