SpringMVCは、 DIコンテナとして有名なSpringのサブプロジェクトとして提供されているWebアプリケーションフレームワークです。
Mixer2には、Spring MVC におけるViewResolverおよび抽象Viewクラスも同梱されています。 ViewのテンプレートとしてJSPを使用する通常のControllerクラスの書き方とほとんど同じ形で 普通のhtmlテンプレートをViewとして使用することができます。
ビューエンジンとして、Mixer2と通常のJSPの両方を使えるようにする場合、 SpringMVCのDispatcherServlet用のDI定義は次のようになります。
<!-- other configuration... --> <context:component-scan base-package="com.example.yourproject" /> <mvc:annotation-driven /> <mvc:resources mapping="/m2static/**" location="classpath:/m2mockup/m2static/" /> <bean id="mixer2Engine" class="org.mixer2.Mixer2Engine" /> <bean class="org.mixer2.spring.webmvc.Mixer2XhtmlViewResolver"> <property name="order" value="1" /> <property name="prefix" value="classpath:m2mockup/m2template/" /> <property name="suffix" value=".html" /> <property name="basePackage" value="com.example.yourproject.web.view" /> <property name="mixer2Engine" ref="mixer2Engine" /> </bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="order" value="2" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp"/> </bean> <!-- other configuration... -->
ただし、最近のSpringFrameworkはXML定義よりもJavaConfiguration方式を推奨しています。 JavaConfigを使う場合は下のような形になるでしょう。
@Configuration @EnableAutoConfiguration @EnableWebMvc @ComponentScan("com.example.yourproject") public MyConfig extends WebMvcConfigurerAdapter { @Bean public Mixer2Engine mixer2Engine() { return new Mixer2Engine(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/m2static/**") .addResourceLocations("classpath:/m2mockup/m2static/"); } @Bean public Mixer2XhtmlViewResolver mixer2XhtmlViewResolver() { Mixer2XhtmlViewResolver resolver = new Mixer2XhtmlViewResolver(); resolver.setPrefix("classpath:m2mockup/m2template/"); resolver.setSuffix(".html"); resolver.setBasePackage("com.example.yourproject.web.view"); resolver.setMixer2Engine(mixer2Engine); resolver.setOrder(1); return resolver; } @Bean public InternalResourceViewResolver internalResourceViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/jsp/"); resolver.setSuffix(".jsp"); resolver.setOrder(2); return resolver; } }
上記の設定は、下のようなソースコードツリー構造を想定しています。 maven標準ディレクトリ構造に習っていますが、 classpathやドキュメントルートからの階層が合っていれば、他の構造でも問題はありません。
src/ └── main/ ├── java/ │ └── com/ │ └── example/ │ └── yourproject/ │ ├── Config.java // JavaConfig方式の場合 │ ├── service/ │ └── web/ │ ├── controller/ │ │ ├── FooController.java │ └── view/ │ ├── FooView.java │ ├── resources/ │ ├── mvc-dispatcher-servlet.xml // XML設定方式の場合 │ └── m2mockup/ │ ├── m2static/ │ │ ├── css/ │ │ │ └── main.css │ │ └── img/ │ │ └── sample.png │ └── m2template/ │ └── foo.html └── webapp/ └── WEB-INF/ └── jsp/ └── bar.jsp
FooControllerクラスで、"/foo"というURIへのアクセスをMixer2で処理し、 "/bar"というURIへのアクセスをJSPで処理する場合、 Controllerのコードは下記のようになります。
@Controller public class IndexController { @RequestMapping(value = "/foo", method = RequestMethod.GET) public String foo(Model model) { model.addAttribute("someMessage", "Life is beautiful"); // attach to FooView class with foo.html template // by Mixer2ViewResolver . return "foo"; } @RequestMapping(value = "/bar", method = RequestMethod.GET) public String bar() { // attach to bar.jsp by InternalResourceViewResolver . return "bar"; } }
"/foo"へのアクセスに対するViewクラスとしてFooViewを作る必要があります。 下記のようなコードになります。
Viewクラスに対して@Componentなどを指定する必要はありません。 前述のDI定義でbasePackageとしてcom.example.yourproject.web.viewを指定したため、 Mixer2ViewResolverはその配下のViewクラスのコンポーネント化とDIを自動的に行います。
... import org.mixer2.spring.webmvc.AbstractMixer2XhtmlView; ... public class FooView extends AbstractMixer2XhtmlView { // You can use any bean in DI container. @Autowired private HelloWorldBean helloWorldBean; @Override protected Html renderHtml(Html html, Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) { // Mixer2ViewResolver has load "foo.html" template // into "html" variable automatically. // So, You can modify it. Div div = html.getById("hellomsg", Div.class); div.replaceInner(helloWorldBean.getHelloWorldMessageString()); // Of course, you can use model that is delivered from controller. String someMessage = (String) model.get("someMessage"); div.replaceInner(someMessage); // replace static file path. // For example: <img src="../m2static/img/sample.png" /> // will be changed to <img src="[contextPath]/m2static/img/sample.png" /> Pattern pattern = Pattern.compile("^\\.+/.*m2static/(.*)$"); String ctx = request.getContextPath(); PathAdjuster.replacePath(html, pattern, ctx + "/m2static/$1"); return html; } @Override protected String modifyHtmlStringHook(String htmlStr) { StringBuilder sb = new StringBuilder(); sb.append("<!--[if lt IE 9]><script src=\"/static/html5shiv.js\"></script><![endif]-->"); sb.append("</head>"); return htmlStr.replaceFirst("</head>", sb.toString()); } }
ECサイトを想定した簡単なサンプルアプリケーションもあります。 Fruit shop sample application for SpringMVC and SpringBoot をご覧ください。