Spring MVC注解小例子

##前言
本文将用注解的形式实现Spring MVC的功能。对于Spring MVC的入门,可以参考本人的前一篇博文。作为一位程序猿界的新人,如有谬误,欢迎指正。

##引用jar包
在项目中引用如下jar包:

.
├──lib
|  ├── commons-logging-1.0.4.jar
|  ├── spring-aop.jar
|  ├── spring-beans.jar
|  ├── spring-context.jar
|  ├── spring-context-support.jar
|  ├── spring-core.jar
|  ├── spring-expression.jar
|  ├── spring-web.jar
|  ├── spring-webmvc.jar

##web.xml配置
本例子中,我们使用自定义的配置文件,拦截规则是/

<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <!-- 这里指定配置文件为WEB-INF下面的springMVC.xml -->
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/springMVC.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

##springMVC.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="  
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <context:component-scan base-package="com.wonsikin" />

    <mvc:annotation-driven />

    <!-- 视图解释器 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />

                <bean
                    class="org.springframework.http.converter.ResourceHttpMessageConverter" />
            </list>
        </property>
    </bean>
</beans>

< context:component-scan base-package=”com.wonsikin” />表示自动扫描的包名。

< mvc:annotation-driven />表示默认的注解映射的支持。如何替换 < mvc:annotation-driven />?请参考赵磊的博客的第十九节。

##模型(Model)
创建一个登录用户的模型,如下:

package com.wonsikin.view;

public class LoginUser {

    private String username;

    private String password;

    /**
    *getter,setter
    */
    ......

}

##控制器(Controller)

package com.wonsikin.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.wonsikin.view.LoginUser;


@Controller
@RequestMapping("/wonsikin")
public class LoginController {

    @RequestMapping("/login")
    public ModelAndView login(@ModelAttribute LoginUser user) throws Exception {
        System.out.println(user.getUsername());
        return new ModelAndView("loginInfo","username",user.getUsername());
    }
}

注解@Controller声明该类为一个Action组件。

类名上面的注解@RequestMapping(“/wonsikin”)类似Struts2的命名空间(namespace),用来声明该类下的方法的父路径为/wonsikin

方法上面的注解@RequestMapping(“/login”)表示调用该方法的路径。

方法中的参数的注解@ModelAttribute表示该前台传过来的参数会被自动解析成一个模型。类似Struts2的模型驱动。

一个控制器里面同时多个方法处理的情况跟这个差不多,无非就是多几个方法,多配置一些路径。在此不赘述。

##REST风格的路径
现在的互联网,REST风格非常流行,很多互联网类型的应用都很喜欢这样的URL。实现这样的功能需要一个注解@PathVariable。同时我们会比较另一个注解@RequestParam,因为这两个注解在功能上非常相似。

@RequestParam用来获取路径中传过来的参数,也就是问号后面的参数。

@PathVariable则是用来获取路径中的变量参数。

举个栗子:

package com.wonsikin.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;


@Controller
@RequestMapping("/userCtl")
public class UserController {

    @RequestMapping("/{userId}/add")
    public ModelAndView add(@PathVariable String userId,@RequestParam String action){
        System.out.println(userId);
        System.out.println(action);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", userId);
        map.put("action", action);
        return new ModelAndView("variable","map",map);
    }
}

当我们向服务器发送请求如下请求时

http://localhost:8081/SpringMVCAnnotation/userCtl/12345/add?action=add

后台截取到的变量分别是

userId:12345
action:add

##静态文件的访问
由于我们的拦截规则是/,这就会导致一些静态文件无法获取到。只需在springMVC.xml中添加如下配置即可:

<!-- 允许对静态资源文件的访问 -->
<mvc:default-servlet-handler/>

事实上,解决静态文件无法访问的方法有多种,详情可以参考赵磊的博客第七小节。

##结语
Spring的注解非常强大,用好注解能减轻我们配置XML的负担。

##参考

  1. 赵磊的博客
  2. StackOverflow上关于@RequestParam和@PathVariable区别的回答