2010-09-07 31 views
51

Có cơ chế thay thế String nào trong Java không, nơi tôi có thể truyền đối tượng bằng văn bản và thay thế chuỗi khi nó xuất hiện.
Ví dụ, văn bản là:Chuỗi thay thế trong java, tương tự như mẫu vận tốc

Hello ${user.name}, 
    Welcome to ${site.name}. 

Đối tượng tôi có là "user""site". Tôi muốn thay thế các chuỗi được đưa ra bên trong ${} với các giá trị tương đương của nó từ các đối tượng. Điều này giống như chúng ta thay thế các đối tượng trong một mẫu vận tốc.

+0

Thay thế ở đâu? Một lớp học? Một JSP? Chuỗi có một phương thức định dạng nếu bạn chỉ: 'String.format (" Hello% s ", tên người dùng);' – Droo

+0

@Droo: Trong ví dụ, chuỗi giống như 'Hello $ {user.name}', không giống như 'Hello % s' hoặc 'Hello {0}'. –

+1

Nếu bạn cần một cái gì đó trông giống như vận tốc và mùi giống như vận tốc, có lẽ nó là vận tốc? :) – serg

Trả lời

89

Sử dụng apache commons lang.

https://commons.apache.org/proper/commons-lang/

Nó sẽ làm điều đó cho bạn (và mã nguồn mở của nó ...)

Map<String, String> valuesMap = new HashMap<String, String>(); 
valuesMap.put("animal", "quick brown fox"); 
valuesMap.put("target", "lazy dog"); 
String templateString = "The ${animal} jumped over the ${target}."; 
StrSubstitutor sub = new StrSubstitutor(valuesMap); 
String resolvedString = sub.replace(templateString); 
+2

Javadoc cho StrSubstitutor http://commons.apache.org/lang/api-release/org/apache/commons/lang/text/StrSubstitutor.html – Paul

+1

Nên là 'Bản đồ valuesMap = new HashMap (); '. – andrewrjones

+1

'StrSubstitutor' hiện không được chấp nhận trong [https://commons.apache.org/proper/commons-lang/](https://commons.apache.org/proper/commons-lang/). Thay vào đó, hãy sử dụng [https://commons.apache.org/proper/commons-text/](https://commons.apache.org/proper/commons-text/) – Lukuluba

4

Đây là một phác thảo về cách bạn có thể thực hiện việc này. Nó sẽ tương đối đơn giản để thực hiện nó như là mã thực tế.

  1. Tạo bản đồ của tất cả các đối tượng sẽ được tham chiếu trong mẫu.
  2. Sử dụng cụm từ thông dụng để tìm các tham chiếu biến trong mẫu và thay thế chúng bằng giá trị của chúng (xem bước 3). Lớp Matcher sẽ có ích để tìm và thay thế.
  3. Tách tên biến tại dấu chấm. user.name sẽ trở thành username. Tra cứu user trong bản đồ của bạn để lấy đối tượng và sử dụng reflection để nhận giá trị name từ đối tượng. Giả sử đối tượng của bạn có getters tiêu chuẩn, bạn sẽ tìm kiếm một phương thức getName và gọi nó.
+0

Heh, chỉ nhìn thấy câu trả lời này. Nó giống hệt với tôi. Vui lòng cho tôi biết suy nghĩ của bạn về việc triển khai của tôi. – jjnguy

82

Hãy xem lớp java.text.MessageFormat, MessageFormat lấy một bộ đối tượng, định dạng chúng, sau đó chèn các chuỗi đã định dạng vào mẫu ở các vị trí thích hợp.

Object[] params = new Object[]{"hello", "!"}; 
String msg = MessageFormat.format("{0} world {1}", params); 
+6

Cảm ơn! Tôi biết java nên có một cách sẵn có để làm điều này mà không cần phải sử dụng là freaking mẫu động cơ để làm một điều đơn giản như vậy! –

+1

Có vẻ như String.format có thể làm bất cứ điều gì mà điều này có thể thực hiện - https://stackoverflow.com/questions/2809633/difference-between-messageformat-format-and-string-format-in-jdk1-5 – Noumenon

+0

+1. Lưu ý rằng 'format' cũng lấy một' Object ... 'varargs để bạn có thể sử dụng cú pháp terse này, nơi có thể sử dụng' format ("{0} world {1}", "Hello", "!"); ' – davnicwil

16

Tôi đã cùng nhau thực hiện thử nghiệm nhỏ. Ý tưởng cơ bản là gọi format và chuyển vào chuỗi định dạng và bản đồ các đối tượng và tên mà chúng có tại địa phương.

Sản lượng sau đây là:

Con chó của tôi được đặt tên fido, và Jane Doe sở hữu anh ấy.

public class StringFormatter { 

    private static final String fieldStart = "\\$\\{"; 
    private static final String fieldEnd = "\\}"; 

    private static final String regex = fieldStart + "([^}]+)" + fieldEnd; 
    private static final Pattern pattern = Pattern.compile(regex); 

    public static String format(String format, Map<String, Object> objects) { 
     Matcher m = pattern.matcher(format); 
     String result = format; 
     while (m.find()) { 
      String[] found = m.group(1).split("\\."); 
      Object o = objects.get(found[0]); 
      Field f = o.getClass().getField(found[1]); 
      String newVal = f.get(o).toString(); 
      result = result.replaceFirst(regex, newVal); 
     } 
     return result; 
    } 

    static class Dog { 
     public String name; 
     public String owner; 
     public String gender; 
    } 

    public static void main(String[] args) { 
     Dog d = new Dog(); 
     d.name = "fido"; 
     d.owner = "Jane Doe"; 
     d.gender = "him"; 
     Map<String, Object> map = new HashMap<String, Object>(); 
     map.put("d", d); 
     System.out.println(
      StringFormatter.format(
       "My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.", 
       map)); 
    } 
} 

Lưu ý: Đây không biên dịch do ngoại lệ unhandled. Nhưng nó làm cho mã dễ đọc hơn nhiều.

Ngoài ra, tôi không thích rằng bạn phải tự xây dựng bản đồ trong mã, nhưng tôi không biết cách lấy tên của các biến cục bộ theo chương trình. Cách tốt nhất để làm điều đó, là nhớ đặt đối tượng vào bản đồ ngay sau khi bạn tạo ra nó.

Ví dụ sau đây tạo ra kết quả mà bạn muốn từ ví dụ của bạn:

public static void main(String[] args) { 
    Map<String, Object> map = new HashMap<String, Object>(); 
    Site site = new Site(); 
    map.put("site", site); 
    site.name = "StackOverflow.com"; 
    User user = new User(); 
    map.put("user", user); 
    user.name = "jjnguy"; 
    System.out.println(
     format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map)); 
} 

Tôi cũng nên đề cập đến mà tôi không có ý tưởng gì Velocity là, vì vậy tôi hy vọng câu trả lời này là có liên quan.

+0

là những gì tôi đang tìm kiếm. Cảm ơn bạn đã thực hiện. Tôi đã cố gắng cho nó và nhận được kết quả không chính xác. : D. Dù sao nó giải quyết vấn đề của tôi. – Joe

+2

@ Joe, vui vì tôi có thể giúp. Đó là một lý do tốt cho tôi để cuối cùng thực hành viết một số mã sử dụng sự phản chiếu trong Java. – jjnguy

+0

+1 để triển khai thực tế. – casablanca

0

Không có gì ngoài hộp có thể so sánh với vận tốc vì vận tốc được viết để giải quyết chính xác vấn đề đó.Điều gần nhất bạn có thể thử được nhìn vào Formatter

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Formatter.html

Tuy nhiên các định dạng như xa như tôi biết được tạo ra để cung cấp C như tùy chọn định dạng trong Java nên có thể không làm xước chính xác ngứa của bạn nhưng bạn đều được chào đón thử :).

4

Có một vài triển khai Ngôn ngữ biểu ra khỏi đó mà thực hiện điều này cho bạn, có thể là một lợi thế để sử dụng triển khai của riêng bạn như hoặc nếu các yêu cầu của bạn phát triển, hãy xem ví dụ JUELMVEL

Tôi thích và đã sử dụng thành công MVEL trong ít nhất một dự án.

Đồng thời xem bài đăng Stackflow JSTL/JSP EL (Expression Language) in a non JSP (standalone) context

Các vấn đề liên quan