Setup Spring MVC 3.2 project without web.xml

ตอนที่แล้ว ผมพา Setup ไปครั้งหนึ่ง แต่นั่นเป็นของ version 3.1 คราวนี้ผมจะพา Setup ของ version 3.2 จุดต่างกันมีแค่จุดเดียวคือตรง WebAppInitializer ซึ่งของเดิมจะ implements WebApplicationInitializer แต่คราวนี้จะเป็นอะไร ลองไปดูกัน

WebInitializer

package com.magicalcyber.springmvc.web.config;

import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.log4j.Logger;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebInitializer extends
		AbstractAnnotationConfigDispatcherServletInitializer {

	private static final Logger logger = Logger.getLogger(WebInitializer.class);

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[] { RootConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[] { WebConfig.class };
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

	@Override
	protected Filter[] getServletFilters() {
		logger.debug("getServletFilters");
		
		CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
		characterEncodingFilter.setEncoding("UTF-8");
		characterEncodingFilter.setForceEncoding(true);

		// HiddenHttpMethodFilter will help you get around the problem, but you
		// have to include a hidden field _method=PUT in your form. If you use
		// the spring:form taglib this will be done automatically for you, but
		// your example seems to use plain HTML.
		//
		// Reference: http://stackoverflow.com/a/13651928
		HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();

		// From Spring Framework Documents: HiddenHttpMethodFilter
		// NOTE: This filter needs to run after multipart processing in case of
		// a multipart POST request, due to its inherent need for checking a
		// POST body parameter.So typically, put a Spring MultipartFilter before
		// this HiddenHttpMethodFilter in your web.xml filter chain.

		return new Filter[] { hiddenHttpMethodFilter, characterEncodingFilter };
	}

	@Override
	public void onStartup(ServletContext servletContext)
			throws ServletException {
		logger.debug("onStartup");
		super.onStartup(servletContext);//MUST HAVE
		servletContext.setInitParameter("defaultHtmlEscape", "true");
	}
}

ดูกระทัดรัด สบายตาขึ้นนะ (ถ้าไม่นับ comment ที่ผมทำไว้เตือนตัวเองนะ) สิ่งที่เปลี่ยนแปลงคือเราต้องไป extends AbstractAnnotationConfigDispatcherServletInitializer ซึ่งคลาสนี้ก็ไป implements WebApplicationInitialize อีกทีหนึ่ง

สิ่งสำคัญในการ extends คลาสนี้คือ ถ้าไปดูใน Docs ของคลาส WebApplicationInitializer จะมี NOTE ทิ้งไว้ให้ว่า เราสามารถใช้คลาสนี้ได้ แต่มันจะไม่ start ทันทีเมื่อทำการ Start Server ทำให้มันไม่ทำการ initialize ค่าต่างๆ ให้ แล้วก็ไม่ได้บอกอะไรไว้เลย (T_T) ผมก็นั่งงมอยู่พักใหญ่ถึงรู้ว่า เราต้องทำการ override onStartup เพื่อสั่งให้คลาสแม่ที่ไปสืบทอดมาทำงาน (ตรงบรรทัด super.onStartup(servletContext);)

ที่เหลือไม่ต้องแก้อะไรเลยก็สามารถทำงานได้ ซึ่งถ้าต้องแก้ก็คงเป็นแค่ค่า config ที่ปรับตามความชอบของแต่ละคน อย่างผมมีปรับตรง messageSource ของคลาส WebConfig ให้ชี้ไปที่ classpath:messages/messages

ใหนๆ ก็มาถึงขั้นนี้แล้ว เอาที่ผมปรับใหม่มาให้ครบเลยดีกว่า จะได้ copy แล้วเอาไปใช้ได้เลย

RootConfig

package com.magicalcyber.springmvc.web.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Contains middle-tier services, data sources, etc.
 */

@Configuration
@ComponentScan(basePackages = { "com.magicalcyber.springmvc.service" })
public class RootConfig {

}

WebConfig

package com.magicalcyber.springmvc.web.config;

import java.util.Locale;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

/**
 * Contains controllers, view resolvers, locale resolvers, and other web-related beans.
 */

@Configuration
@ComponentScan(basePackages = { "com.magicalcyber.springmvc.web" })
public class WebConfig extends WebMvcConfigurerAdapter {

	private static final Logger logger = Logger.getLogger(WebConfig.class);

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		logger.debug("addResourceHandlers");
		registry.addResourceHandler("/resources/").addResourceLocations(
				"/resources/**");
	}

	@Override
	public void configureDefaultServletHandling(
			DefaultServletHandlerConfigurer configurer) {
		logger.debug("configureDefaultServletHandling");
		// if the spring dispatcher is mapped to / then forward non handled
		// requests
		// (e.g. static resource) to the container's "default servlet"
		configurer.enable();
	}

	@Override
	public void addInterceptors(final InterceptorRegistry registry) {
		logger.debug("addInterceptors");
		// Default name of the locale specification parameter: "locale".
		LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
		localeChangeInterceptor.setParamName("lang");
		registry.addInterceptor(localeChangeInterceptor);
	}

	@Bean
	public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
		logger.debug("simpleMappingExceptionResolver");

		SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
		Properties mappings = new Properties();
		mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
		mappings.put("org.springframework.dao.DataAccessException",
				"dataAccessFailure");
		mappings.put("org.springframework.transaction.TransactionException",
				"dataAccessFailure");
		b.setExceptionMappings(mappings);

		return b;
	}

	@Bean
	public ViewResolver viewResolver() {
		logger.debug("viewResolver");

		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");

		return viewResolver;
	}

	@Bean
	public MessageSource messageSource() {
		logger.debug("messageSource");

		ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
		messageSource.setBasenames("classpath:messages/messages");
		messageSource.setCacheSeconds(5);
		messageSource.setDefaultEncoding("UTF-8");

		return messageSource;
	}

	@Bean
	public LocaleResolver localeResolver() {
		logger.debug("localeResolver");

		SessionLocaleResolver lr = new org.springframework.web.servlet.i18n.SessionLocaleResolver();
		lr.setDefaultLocale(Locale.ENGLISH);

		return lr;
	}
}

ปิดท้ายด้วย Hello World!

ถ้าสังเกตุดูจะเห็นว่า เราไม่ได้ตั้งค่า welcome file ที่เป็นพวก index.jsp ไว้เลย แล้วถ้าจะสั่ง redirect หน้าแรกจะทำอย่างไร ผมก็เลยทำ Hello World ฉบับมาเป็นตัวอย่าง

IndexController

package com.magicalcyber.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
	@RequestMapping(value = "/")
	public String index() {
		return "home";
	}
}

สั้นๆ ง่ายๆ คือเรา mapping “/” เอาไว้ ซึ่งก็เอาไว้แทน redirect ได้ ซึ่งผมสั่งให้ redirect ไปยังไฟล์”home”

home.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
Hello World!<br/>
Spring MVC 3.2 (No web.xml) Setup
</body>
</html>

2 thoughts on “Setup Spring MVC 3.2 project without web.xml

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s