Spring MVC

1 介绍

1.1 MVC框架是什么

模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计模式。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中解耦。通常,模型负责封装应用程序数据在视图层展示。视图仅仅只是展示这些数据,不包含任何业务逻辑。控制器负责接收来自用户的请求,并调用后台服务(manager或者dao)来处理业务逻辑。处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。

在Spring MVC应用程序中,模型通常由POJO对象组成,它在业务层中被处理,在持久层中被持久化。视图通常是用JSP标准标签库(JSTL)编写的JSP模板。控制器部分是由dispatcher servlet负责,在本教程中我们将会了解更多它的相关细节。
一些开发人员认为业务层和DAO层类是MVC模型组件的一部分。我对此持有不同的意见。我不认为业务层及DAO层类为MVC框架的一部分。通常一个web应用是3层架构,即数据-业务-表示。MVC实际上是表示层的一部分。


Dispatcher Servlet(Spring控制器)

在最简单的Spring MVC应用程序中,控制器是唯一的你需要在Java web部署描述文件(即web.xml文件)中配置的Servlet。Spring MVC控制器 ——通常称作Dispatcher Servlet,实现了前端控制器设计模式。并且每个web请求必须通过它以便它能够管理整个请求的生命周期。

当一个web请求发送到Spring MVC应用程序,dispatcher servlet首先接收请求。然后它组织那些在Spring web应用程序上下文配置的(例如实际请求处理控制器和视图解析器)或者使用注解配置的组件,所有的这些都需要处理该请求。


在Spring3.0中定义一个控制器类,这个类必须标有@Controller注解。当有@Controller注解的控制器收到一个请求时,它会寻找一个合适的handler方法去处理这个请求。这就需要控制器通过一个或多个handler映射去把每个请求映射到handler方法。为了这样做,一个控制器类的方法需要被@RequestMapping注解装饰,使它们成为handler方法。

handler方法处理完请求后,它把控制权委托给视图名与handler方法返回值相同的视图。为了提供一个灵活的方法,一个handler方法的返回值并不代表一个视图的实现而是一个逻辑视图,即没有任何文件扩展名。你可以将这些逻辑视图映射到正确的实现,并将这些实现写入到上下文文件,这样你就可以轻松的更改视图层代码甚至不用修改请求handler类的代码。
为一个逻辑名称匹配正确的文件是视图解析器的责任。一旦控制器类已将一个视图名称解析到一个视图实现。它会根据视图实现的设计来渲染对应对象。

1.2 SpringMVC和Spring有什么关系?

  1. 首先,对于一个web应用,其部署在web容器中, web容器提供其一个全局的上下文环境,这个上下文就是ServletContext ,其为后面的spring IoC容器提供宿主环境;

  2. 其次, 在web.xml中会提供有contextLoaderListener 。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用, 在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。 这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;

  3. 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。 DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean 。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。 这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean 。

1.3 dispatcherServlet创建的ApplicationContext和Spring容器的ApplicationContext有关系吗?

ContextLoaderListener中创建ApplicationContext主要用于整个Web应用程序需要共享的一些组件 ,比如DAO,数据库的ConnectionFactory等。而 由DispatcherServlet创建的ApplicationContext主要用于和该Servlet相关的一些组件 ,比如Controller、ViewResovler等。

对于作用范围而言, 在DispatcherServlet中可以引用由ContextLoaderListener所创建的ApplicationContext ,而反过来不行。

在Spring的具体实现上,这两个ApplicationContext都是通过ServletContext的setAttribute方法放到ServletContext中的。但是, ContextLoaderListener会先于DispatcherServlet创建ApplicationContext,DispatcherServlet在创建ApplicationContext时会先找到由ContextLoaderListener所创建的ApplicationContext,再将后者的ApplicationContext作为参数传给DispatcherServlet的ApplicationContext的setParent()方法 ,在Spring源代码中,你可以在FrameServlet.java中找到如下代码:

wac.setParent(parent);

其中, wac即为由DisptcherServlet创建的ApplicationContext,而parent则为有ContextLoaderListener创建的ApplicationContext 。此后,框架又会调用ServletContext的setAttribute()方法将wac加入到ServletContext中。

当Spring在执行ApplicationContext的getBean时, 如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找 。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。

 

2 项目依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>SpringmvcREST</groupId>
	<artifactId>Springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>Springmvc</name>
	<description />
	 <properties>
        <springframework.version>4.2.0.RELEASE</springframework.version>
     
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
             
    </dependencies>
	<build>
		<finalName>Springmvc</finalName>
	</build>
</project>

 

 

3 配置文件

3.1 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>SpringMVC_HelloWorld</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- spring mvc 的servlet -->
  <!-- DispatcherServlet在初始化后会直接在/WEB-INF/下找springmvc-servlet.xml文件,
               servlet-name标签的参数定义要和XML文件对应 -->
  <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
  </servlet-mapping>
  
  <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

 

3.2 springmvc-servlet.xml

这个文件的名字是由web.xml里面配置的DispatcherServlet的<servlet-name></servlet-name>决定的,路径在上下文/WEB-INF/里面,主要是配置控制器返回的逻辑视图名和物理视图的对应关系

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                     http://www.springframework.org/schema/beans/spring-beans.xsd 
                     http://www.springframework.org/schema/tx 
                     http://www.springframework.org/schema/tx/spring-tx.xsd 
                     http://www.springframework.org/schema/aop 
                     http://www.springframework.org/schema/aop/spring-aop.xsd
                     http://www.springframework.org/schema/context 
                       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 自动扫描的包 -->
    <context:component-scan base-package="com.lin.helloworld.controller" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <!-- controller 返回的一个逻辑视图名经过前后缀的处理返回物理视图 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

 

4 编写一个domain类

用来封装一些提交数据

package com.lin.helloworld.domain;

public class HelloWorld {
    
    private String data;

    public HelloWorld() {
        super();
    }

    public HelloWorld(String data) {
        super();
        this.data = data;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "HelloWorld [data=" + data + "]";
    }

}

 

5 编写controller

这个是MVC中的控制器,和struts2不一样的是他是方法级的拦截,struts2是类级的拦截.

package com.lin.helloworld.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.lin.helloworld.domain.HelloWorld;

@Controller
public class HelloWorldController {

    //这里的/hello相当于struts2里的一个action
    //返回一个字符串给视图
    @RequestMapping("/hello")
    public ModelAndView sayHello()
    {
        //modelAndView的构造方法的第一个参数相当于Struts2里的一个result的name
        ModelAndView modelAndView = new ModelAndView("helloworld", "msg", "HelloWorld!!!");
        return modelAndView;
    }
    
    //返回一个对象给视图
    //@ModelAttribute("obj")的作用相当于Struts2的action类里面的一个field,
    //用于表单提交的数据放进一个对象里面
    //这里和struts2的区别:
    //struts2处理表单提交的方式是:<input name="obj.data"/> 提交的数据封装在obj对象的data里面
    //springmvc的方式是:<input name="data"/> 提交的数据封装在obj对象的data里面,
    //前提是要使用@ModelAttribute注解
    @RequestMapping("/helloObj")
    public ModelAndView sayHelloWorld(@ModelAttribute("obj") HelloWorld obj)
    {
        System.out.println(obj.toString());
        ModelAndView modelAndView = new ModelAndView("helloworld", "obj", obj);
        return modelAndView;
    }

}

 

6 视图

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'helloworld.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    HelloWorld! This is a spring mvc framework example.<br>
    ${msg}
    <hr/>
    <form action="helloObj" method="post">
        <!-- 这里的表单提交和struts2不同的是name="data"会自动对应上对象的filed -->
        <input type="text" name="data" size="30"/><br/>
        <input type="submit" value="Submit"/>
    </form>
    <hr/>
    ${obj.data}
  </body>
</html>

 

7 目录结构

185213_10au_2328736.png

 

8 自定义一个拦截器

8.1 需求

假设现在用户发出请求时,系统需要判断该用户是否已经登录,如果用户已经登录,则请求继续被处理;如果用户没有登录,则拦截器需要拦截该请求,并且为用户跳转到登录页面。但是会有一个问题,拦截器不应该拦截所有请求,我们只需要她拦截我们要她拦截的请求,比如,如果拦截器拦截登录请求的话,那么用户永远也登陆不了。

 

8.2 用户登录拦截器

package com.lin.helloworld.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoginInterceptor implements HandlerInterceptor {
    
    private String[] allow;//允许不拦截的请求

    public String[] getAllow() {
        return allow;
    }

    public void setAllow(String[] allow) {
        this.allow = allow;
    }

    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("ServletDispatcher 完成处理时执行");
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        
        System.out.println("处理请求后执行");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object object) throws Exception {
        
        String currentRequestURI = request.getRequestURI();
        
        currentRequestURI = currentRequestURI.substring(currentRequestURI.lastIndexOf("/")+1, currentRequestURI.length());

        if(currentRequestURI.equals("login")){//如果当前请求是登录请求,则把用户登录信息放进session

            if(request.getParameter("userName").equals("lin")){//判断用户登录信息是否正确
                HttpSession session = request.getSession();
                session.setAttribute("userName", request.getParameter("userName"));
                
                return true;
            }
            else{
                request.getRequestDispatcher("/login.jsp").forward(request, response);//回到登录页面,并且提示用户登录信息错误
                return false;
            }
        }
        
        if(allow != null && allow.length != 0){//如果当前请求不是登录,则看该请求是否需要被拦截
            for(String allowURI : allow){
                
                if(allowURI.equals(currentRequestURI)){
                    
                    return true;//如果不需要拦截,则让请求通过,继续处理请求
                }
            }
        }
        
        HttpSession session = request.getSession();
        
        if(session.getAttribute("userName") == null){//判断用户是否已经登录,如果没有登录,跳转到登录页面
            
            response.sendRedirect("http://localhost:8080/SpringMVC_HelloWorld/login.jsp");
            return false;
        }
        else {
            return true;
        }
    }
}

 

自定义的拦截器只需要实现 HandlerInterceptor 接口即可。

 

8.3 配置拦截器

 

需要先导入MVC的命名空间。

 

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" 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.xsd 
                     http://www.springframework.org/schema/tx 
                     http://www.springframework.org/schema/tx/spring-tx.xsd 
                     http://www.springframework.org/schema/aop 
                     http://www.springframework.org/schema/aop/spring-aop.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.0.xsd">

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/*"/>
            <!-- 自定义拦截器 -->
            <bean class="com.lin.helloworld.interceptor.LoginInterceptor">
                <!-- 允许哪些请求不需要被拦截 -->
                <property name="allow">
                    <array>
                        <value>login</value>
                    </array>
                </property>
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

</beans>

 

8.4 登录控制器

/**
     * 处理登录请求
     * @param userName 用户登录信息
     * @return
     */
    @RequestMapping("/login")
    public ModelAndView login(@FormParam("userName") String userName)
    {
        return new ModelAndView("helloworld");
    }

 

8.5 登录页面

<body>
    <form action="login" method="post">
        <input type="text" name="userName"><input type="submit" value="login">
    </form>
  </body>

 

8.6 测试

向服务器提交一个请求:http://localhost:8080/SpringMVC_HelloWorld/hello,跳出一个登录页面,登录后再请求,正常处理hello请求。。。

9 SpringMVC开发REST式的WEB服务

9.1 项目依赖

修改pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>SpringmvcREST</groupId>
	<artifactId>SpringmvcREST</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>SpringmvcREST</name>
	<description />
	 <properties>
        <springframework.version>4.2.0.RELEASE</springframework.version>
        <jackson.version>2.5.3</jackson.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>
 
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
             
    </dependencies>
	<build>
		<finalName>SpringmvcREST</finalName>
	</build>
</project>

9.2 怎么让SpringMVC既能展示JSP又能展示JSON

修改mvc配置文件,springmvc-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: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.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 自动扫描的包 -->
	<context:component-scan base-package="com.lin.rest.controller" />
        <context:component-scan base-package="com.lin.helloworld.controller" />


	<mvc:annotation-driven />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	<!-- Configure to plugin JSON as request and response in method handler -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
			<list>
				<ref bean="jsonMessageConverter"/>
			</list>
		</property>
	</bean>
	
	<!-- Configure bean to convert JSON to POJO and vice versa -->
	<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
	</bean>	

</beans>

9.3 model类

package com.lin.rest.domain;

public class User {
	
	private int id;
	private String email;
	private String password;
	
	public User() {
	}

	public User(int id, String email, String password) {
		this.id = id;
		this.email = email;
		this.password = password;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", email=" + email + ", password=" + password
				+ "]";
	}

}

9.4 资源类

package com.lin.rest.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.lin.rest.domain.User;

@RestController
public class MyResource {
	
	//------------------------------------get all users-------------------------------------
	@RequestMapping(value="/user/all",method=RequestMethod.GET)
	public List<User> getAllUser()
	{
		List<User> users = new ArrayList<User>();
		for(int i=0;i<10;i++)
		{
			User user = new User();
			user.setId(i);
			user.setEmail("xx"+i+"@163.com");
			user.setPassword("password"+i);
			
			users.add(user);
		}
		return users;
	}
	
	//---------------------------------------get user by id-----------------------------------
	@RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<User> getUserById(@PathVariable int id)
	{
		User user = new User();
		user.setId(id);
		user.setEmail("xx"+id+"@163.com");
		user.setPassword("password");
		
		return new ResponseEntity<User>(user, HttpStatus.OK);
	}
	
	//---------------------------------get user by query parameters
	@RequestMapping(value = "/user/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<User> getUserByQueryParam(@RequestParam("email") String email,@RequestParam("password") String password)
	{
		User user  = new User();
		user.setId(1);
		user.setEmail(email);
		user.setPassword(password);
		
		return new ResponseEntity<User>(user,HttpStatus.OK);
	}
	
	//------------------------------------create a user------------------------------------------
	@RequestMapping(value = "/user/", method = RequestMethod.POST)
	public ResponseEntity<Void> createUser(@RequestBody User user,UriComponentsBuilder ucBuilder)
	{
		System.out.println("add a user:"+user.toString());
		HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
	}
	
	//--------------------------------update user by id------------------------------------
	@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
	public ResponseEntity<User> updateUser(@PathVariable int id,@RequestBody User user)
	{
		if(user == null)
		{
			return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
		}
		System.out.println("update user by id:"+id);
		System.out.println("update as new user:"+user.toString());
		
		return new ResponseEntity<User>(user, HttpStatus.OK);
	}
	
	//----------------------------------delete user by id--------------------------------------
	@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
	public ResponseEntity<Void> deleteUserById(@PathVariable int id)
	{
		System.out.println("delete user by id:"+id);
		return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
	}
	
	//---------------------------------------delete all users------------------------------------------
	@RequestMapping(value = "/user/", method = RequestMethod.DELETE)
	public ResponseEntity<Void> deleteAllUsers()
	{
		System.out.println("Deleting All Users");
        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
	}

}

9.5 测试REST WebService接口

在各种浏览器有一些REST插件可以测试,比如FireFox的RESTClient等等,,,测试就省略喇,,,,

9.6 REST客户端

Spring提供RestTemplate能够很方便的访问REST资源

package com.lin.rest.client;

import java.util.LinkedHashMap;
import java.util.List;

import org.junit.Test;
import org.springframework.web.client.RestTemplate;

import com.lin.rest.domain.User;

public class RESTCilent {
	
	private static final String BASE_URI = "http://localhost:8080//SpringmvcREST/user/";
	
	/**
	 * get all users
	 */
	@Test
	@SuppressWarnings("unchecked")
	public void getAllUser()
	{
		RestTemplate restTemplate = new RestTemplate();
		List<LinkedHashMap<String, Object>> userMapping = restTemplate.getForObject(BASE_URI+"all", List.class);
		
		for(LinkedHashMap<String, Object> user : userMapping)
		{
			System.out.println(user.get("id"));
			System.out.println(user.get("email"));
			System.out.println(user.get("password"));
		}
	}
	
	/**
	 * get user by id
	 */
	@Test
	public void getUserById()
	{
		RestTemplate restTemplate = new RestTemplate();
		User user = restTemplate.getForObject(BASE_URI+"1", User.class);
		System.out.println(user.toString());
	}
	
	/**
	 * get user by query parameters
	 */
	@Test
	public void getUserByParameters()
	{
		RestTemplate restTemplate = new RestTemplate();
//		Map<String,Object> parameters = new HashMap<String, Object>();
//		parameters.put("email", "XXX@163,com");
//		parameters.put("password", "password");
		User user = restTemplate.getForObject(BASE_URI+"?email=XXX@163.com&password=password", User.class);
		
		System.out.println(user.toString());
	}
	
	/**
	 * create a user
	 */
	@Test
	public void createUser()
	{
		RestTemplate restTemplate = new RestTemplate();
		User user = new User();
		user.setId(1);
		user.setEmail("xx1@163.com");
		user.setPassword("password");
		
		restTemplate.postForEntity(BASE_URI, user, User.class);
	}
	
	/**
	 * update user by id
	 */
	@Test
	public void updateUser()
	{
		RestTemplate restTemplate = new RestTemplate();
		User user = new User();
		user.setId(1);
		user.setEmail("xx1@163.com");
		user.setPassword("password");
		restTemplate.put(BASE_URI+"1", user);
	}
	
	/**
	 * delete user by id
	 */
	@Test
	public void deleteUserById()
	{
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.delete(BASE_URI+"1");
	}
	
	/**
	 * delete all users 
	 */
	@Test
	public void deleteAllUsers()
	{
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.delete(BASE_URI);
	}

}

9.7 单元测试

转载于:https://my.oschina.net/ChiLin/blog/693486

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值