Spring에서 Handlebars를 쓴다면?
1. 의존성 설정
Maven<
dependency
>
<
groupId
>com.github.jknack</
groupId
>
<
artifactId
>handlebars-springmvc</
artifactId
>
<
version
>${handlebars-version}</
version
>
</
dependency
>
https://github.com/jknack/handlebars.java/tree/master/handlebars-springmvc
2. View Resolver 설정
xml base<
bean
class
=
"com.github.jknack.handlebars.springmvc.HandlebarsViewResolver"
>
<
property
name
=
"prefix"
value
=
"/WEB-INF/pages/"
/>
<
property
name
=
"suffix"
value
=
".hbs"
/>
</
bean
>
java configration@Bean
public
HandlebarsViewResolver handlebarsViewResolver() {
HandlebarsViewResolver viewResolver =
new
HandlebarsViewResolver();
viewResolver.setOrder(
1
);
viewResolver.setPrefix(
"/WEB-INF/views/"
);
viewResolver.setSuffix(
".hbs"
);
return
viewResolver;
}
3. 사용
java controller@Controller
public
class
HelloController {
@RequestMapping
(value =
"/"
, method = RequestMethod.GET)
public
ModelAndView hello() {
ModelAndView mav =
new
ModelAndView(
"index"
);
mav.addObject(
"hello"
,
"Hello world!"
);
return
mav;
}
}
index.hbs<
html
>
<
body
>
<
h1
>{{hello}}</
h1
>
</
body
>
</
html
>
html<
html
>
<
body
>
<
h1
>Hello world!</
h1
>
</
body
>
</
html
>
4. Helper 추가
java configration@Bean
public
HandlebarsViewResolver handlebarsViewResolver() {
HandlebarsViewResolver viewResolver =
new
HandlebarsViewResolver();
@Overridepublic Object apply(final Object context, final Options options) throws IOException {return "Spring Helper";}};viewResolver.registerHelper("spring", helper);viewResolver.setHelperSources(Arrays.asList(HandlebarsApp.class));Map<String, Helper<?>> helpers = new HashMap<String, Helper<?>>();helpers.put("setHelper", helper);viewResolver.setHelpers(helpers);// no cache for testingviewResolver.setCache(false);viewResolver.setBindI18nToMessageSource(true);return
viewResolver;
}
5. Handlebars + Spring boot
java controller@Controller@SpringBootApplicationpublic static class Application {@RequestMapping("/")public String index(Model model) {model.addAttribute("foo", "Hello Handlebars!");return"index";}public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
index.hbs
< html > < body > < h1 >{{foo}}</ h1 > </ body > </ html >
|
6. Registering custom helpers
하나의 helper 등록할 경우handlebars.registerHelper("blog", new Helper<Blog>() {public CharSequence apply(Blog blog, Options options) {return options.fn(blog);}});
- 여러개의 helper 를 한번에 등록할 경우public class HelperSource {public String blog(Blog blog, Options options) {return options.fn(blog);}public static String now() {return new Date().toString();}public String render(Blog context, String param0, int param1,boolean param2, Options options) {return ...}}
- instance 등록하는 방법handlebars.registerHelpers(new HelperSource());
- static 등록하는 방법handlebars.registerHelpers(HelperSource.class);
7. Helper options
하나의 helper 등록할 경우handlebars.registerHelper("blog", new Helper<Blog>() {public CharSequence apply(Blog blog, Options options) {return options.fn(blog);}});
8. HandlebarsApp.java
HandlebarsApp.javapackage com.github.jknack.handlebars.springmvc;import java.io.IOException;import java.util.Arrays;import java.util.HashMap;import java.util.Map;import com.github.jknack.handlebars.Handlebars;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.MessageSource;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.support.ResourceBundleMessageSource;import com.github.jknack.handlebars.Helper;import com.github.jknack.handlebars.Options;@Configurationpublic class HandlebarsApp {@AutowiredApplicationContext applicationContext;@Beanpublic HandlebarsViewResolver viewResolver() {HandlebarsViewResolver viewResolver = new HandlebarsViewResolver();Helper<Object> helper = new Helper<Object>() {@Overridepublic Object apply(final Object context, final Options options) throws IOException {return "Spring Helper";}};viewResolver.registerHelper("spring", helper);viewResolver.setHelperSources(Arrays.asList(HandlebarsApp.class));Map<String, Helper<?>> helpers = new HashMap<String, Helper<?>>();helpers.put("setHelper", helper);viewResolver.setHelpers(helpers);// no cache for testingviewResolver.setCache(false);viewResolver.setBindI18nToMessageSource(true);return viewResolver;}@Beanpublic HandlebarsViewResolver parameterizedHandlebarsViewResolver() {HandlebarsViewResolver viewResolver = new HandlebarsViewResolver(new Handlebars(new SpringTemplateLoader(applicationContext)));// no cache for testingviewResolver.setCache(false);return viewResolver;}@Beanpublic MessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasename("messages");return messageSource;}@Beanpublic HandlebarsViewResolver viewResolverWithoutMessageHelper() {return new HandlebarsViewResolver().withoutMessageHelper();}public static CharSequence helperSource() {return "helper source!";}}
9. Helper 추가(Create a Dynamic Select)
java configration@Bean
public
HandlebarsViewResolver handlebarsViewResolver() {
HandlebarsViewResolver viewResolver =
new
HandlebarsViewResolver();
public CharSequence apply(List<CmnCdVO> list, Options options){String lsSltId = options.param( 0 ); // SELECT IDString lsMode = options.param( 1 ); // SELECT MODE(S:선택 , A:전체)String lsEtc = options.param( 2 ); // SELECT REQUIREDStringBuffer sb = new StringBuffer(); // SELECT HTMLsb.append( "<select id='" ).append ( lsSltId ).append ( "' name='" ).append ( lsSltId ).append ( "' " ).append ( lsEtc ).append( " >" );if ( "A".equals ( lsMode ) ){sb.append( "<option value=\"\">전체</option>" );}else{sb.append( "<option value=\"\">선택</option>" );}for (CmnCdVO cmnCdVO: list){sb.append( "<option value='" ).append ( cmnCdVO.getCd() ).append ( "'>" ).append ( cmnCdVO.getNmCdKo() ).append ( "</option>" );}sb.append( "</select>" );return new Handlebars.SafeString( sb.toString() );}};viewResolver.registerHelper("select", helper);viewResolver.setHelperSources(Arrays.asList(HandlebarsApp.class));Map<String, Helper<?>> helpers = new HashMap<String, Helper<?>>();helpers.put("setHelper", helper);viewResolver.setHelpers(helpers);// no cache for testingviewResolver.setCache(false);viewResolver.setBindI18nToMessageSource(true);return
viewResolver;
}
10. Custom Helper 분리 구성
java configration@Bean
public
HandlebarsViewResolver handlebarsViewResolver() {
HandlebarsViewResolver viewResolver =
new
HandlebarsViewResolver();
viewResolver.registerHelper("select", new SelectHelper());viewResolver.registerHelper("math", new MathHelper());viewResolver.registerHelper("url", new UrlHelper());viewResolver.registerHelpers(ConditionalHelpers.class); // handlebars 자체 확장Helper 추가viewResolver.setOrder(0);viewResolver.setViewClass(HandlebarsView.class);viewResolver.setContentType(DEFAULT_CONTENT_TYPE);viewResolver.setPrefix("/WEB-INF/views/hbs/");viewResolver.setSuffix(".hbs");viewResolver.setCache(false);viewResolver.setFailOnMissingFile(false);return viewResolver;}
- Select Custom Helperimport java.util.List;import com.github.jknack.handlebars.Handlebars;import com.github.jknack.handlebars.Helper;import com.github.jknack.handlebars.Options;import com.gsc.component.share.vo.ViewCmnCdVO;/*** Handlebars Select Helper**/public class SelectHelper implements Helper<List<ViewCmnCdVO>>{public CharSequence apply(List<ViewCmnCdVO> list, Options options){String lsSltId = options.param( 0 ); // SELECT IDString lsMode = options.param( 1 ); // SELECT MODE(S:선택 , A:전체)String lsEtc = options.param( 2 ); // SELECT REQUIREDStringBuffer sb = new StringBuffer(); // SELECT HTMLsb.append( "<select id='" ).append ( lsSltId ).append ( "' name='" ).append ( lsSltId ).append ( "' " ).append ( lsEtc ).append( " >" );if ( "A".equals ( lsMode ) ){sb.append( "<option value=\"\">전체</option>" );}else{sb.append( "<option value=\"\">선택</option>" );}for (ViewCmnCdVO cmnCdVO: list){sb.append( "<option value='" ).append ( cmnCdVO.getCd() ).append ( "'>" ).append ( cmnCdVO.getNmCdKo() ).append ( "</option>" );}sb.append( "</select>" );return new Handlebars.SafeString( sb.toString() );}}
- Math Custom Helper - https://github.com/mrhanlon/handlebars-math-helperimport java.io.IOException;import java.math.BigDecimal;import java.math.MathContext;import java.math.RoundingMode;import com.github.jknack.handlebars.Helper;import com.github.jknack.handlebars.Options;/*** Handlebars Math Helper** <p>* Perform math operations in handlebars. Inspired by: http://jsfiddle.net/mpetrovich/wMmHS/* Operands are treated as java.math.BigDecimal and operations are performed with the* java.math.MathContext.DECIMAL64 MathContext, yielding results with 16 bits of precision* and rounding to the nearest EVEN digit, according to IEEE 754R. You can force rounding* decimal results using the extra parameter <code>scale</code>, which corresponds to calling* <code>BigDecimal.setScale(int scale, RoundingMode.HALF_UP)</code>.* </p>** <p>addition</p>** <pre>{{math arg0 "+" arg1}} // arg0 + arg1</pre>** <p>subtraction</p>** <pre>{{math arg0 "-" arg1}} // arg0 - arg1</pre>** <p>multiplication</p>** <pre>{{math arg0 "*" arg1}} // arg0 * arg1</pre>** <p>division</p>** <pre>{{math arg0 "/" arg1}} // arg0 / arg1</pre>** <p>modulus</p>** <pre>{{math arg0 "%" arg1}} // arg0 % arg1</pre>** @author mrhanlon* @see java.math.BigDecimal* @see java.math.MathContext*/public class MathHelper implements Helper<Object> {public enum Operator{add("+"),subtract("-"),multiply("*"),divide("/"),mod("%");private Operator(String symbol){this.symbol = symbol;}private String symbol;public static Operator fromSymbol(String symbol){Operator op = null;if (symbol.equals("+")){op = add;} else if (symbol.equals("-")){op = subtract;} else if (symbol.equals("*")){op = multiply;} else if (symbol.equals("/")){op = divide;} else if (symbol.equals("%")){op = mod;}return op;}}@Overridepublic CharSequence apply(final Object value, Options options) throws IOException, IllegalArgumentException{if (options.params.length >= 2){Operator op = Operator.fromSymbol(options.param(0).toString());if (op == null){throw new IllegalArgumentException("Unknown operation '" + options.param(0) + "'");}Integer scale = options.hash("scale");MathContext mc = new MathContext(16, RoundingMode.HALF_UP);if (value == null || options.param(1) == null){throw new IllegalArgumentException("Cannot perform operations on null values");}BigDecimal t0 = new BigDecimal(value.toString());BigDecimal t1 = new BigDecimal(options.param(1).toString());BigDecimal result;switch (op){case add : result = t0.add(t1, mc);break;case subtract : result = t0.subtract(t1, mc);break;case multiply : result = t0.multiply(t1, mc);break;case divide : result = t0.divide(t1, mc);break;case mod : result = t0.remainder(t1, mc);break;default : throw new IllegalArgumentException("Unknown operation '" + options.param(0) + "'");}if (scale != null){result = result.setScale(scale, BigDecimal.ROUND_HALF_UP);}return result.toString();}else{throw new IOException("MathHelper requires three parameters");}}}
- Url Custom Helper - html 태그 url decocdingimport com.github.jknack.handlebars.Handlebars;import com.github.jknack.handlebars.Helper;import com.github.jknack.handlebars.Options;/*** Handlebars Url Helper**/public class UrlHelper implements Helper<String>{public CharSequence apply( String value, Options options){return new Handlebars.SafeString( value );}}
참조
https://jknack.github.io/handlebars.java/helpers.html (Handlebars.java)
http://allegro.tech/2015/04/spring-boot-starter-handlebars.html (Spring Boot Handlebars)
https://slipp.net/wiki/display/SLS/mustache#mustache-잉여내용:Spring에서Handlebars를쓴다면?