你的位置:首页 > Java教程

[Java教程]SpringMvc入门三


 

在传统的Spring MVC开发方法中,必须在Bean配置文件中为每个控制器类配置实例和请求映射和让每个控制器类去实现或者扩展特定于框架的接口或者基类,不够灵活。

如果Spring MVC可以自动侦测你的控制器类和请求映射,就能减少配置所需要的工作量。

Spring2.5支持一种基于注解的控制器开发方法。

Spring可以通过@Controller注解自动发现你的控制器类以及@RequestMapping注解中的请求映射,这样就为你免去了在Bean配置文件中配置它们的麻烦。此外,如果使用注解,控制器类和处理程序方法在访问上下文资源(例如请求参数、模型属性和会话属性)时也会更加灵活。

常用到的注解

   

1、@Controller 

2、@RequestMapping

3、@RequestParam,  @PathVariable,  @CookieValue

4、ModelAndView

   

@Controller注解能将任意的类标注成控制器类。与传统的控制器相反,被标注的控制器类不需要实现特定于框架的接口,也不必扩展特定于框架的基类。

在控制器类内部,可能有一个或者多个处理程序方法添加了@RequestMapping注解。

   

处理程序方法的签名非常灵活。你可以为处理程序方法指定任意的名称,并定义以下任意一种类型作为它的方法参数。在这里,只提到了常见的参数类型。关于有效参数类型的完整列表,请参阅有关配置基于注解的控制器的Spring文档。

 

常见的参数类型

 

1.HttpServletRequest、HttpServletResponse或HttpSession。

2.添加了@RequestParam注解的任意类型的请求参数

3.添加了@ModelAttribute注解的任意类型的模型属性

4.任意类型的命令对象,供Spring绑定请求参数

5.Map或者ModelMap,供处理程序方法向模型添加属性

6.Errors或者BindingResult,让处理程序方法访问命令对象的绑定和验证结果

7.SessionStatus,让处理程序方法发出会话处理已经完成的通知

   

常见的返回值类型

处理程序方法的返回类型可以是ModelAndView、Model、Map、String、void

   

在创建基于注解的控制器之前,必须构建web应用程序上下文来处理注解。

首先,为了让Spring用@Controller注解自动侦测控制器,必须通过<context:component-scan>元素启用Spring的组件扫描特性。

其次Spring MVC还能够根据@RequestMapping将请求映射到控制器类和处理程序方法。

为了使其生效,必须在web应用程序上下文中注册DefaultAnnotationHandlerMapping实例和AnnotationMethodHandlerAdapter实例。

它们分别处理在类级别和方法级别上的@RequestMapping注解。

 

ModelAndView

 

这个构造方法构造出来的ModelAndView 不能直接使用,应为它没有指定view,也没有绑定对应的model对象。当然,model对象不是必须的,但是view确实必须的。

用这个构造方法构造的实例主要用来在以后往其中加view设置和model对象。

 

给ModelAndView实例设置view的方法有两个:setViewName(String viewName) 和 setView(View view)。前者是使用viewName,后者是使用预先构造好的View对象。其中前者比较常用。事实上View是一个接口,而不是一个可以构造的具体类,我们只能通过其他途径来获取View的实例。对于viewname,它既可以是jsp的名字,也可以是tiles定义的名字,取决于使用的ViewNameResolver如何理解这个view name。如何获取View的实例以后再研究。

 

而对应如何给ModelAndView实例设置model则比较复杂。有三个方法可以使用:

 

addObject(Object modelObject)

 

addObject(String modelName, Object modelObject)

 

addAllObjects(Map modelMap)

 

ModelAndView可以接收Object类型的对象,ModelAndView将它视为其众多model中的一个。当使用Object类型的对象的时候,必须指定一个名字。ModelAndView也可以接收没有明显名字的对象,原因在于ModelAndView将调用spring自己定义的Conventions 类的.getVariableName()方法来为这个model生成一个名字。显然,对model而言,名字是必须的。

 

Conventions.getVariableName()生成名字的规则是使用对象的类名的小写模式来作model名字。当这个model是集合或数组的时候,使用集合的第一个元素的类名加s来作model的名字。

ModelAndView也可以接收Map类型的对象,ModelAndView将这个Map中的元素视为model,而不是把这个Map本身视为model。但是其他的集合类可以用本身作为model对象。实际上,ModelAndView对model的支持来自于类ModelMap,这个类继承自HashMap。

DEMO结构图:

Web.

<?

<web-app

    

    xsi:schemaLocation="http://java.sun.com/

    id="WebApp_ID" version="2.5">

    <display-name>SpringMvc02</display-name>

    <welcome-file-list>

        <welcome-file>index.jsp</welcome-file>

    </welcome-file-list>

    <servlet>

        <servlet-name>springmvc</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>classpath:spring-mvc.</param-value>

        </init-param>

    </servlet>

    <servlet-mapping>

        <servlet-name>springmvc</servlet-name>

        <url-pattern>*.do</url-pattern>

    </servlet-mapping>

</web-app>

 

spring-mvc.

<?

<beans

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 使用注解的包,包括子集 -->

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

<!-- 视图解析器 -->

    <bean id="viewResolver"

        >

<!—前缀 -->

        <property name="prefix" value="/WEB-INF/jsp/" />

<!—后缀 -->

        <property name="suffix" value=".jsp"></property>

    </bean>

</beans>

Model类Student.java:

public class Student {

    private int id;

    private String name;

    private int age;

    public Student() {

        super();

    }

    public Student(int id, String name, int age) {

        super();

        this.id = id;

        this.name = name;

        this.age = age;

    }

<!-- 下面的get,set方法省略 -->

}

StudentController:

@Controller

@RequestMapping("/student")

public class StudentController {

 

    private static List<Student> studentList=new ArrayList<Student>();    

    //只添加一次,用static

    static{

        studentList.add(new Student(1,"张三",11));

        studentList.add(new Student(2,"李四",12));

        studentList.add(new Student(3,"王五",13));

    }

    @RequestMapping("/list")

    public ModelAndView list(){

        ModelAndView mav=new ModelAndView();

        mav.addObject("studentList", studentList);//这里调用的是model的方法,将studentList对象传递到视图上

        mav.setViewName("student/list");//这里视图name对应student/list.jsp,调用student/list.do则页面会返回到student/list.jsp

        return mav;

    }

    

    @RequestMapping("/preSave")

    public ModelAndView preSave(@RequestParam(value="id",required=false) String id){//参数id,这里的id就相当于servlet中的request.getPaXXx("id"),required=false,表示不是必须参数,可以没有参数,默认为true,另一个常见的参数是DefaultValue.

        ModelAndView mav=new ModelAndView();

        if(id!=null){

            mav.addObject("student", studentList.get(Integer.parseInt(id)-1));

            mav.setViewName("student/update");

        }else{

            mav.setViewName("student/add");            

        }

        return mav;

    }

}

 

Jsp页面:

add.jsp

<body>

<form action="${pageContext.request.contextPath}/student/save.do" method="post">

<table>

    <tr>

        <th colspan="2">学生添加</th>

    </tr>

    <tr>

        <td>姓名</td>

        <td><input type="text" name="name"/></td>

    </tr>

    <tr>

        <td>年龄</td>

        <td><input type="text" name="age"/></td>

    </tr>

    <tr>

        <td colspan="2">

            <input type="submit" value="提交"/>

        </td>

    </tr>

</table>

</form>

</body>

list.jsp

页面前引用:<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<body>

<a href="${pageContext.request.contextPath}/student/preSave.do">添加学生</a>

<table>

    <tr>

        <th>编号</th>

        <th>姓名</th>

        <th>年龄</th>

        <th>操作</th>    

    </tr>

    <c:forEach var="student" items="${studentList }">

    <tr>

        <td>${student.id }</td>

        <td>${student.name }</td>

        <td>${student.age }</td>

        <td><a href="${pageContext.request.contextPath}/student/preSave.do?id=${student.id}">修改</a></td>

    </tr>

    </c:forEach>

</table>

</body>

update.jsp

<body>

<form action="${pageContext.request.contextPath}/student/save.do" method="post">

<table>

    <tr>

        <th colspan="2">学生修改</th>

    </tr>

    <tr>

        <td>姓名</td>

        <td><input type="text" name="name" value="${student.name }"/></td>

    </tr>

    <tr>

        <td>年龄</td>

        <td><input type="text" name="age" value="${student.age }"/></td>

    </tr>

    <tr>

        <td colspan="2">

            <input type="hidden" name="id" value="${student.id }"/>

            <input type="submit" value="提交"/>

        </td>

    </tr>

</table>

</form>

</body>

 

Index.jsp转向页面

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"

pageEncoding="ISO-8859-1"%>

<% response.sendRedirect("student/list.do"); %>

 

测试:http://localhost:8080/SpringMvc02/

DEMO还有一个save功能没有写,因为这里的数据都只是自己定义的,无法完成数据的保存。