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.jspFooControllerクラスで、"/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 をご覧ください。