Spring mvc 拓展使用

本文介绍了SpringMVC框架中的扩展点,包括自定义拦截器、控制器方法参数解析器、文件视图解析器及异常处理器等内容,展示了如何通过这些扩展点增加应用的灵活性。
原文链接:http://my.oschina.net/u/1165099/blog/184377

Spring mvc作为一个web mvc框架的后起之秀,其易用性,拓展性则实让人在使用之余,赞叹不已。本文从Spring mvc的Controller的执行过程中,找出一些开发者用到的几个拓展点。

首先,按先后顺序列一下Spring mvc中controller的执行过程:

1. 执行所有的拦截器(实现HandlerInterceptor接口的类);

2. 调用controller方法之前,对方法参数进行解释绑定(实现WebArgumentResolver接口,spring3.1以后推荐使用HandlerMethodArgumentResolver);

3. 调用controller方法,返回逻辑视图(通常是一个视图的名称);

4. 将逻辑视图映射到物理视图(使用实现ViewResolver接口的类处理);

5. 物理视图渲染输出到客户端(实现View接口);

6. 若在以上执行过程中抛出了异常,可以自定义异常处理器对不同的异常进行处理(实现HandlerExceptionResolver接口)。

开发者通过实现以上的接口(一般情况下不需要从接口实现,通过继承Spring mvc实现的一些抽象类更简单),就可以自定义controller执行过程中的一些行为,从而让程序更富灵活性。

以下是几个常用的例子:

1. 自定义拦截器,拦截未登录用户的请求。

AuthorityInterceptor.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@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添加配置:
?
1
2
3
4
5
6

<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从取值绑定到方法参数。([color=red]实际上@SessionAttributes 已经提供该功能,此次仅为举例[/color])

SessionValue.java
?
1
2
3
4
5
6

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

SessionValueResolver.java
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

@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添加配置:
?
1
2
3
4
5
6
7
8
9

<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中使用:
?
1
2
3
4
5
6

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

3. 自定义文件视图解释器,在controller方法里返回文件路径,实现文件下载

FileViewResolver.java
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

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添加配置:
?
1
2
3

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

在controller中使用:
?
1
2
3
4
5
6

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

4. 自定义异常处理,抛出以下异常时,返回错误页面

CustomExceptionResolver.java
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

@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使用拓展点介绍结束。

Spring mvc使用拓展点介绍结束。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值