Java-SpringMVC学习笔记之特点、作用及基础配置

1.主流的mvc构架包括:

struts1, webwork, strut2, spring mvc, jsf

2.spring MVC特点:

@  功能组件划分细致
@  灵活、强大
@  设计思想优秀

3.spring mvc的作用:

@、以Controller为中心完成对系统流程的控制管理
@、从请求中收集数据
@、对传入参数进行验证
@、根据请求调用相应业务逻辑完成数据处理
@、将处理结果返回给视图
@、国际化支持
@、针对不同视图技术提供不同解析支持方案
@、针对JSP视图技术提供标签库
@、通过拦截器链实现面向方面编程完成系统级控制
@、对文件上传、下载等常用功能的封装

4.Spring MVC框架的核心构件

Dispatcher Servlet (分发器、调度器)
Controller (控制器)
Handler Mapping (映射器)
ViewResolver  & View (视图解析器及视图处理类)
Interceptors (拦截器)
LocalResolver
Validate

5.spring MVC示例1
spring-framework下载
Latest GA release: 3.0.1.RELEASE-A

spring-framework-3.0.1.RELEASE-A-dependencies.zip 133.3 MB
spring-framework-3.0.1.RELEASE-A-with-docs.zip 45.3 MB
spring-framework-3.0.1.RELEASE-A.zip 21.8 MB

加Jar包
下载spring 的jar包,包括:spring 本身之外还要下载: spring framework dependencies.zip 它所依赖的一些包。
首先新建一个个名为spring_mvc_test的web project,先导入以下几个包:
(找不到的jar包可以到jarvana去找)

springframework.beans-3.1.0.RELEASE.jar
springframework.context-3.1.0.RELEASE.jar
springframework.context.support-3.1.0.RELEASE.jar
springframework.core-3.1.0.RELEASE.jar
springframework.web.servlet-3.1.0.RELEASE.jar
commons-logging-1.1.1.jar

文件结构
文件结构

配置web.xml

<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup> <!-- 在项目启动时就加载 -->
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.test</url-pattern>    <!-- 获得所有以 .test的请求,即管理所有以 .test的请求 -->
</servlet-mapping>    <servlet>
<servlet-name>test</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup> <!-- 在项目启动时就加载 -->
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.test</url-pattern>    <!-- 获得所有以 .test的请求,即管理所有以 .test的请求 -->
</servlet-mapping>

spring mvc 特点

1.它是一个大的对象工厂,这是整个spring最核心、最基本的功能。spring mvc的核心功能,表现在在依赖注入。
2.dispatcher servlet在被初始化的时候,就会读取配置文件中的各个bean,完成对各个类型、各个构件的初始化过程。
3.如查没有指定dispatcher(调度器)读取哪一个配置文件,dispatcher会默认读取/WEB-INF/[servlet-name]-servlet.xml配置文件。
4.建一个名为StartController的java文件,再在WEB-INF/目录下建一个test-servlet.xml的配置文件。

StartController.java

package test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
 * @className:StartController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-12下午09:21:58
 */
public class StartController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
                                      HttpServletResponse response) throws Exception {
        System.out.println("start controller is working !");
        return new ModelAndView("start");    //只指定一个视图的逻辑名称叫start
        //使用控制器与视图名称完全分离,只返回一个名称叫start的视图,具体返回什么视图由后续配置决定。
    }

test-servlet.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"
       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">
    <!-- 定义控制器 -->
    <bean id="startController" class="test.StartController"></bean>
    <!-- 定义映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="start.test">startController</prop><!-- key是url,text是控制器的名称 -->
            </props>
        </property>
    </bean>
    <!-- 配置url解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <!-- 视图处理类 -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"/><!-- 返回的逻辑名称的前缀 -->
        <property name="suffix" value=".jsp"/><!-- 返回的逻辑名称的后缀 -->
    </bean>
</beans>

发布到tomcat启动,根据错误提示,添加缺少的对应的Jar包,有如下:

org.springframework.web-3.1.0.RELEASE.jar
org.springframework.asm-3.1.0.RELEASE.jar
org.springframework.expression-3.1.0.RELEASE.jar

start.jsp

<body>
This is my start jsp page. <br>
</body>

运行结果
图1
图2

控制器功能结构
控制器功能结构

modules
modules

spring mvc常用controller

@、直接实现Controller 接口或AbstractController抽象类
@、ModelAndView对象 模型视图对象
@、用于直接跳转页面的
ParameterizableViewController, UrlFilenameViewController
参数化视图控制器,url文件名视图控制器

@、在同一控制器类中处理多个请求的MultiActionController.具体调用的方法通过MethodNameResolver决定 (InternalPathMethodResolver, ParameterMethodNameResolver, PropertiesMethodResolver) 

按照请求路径名解析,按照参数方法名解析,按照属性方法名解析
方法签名:
public (ModelAndView | Map | String | void) actionName(HttpServletRequest request, HttpServletResponse response, [,HttpSession] [,AnyObject]);

@、能封装表单参数的CommondController、 FormController
如果一个控制器实现了CommandContrller 或FormController,那么它就可以直接接收一个表单对象。

基于示例1的示例2

文件结构
文件结构

命令控制器 EmpController.java

package test;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ejb.Handle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;
import org.springframework.web.servlet.mvc.AbstractController;
/**
 * @className:EmpController.java
 * @classDescription:Emp控制器
 * @author:wei.luo
 * @createTime:2012-2-13
 */
/*public class EmpController extends AbstractController {    //实现简单的Controller抽象类
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
            HttpServletResponse response) throws Exception {    //
        String name=request.getParameter("name");
        String phone=request.getParameter("phone");
        Emp emp=new Emp();
        emp.setName(name);
        emp.setPhone(phone);
        //empService.add(emp);
        return null;
    }
}*/
public class EmpController extends AbstractCommandController{
    @Override
    protected ModelAndView handle(HttpServletRequest request,
                                  HttpServletResponse response, Object command, BindException errors)
            throws Exception {
        Emp emp=(Emp)command;
        System.out.println(emp.toString());
        return new ModelAndView("success");
    }
    /**
     * 初始化数据绑定器
     */
    @Override
    protected void initBinder(HttpServletRequest request,
                              ServletRequestDataBinder binder) throws Exception {
        //绑定日期数据,注册一个新的日期编辑器
        binder.registerCustomEditor(Date.class, new CustomDateEditor(
                new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}

Emp.java

package test;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * @className:Emp.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-13
 */
public class Emp {
    private int empNo;
    private String name;
    private String phone;
    private Date hireDate;
    private String dept;
    public int getEmpNo() {
        return empNo;
    }
    public void setEmpNo(int empNo) {
        this.empNo = empNo;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public Date getHireDate() {
        return hireDate;
    }
    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }
    public String getDept() {
        return dept;
    }
    public void setDept(String dept) {
        this.dept = dept;
    }
    @Override
    public String toString() {
        return "Emp [empNo="+empNo+",name=" + name + ", phone=" + phone
                + ",hireDate="+new SimpleDateFormat("yyyy-MM-dd").format(hireDate)
                +",dept="+dept+"]";
    }
}

test-servlet.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"
       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">
    <!-- 定义映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="start.test">startController</prop><!-- key是url,text是控制器的名称 -->
                <prop key="login.test">loginController</prop>
                <prop key="add_emp.test">addEmpController</prop>
                <prop key="add.test">addEmpSuccController</prop>
            </props>
        </property>
    </bean>
    <bean id="startController" class="test.StartController"></bean>
    <!-- 给loginController配置一个参数化的视图控制器类 --><!---
<bean id="loginController" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName" value="login"></property> --><!-- 返回一个名称叫login的视图 -->
    <!-- </bean> -->
    <!-- 给loginController配置一个按url文件名决定的一个控制器,这样可以省去配置视图名的过程 -->
    <bean id="loginController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
    <!-- 一个url对应一个controller的情况 -->
    <bean id="addEmpController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
    <!-- 命令控制器 -->
    <bean id="addEmpSuccController" class="test.EmpController">
        <property name="commandClass" value="test.Emp"></property> <!-- 指定command对象的类别 -->
    </bean>
    <!-- 配置url解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <!-- 视图处理类 -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"/><!-- 返回的逻辑名秼/span>
</bean>
</beans>

自定义属性编辑器(MyEditor.java)

package test;
import java.beans.PropertyEditorSupport;
/**
 * @className:MyEditor.java
 * @classDescription:自定义一个属性编辑器
 * @author:wei.luo
 * @createTime:2012-2-13
 */
public class MyEditor extends PropertyEditorSupport {
    @Override
    public String getAsText() {
        // TODO Auto-generated method stub
        return super.getAsText();
    }
    @Override
    public void setValue(Object value) {
        // TODO Auto-generated method stub
        super.setValue(value);
    }
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        // TODO Auto-generated method stub
        super.setAsText(text);
    }
}

表单控制器
EmpFormController.java

package test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
/**
 * @className:EmpFormController.java
 * @classDescription:表单控制器
 * @author:wei.luo
 * @createTime:2012-2-13上午02:41:45
 */
public class EmpFormController extends SimpleFormController {
    /**
     * 当表单提交是执行
     */
    @Override
    protected ModelAndView onSubmit(Object command) throws Exception {
        Emp emp=(Emp)command;    //注意,直接将command对象转换成Emp对象即可
        System.out.println(emp.toString());
        return new ModelAndView(getSuccessView());
    }
    /**
     * 此方法处理模型,向模型中加入两个列表
     */
    @Override
    protected Map referenceData(HttpServletRequest request) throws Exception {
        Map<String,Object> model=new HashMap<String,Object>();    //建立一个模型
        model.put("deptList", new String[]{"sales","manage"});    //向模型中放入一个列表
        return model;    //返回加入了deptList的模型
    }
    /**
     * 添加日期属性编辑器
     */
    @Override
    protected void initBinder(HttpServletRequest request,
                              ServletRequestDataBinder binder) throws Exception {
        //绑定日期数据,注册一个新的日期编辑器
        binder.registerCustomEditor(Date.class, new CustomDateEditor(
                new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}

配置文件(test-servlet.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"
       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">
    <!-- 定义映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="start.test">startController</prop><!-- key是url,text是控制器的名称 -->
                <prop key="login.test">loginController</prop>
                <prop key="add_emp.test">addEmpController</prop>
                <!-- <prop key="add.test">addEmpSuccController</prop> -->
            </props>
        </property>
    </bean>
    <bean id="startController" class="test.StartController"></bean>
    <!-- 给loginController配置一个按url文件名决定的一个控制器,这样可以省去配置视图名的过程 -->
    <bean id="loginController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
    <!-- 表单控制器,使用一个controller对应多个url处理 -->
    <bean id="addEmpController" class="test.EmpFormController">
        <property name="commandClass" value="test.Emp"/><!-- 它也需要command对象是什么类别 -->
        <property name="formView" value="add_emp"/><!-- 表单提交页面 -->
        <property name="successView" value="success"/><!-- 表单成功页面 -->
    </bean>
    <!-- 配置url解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <!-- 视图处理类 -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"/><!-- 返回的逻辑名称的前缀 -->
        <property name="suffix" value=".jsp"/><!-- 返回的逻辑名称的后缀 -->
    </bean>
</beans>

运行截图:
spring mvc 的controller控制器处理
spring mvc 的controller控制器处理

绑定注册日期属性编辑器控件
绑定注册日期属性编辑器控件

处理模型
处理模型

一个controller对应多个url的处理
一个controller对应多个url的处理

MultiController
要点: 1.如果没有指定视图名称,那么spring mvc 它会按默认的方式来指定视图名称。

EmpMultiController.java

package test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
/**
 * @className:EmpMultiController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-14
 */
public class EmpMultiController extends MultiActionController {
    private ModelAndView toAdd() {
        //viewName logic name :视图的逻辑名
        //Model 隐含了Map对象
        //构建模型的方法:
        //1.直接在new的时候,传入模型名称
        //ModelAndView mav=new ModelAndView("add_emp");
        //2.先构建模型,再执行setViewName方法
        //ModelAndView mav=new ModelAndView();
        //mav.setViewName("add_emp");
        //3.加入模型项
        //mav.addObject(attributeValue);
        //4.也可以一次性加入一个Map项
        //Map model = new HashMap;
        //mav.addAllObjects(modelMap);
        ModelAndView mav = new ModelAndView();
        mav.setViewName("add_emp");
        mav.addObject("deptList",new String[]{"salse","manage"});
        return mav;
    }
    //public ModelAndView addEmp(HttpServletRequest request,
    public String addEmp(HttpServletRequest request,
                         HttpServletResponse response,HttpSession session,Emp emp){
        System.out.println(emp);
        //return new ModelAndView("success");
        return "success";    //直接返回一个字符串,就是viewName
    }
}

test-servlet.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"
       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">
    <!-- 定义映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="start.test">startController</prop><!-- key是url,text是控制器的名称 -->
                <prop key="login.test">loginController</prop>
                <prop key="to_add.test">addEmpController</prop>
                <prop key="add_emp.test">addEmpController</prop>
                <!-- <prop key="add.test">addEmpSuccController</prop> -->
            </props>
        </property>
    </bean>
    <bean id="startController" class="test.StartController"></bean>
    <!-- MultiController -->
    <bean id="addEmpController" class="test.EmpMultiController">
        <property name="commandClass" value="test.Emp"/>
        <property name="methodNameResolver">
            <!-- 按照参数进行方法名的解析器 -->
            <bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
                <property name="paramName" value="func"></property>    <!-- 此参数决定调用哪一个方法名 -->
            </bean>
        </property>
    </bean>
    <!-- 配置url解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <!-- 视图处理类 -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"/><!-- 返回的逻辑名称的前缀 -->
        <property name="suffix" value=".jsp"/><!-- 返回的逻辑名称的后缀 -->
    </bean>
</beans>

spring mvc 常用的Handler mapping
@、默认的ControllerClassNameHandlerMapping
按照控制器的类名来自动完成映射,在这需要使用拦截器的时候,它不需要配置任何属性。如下:

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">

当发送一个以 abc.test 结尾的请求时,它会找一个名称为AbcController,直接根据控制器的类名匹配请求的路径来寻找控制器。

如果是multiController
如果是multiController

@、常用的SimpleUrlHandlerMapping 按照简单的Url映射 @、BeanNameUrlHandlerMapping 按照beanName的Url来映射。 @、基于注解Controller时使用的DefaultAnnotationHandlerMapping

基于注解的MVC

**要点:**

基于xml文件配置的mvc的缺点:到项目到达一定程序是,就会有很多的配置文件,造成项目维护起来比较麻烦,优点:低侵入式,降低了耦合。  
新建一个名为 :@mvc 的项目,并把配置spring mvc需要的Jar都加到WEB-INF/lib目录下。
在项目中建两个源包,src/java , src/config ,源包在编译之后,都会跑到Tomcat相应的应用目录下的WEB-INF/classes目录下。
在config源包中建一个spring包,并在spring包中建一个servlet.xml,配置servlet.xml,如果要使用基于注解的spring mvc ,则在配置文件中必须加入一个 context 与 mvc 的命名空间。
5. controller类可以不定义requestMapping,但一个要请求路径的方法,就必须定义requestMapping。

配置文件的模式定义

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd" >
</beans>

示例3(基于注解的配置)
文件结构:
文件结构:

servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd" >
    <!-- 主键扫描,配置要扫描的Java类 -->
    <context:component-scan base-package="test.controller" ></context:component-scan>
    <!-- 定义一个视图解析类,基于ResourceView的解析器 ,此解析器是在url解析器上,加入了对jstl的支持-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

TestController.java

package test.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.RequestMethod;
/**
 * @className:TestController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-15
 */
@Controller        //标记这个类为控制器
@RequestMapping("/test")    //类的映射路径
public class TestController {
    @RequestMapping("/start")    //映射到start方法
    public String start(HttpServletRequest request,HttpServletResponse response){
        String nameString=request.getParameter("name");
        System.out.println("name="+nameString);
        return "start";
    }
    //restful风格
    //http://localhost:8080/@mvc/test/start.do?name=zhangsan
    //http://localhost:8080/@mvc/test/start.do?name=lisi
    //http://localhost:8080/@mvc/test/start/zhangsan.do
    //http://localhost:8080/@mvc/test/start/lisi.do
    @RequestMapping("/start2/{name}/{age}")    //name为url模板中取出的路径变量
    public String start2(@PathVariable String name,@PathVariable("age") String age,
            /*如果采用release模式,则需要定义为 @PathVariable("name") String name
             因为release模式不保存变量名*/
                         HttpServletRequest request,HttpServletResponse response){
        System.out.println("name="+name+" age="+age);
        return "start";
    }
    //访问以下链接:
    //http://localhost:8080/@mvc/test/start2/zhangsan/20.do
    //以相同的路径,不同的请求方法访问
    @RequestMapping(value="/start3",method=RequestMethod.POST)    //映射到start方法
    public String start_post(HttpServletRequest request,HttpServletResponse response){
        System.out.println("RequestMethod.POST");
        return "start_post";
    }
    @RequestMapping(value="/start3",method=RequestMethod.GET)
    public String start_get(HttpServletRequest request,HttpServletResponse respose){
        System.out.println("RequestMethod.GET");
        return "start_get";
    }
}

start.jsp

<body>
<h1>This is start JSP page. </h1><br>
<form name="form2" action="test/start3.do" method="get">
    <input type="submit"/>
</form>
<form name="form2" action="test/start3.do" method="post">
    <input type="submit"/>
</form>
</body>

start_get.jsp

<body>
<h1>This is start_get JSP page. </h1><br>
</body>

start_post.jsp

<body>
<h1>This is start_post JSP page. </h1><br>
</body>

运行截图
运行截图
运行截图

@、@Controller
//标记一个类为控制器
@、@RequestMapping 请求映射
@、@RequestParam, @PathVariable, @CookieValue
@、Handler方法的可用参数与返回值

spring MVC 常用ViewResoler & View

要点

1. 当映射的方法返回值为void的时候,则spring mvc框架会生成一个隐含的viewName,根据请求的路径,生成相应的视图名,如果请求的是 xxx.do,则返回的视图为 xxx.jsp ;
2. 当映射的方法返回值的类型为String,则方法返回对应的视图名,在结果页面中同样还可以使用方法中的model;
3. 当返回的是任意类型的对象时,则框架会将该类型的对象也存放到model中,例如:如果函数返回值是User类型的对象,则框架会自动向Model中设置一个属性:model.addAttribute("user",user) ;
4. 如果返回List<User>,则框架会自动向Model中加入:model.addAttribute("userList",userList) ;
5. 如果返回Set<User>,则框架会自动向Model中加入:model.addAttribute("userSet",userSet) ;
6. 如果返回一个map<String,?>对象,则框架也会自动向Model中加入:model.addAllAttributes(map<String,?>) ;
7. 也可以直接返回model;而视图名则按默认的策略解析,如果xxx.do解析成xxx.jsp ;
8. 更完整的方式是直接返回ModelAndView。  

示例1 (TestController.java)

package test.controller;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.support.WebRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import test.entity.User;
/**
 * @className:TestController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-15
 */
@Controller        //标记这个类为控制器
@RequestMapping("/test")    //类的映射路径
public class TestController<AnyType> {
    @RequestMapping("/start")    //映射到start方法
    public String start(HttpServletRequest request,HttpServletResponse response){
        String nameString=request.getParameter("name");
        System.out.println("name="+nameString);
        return "start";
    }
    //restful风格
    //http://localhost:8080/@mvc/test/start.do?name=zhangsan
    //http://localhost:8080/@mvc/test/start.do?name=lisi
    //http://localhost:8080/@mvc/test/start/zhangsan.do
    //http://localhost:8080/@mvc/test/start/lisi.do
    @RequestMapping("/start2/{name}/{age}")    //name为url模板中取出的路径变量
    public String start2(@PathVariable String name,@PathVariable("age") String age,
            /*如果采用release模式,则需要定义为 @PathVariable("name") String name
             因为release模式不保存变量名*/
                         HttpServletRequest request,HttpServletResponse response){
        System.out.println("name="+name+" age="+age);
        return "start";
    }
    //访问以下链接:
    //http://localhost:8080/@mvc/test/start2/zhangsan/20.do
    //以相同的路径,不同的请求方法访问
    @RequestMapping(value="/start3",method=RequestMethod.POST)    //映射到start方法
    public String start_post(HttpServletRequest request,HttpServletResponse response){
        System.out.println("RequestMethod.POST");
        return "start_post";
    }
    @RequestMapping(value="/start3",method=RequestMethod.GET)
    public String start_get(HttpServletRequest request,HttpServletResponse respose){
        System.out.println("RequestMethod.GET");
        return "start_get";
    }
    @RequestMapping(value="/{test}",method=RequestMethod.GET)
    public void testPathVariable(@PathVariable("test") Date test){
    }
    @InitBinder
    public void initBinder(WebRequestDataBinder binder){
        binder.registerCustomEditor(Date.class,new CustomDateEditor(
                new SimpleDateFormat("yyyyMMdd"),false));
    }
    //session前提条件,当前请求session可用,request.getSession(),session.setAttribute();
    public void testAllArguments(HttpServletRequest request,HttpServletResponse response,
                                 HttpSession session,@PathVariable AnyType xxx,@PathVariable AnyType id,
                                 @CookieValue("user-Agent") AnyType cookieName){
    }
    @RequestMapping
    public String testAllArguments(PrintWriter out,Map model){
        //out = response.getWrite();
        //out.print();
        new ModelAndView();
        //out.print("-----------");
        return "viewName";
    }
    @RequestMapping
    public String testCommand(User user,BindingResult result){
        return "xxx";
    }
    @RequestMapping("/xxx")
    public void testVoid(){
        System.out.print("xxx");
        //会生成一个隐含的viewName -- 按请求路径,如果请求是xxx.do 则返回的视图为 xxx.jsp
        //${appName }/test/xxx.do --> test/xxx --> /WEB-INF/page/test/xxx.jsp
    }
    public User testuser(){ //model("user",user)
        return null;
    }
    //除了可以单独返回一个User对象,我们也可以返回一个List对象
    public List<User> testuser2(){
        //model("userList",user) request.getAttribute("userList");
        //即默认生成的key值为 userList
        return null;
    }
}

User.java

package test.entity;
/**
 * @className:User.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-15下午11:04:10
 */
public class User {
    private String name;
    private String password;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

@、 InternalResourceViewResolver、 UrlBasedViewResolver
@、Redirect 重定向视图 (redirect:)

示例2 (UserController.java)

package test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import test.entity.User;
/**
 * @className:UserController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-16上午12:59:17
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping(method=RequestMethod.GET)
    public String addForm(){
        return "add_user";
    }
    @RequestMapping(method=RequestMethod.POST)
    public String addUser(User user){
        //返回一个重定向视图
        return "redirect:/user_list";
    }
    //避免重复提交
    //request.forward(); a -server -> b
    //response.redirect a --> server --> client --> b
}

@、XmlViewResovler
@、视图链
@、JstlView, ExcelView及自定义view (JsperReport, Pdf, Excel)

拦截器、视图国际化、验证

@、Interceptor
示例3

MyInteceptor.java

package test.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
 * @className:MyInteceptor.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-16上午01:30:20
 */
public class MyInteceptor implements HandlerInterceptor {
    //释放资源
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object arg2, Exception arg3)
            throws Exception {
    }
    //控制器执行完,生成视图之前可以做的动作,向模型中添加公共成员
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {
    }
    //拦截之前执行的方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        return false;
    }
}

servlet.xml

…………
<!-- 设置拦截器链 ,当配置了多个拦截器bean时,则是顺序的往下执行-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/*"/>
        <bean class="test.web.MyInteceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>
…………

@、resourceMessage

国际化
新建几个properties文件,编辑内容如下:

mess.properties
welcome=welcome
mess_zh_CN.properties
welcome=\欢\迎
mess_en_US.properties
welcome=(US)welcome
@、JSR-303 validate bean

框架验证
编辑UserController.java

package test.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import test.entity.User;
/**
 * @className:UserController.java
 * @classDescription:
 * @author:wei.luo
 * @createTime:2012-2-16上午12:59:17
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping(method=RequestMethod.GET)
    public String addForm(){
        return "add_user";
    }
    @RequestMapping(method=RequestMethod.POST)
    public String addUser(User user){
        //返回一个重定向视图
        return "redirect:/user_list";
    }
    //避免重复提交
    //request.forward(); a -server -> b
    //response.redirect a --> server --> client --> b
    //spring mvc的bean验证,对user对象加入验证,并绑定到一个结果集上
    @RequestMapping(method=RequestMethod.POST)
    public String addUser2(@Valid User user,BindingResult result){
        if(result.hasErrors()){    //如果验证发生错误
            return "formView";
        }
        //返回一个重定向视图
        return "redirect:/user_list";
    }
    //使用这个验证,要加入以下几个包:
    //validation-api-1.0.0.GA.jar
    //hibernate-validator-4.0.2.GA.jar
    //slf4j-api-1.5.6.jar
    //slf4j-log4j12-1.5.6.jar
}

参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc

版权所有,转载请注明出处 luowei.github.io.