Spring mvc 拓展使用

    Spring mvc做爲一個web mvc框架的後起之秀,其易用性,拓展性則實讓人在使用之餘,讚歎不已。本文從Spring mvcController的執行過程當中,找出一些開發者用到的幾個拓展點。 html

首先,按前後順序列一下Spring mvccontroller的執行過程: java

1.  執行全部的攔截器(實現HandlerInterceptor接口的類); web

2.  調用controller方法以前,對方法參數進行解釋綁定(實現WebArgumentResolver接口,spring3.1之後推薦使用HandlerMethodArgumentResolver); spring

3.  調用controller方法,返回邏輯視圖(一般是一個視圖的名稱); session

4.  將邏輯視圖映射到物理視圖(使用實現ViewResolver接口的類處理); mvc

5.  物理視圖渲染輸出到客戶端(實現View接口); app

6.  若在以上執行過程當中拋出了異常,能夠自定義異常處理器對不一樣的異常進行處理(實現HandlerExceptionResolver接口)。 框架

    開發者經過實現以上的接口(通常狀況下不須要從接口實現,經過繼承Spring mvc實現的一些抽象類更簡單),就能夠自定義controller執行過程當中的一些行爲,從而讓程序更富靈活性。 ide

如下是幾個經常使用的例子: post

1.  自定義攔截器,攔截未登陸用戶的請求。

AuthorityInterceptor.java

@Component
public class AuthorityInterceptor extends HandlerInterceptorAdapter{
	
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
	{
        Integer userId = (Integer)request.getSession().getAttribute("userId");
        
        //登陸才能夠繼續訪問
        if (userId != null) 
        {
            return true;
        }
        
        String contextPath = request.getContextPath();
        response.sendRedirect(contextPath + "/index.html");
        return false;
    }
}

applicationContext-mvc.xml添加配置:

<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/user/**"/>
		<ref bean="authorityInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>

值得一提的是:HandlerInterceptor接口有三個方法,preHandle在controller方法調用前攔截,postHandle在controller方法調用後攔截,afterCompletion在客戶端請求處理結束後(controller方法調用後,返回視圖,而且視圖已經渲染輸出後)攔截。

2.  自定義controller方法參數的解釋器,從session從取值綁定到方法參數。

SessionValue.java

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SessionValue {
	String value() default "";
}

SessionValueResolver.java

@Component
public class SessionValueResolver implements WebArgumentResolver {

	@Override
	public Object resolveArgument(MethodParameter parameter,
			NativeWebRequest webRequest) throws Exception {
		
		SessionValue svAnnotation = parameter.getParameterAnnotation(SessionValue.class);
		if(svAnnotation == null)
		{
			return WebArgumentResolver.UNRESOLVED;
		}
		return _resolveArgument(parameter, webRequest);
	}
	
	private Object _resolveArgument(MethodParameter parameter,
			NativeWebRequest webRequest) throws Exception {
		
		SessionValue sessionValueAnnot = parameter.getParameterAnnotation(SessionValue.class);
		
		String attrName = sessionValueAnnot.value();
		if(attrName == null || attrName.equals(""))
		{
			attrName = parameter.getParameterName();
		}
		
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		
		Object value = request.getSession().getAttribute(attrName);
		if(value == null)
		{
			throw new Exception("SessionValueResolver: session 內沒有該屬性:" + attrName);
		}
		
		return value;
	}
}

applicationContext-mvc.xml添加配置:

<bean 
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	<property name="customArgumentResolvers">
		<list>
			<ref bean="sessionValueResolver"/>
		</list>
	</property>
	<property name="order" value="1"></property>
</bean>

在controller中使用:

@RequestMapping("/get")
public String getUser(@SessionValue("userId")Integer userId)
{
	//do something 
	return "user";
}

3.  自定義文件視圖解釋器,在controller方法裏返回文件路徑,實現文件下載

FileViewResolver.java

public class FileViewResolver extends AbstractCachingViewResolver implements Ordered{
	
	private int order = Integer.MAX_VALUE;
	
	@Override
	protected View loadView(String viewName, Locale locale) throws Exception {
		if(viewName.startsWith(FileView.FILE_VIEW_PREFIX))
		{
			return new FileView(viewName);
		}
		return null;
	}

	@Override
	public int getOrder() 
	{
		return this.order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
}

FileView.java

public class FileView extends AbstractView {

	public static final String FILE_VIEW_PREFIX = "file:";
	
	private String viewName;
	
	public FileView(String viewName)
	{
		this.viewName = viewName;
	}
	
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception 
	{
		File file = getOutputFile();
		downloadFile(request, response, file);
	}

	private File getOutputFile() throws Exception 
	{
		Integer beginIndex = viewName.indexOf(FILE_VIEW_PREFIX) + FILE_VIEW_PREFIX.length();
		String filePath = viewName.substring(beginIndex).trim();
		File file = new File(filePath);
		if(file.exists())
		{
			return file;
		}
		throw new Exception("下載的文件不存在: " + filePath);
	}
	
	private void downloadFile(HttpServletRequest request,
			HttpServletResponse response, File file) 
	{
		//將文件寫入輸出流
	}
}

applicationContext-mvc.xml添加配置:

<bean class="com.plugin.FileViewResolver">
	<property name="order" value="1" />
</bean>

在controller中使用:

@RequestMapping("/download")
public String download()
{
	String filePath = "f://download/text.txt";
	return "file:" + filePath;
}

4. 自定義異常處理,拋出如下異常時,返回錯誤頁面

CustomExceptionResolver.java

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver 
{
	private static List<String> exceptionList;
	static{
		exceptionList = new ArrayList<String>();
		
		exceptionList.add("InvalidExcelException");
		exceptionList.add("NoSuchCourseExcption");
		exceptionList.add("NoTraineeExcption");
		exceptionList.add("NoQuestionExcption");
	}
 	
	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		
		if(exceptionList.contains(ex.getClass().getSimpleName()))
		{
			return new ModelAndView("error");
		}
		return null;
	}
	
}

自定義異常處理器只須要成爲spring容器的bean,無需其它配置。

Spring mvc使用拓展點介紹結束。

各位Oscer,如有關於Spring mvc使用的優秀實踐,請不吝分享,分享快樂。

相關文章
相關標籤/搜索