Spring MVC对restful的支持

本文介绍SpringMVC框架中RESTful的支持方式,包括关键注解如@Controller、@RequestMapping等的使用方法,并展示了如何利用RestTemplate进行RESTful服务间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring MV SpringMVC对restful的支持

1.   C中的常用注解

(1)@Controller

    对将成为 MVC 中控制器的类进行注解并处理HTTP 请求。

(2)@RequestMapping

    对函数进行注解,该函数处理某些 HTTP 方法、URI 或 HTTP 头。

此注解是 Spring REST 支持的关键。可以更改 method 参数以处理其他 HTTP 方法。

    例如:

    @RequestMapping(method=RequestMethod.GET,value="/emps",

       headers="Accept=application/xml,application/json")

(3)@PathVariable

   可将 URI 中的路径变量作为参数插入。

@RequestMapping("/owners/{ownerId}",method=RequestMethod.GET)

public String findOwner(@PathVariableString ownerId, Model model) {

       // ...

}

(4)@RequestParam

   这个注解跟@PathVariable功能差不多,只是参数值的来源不一样而已。它的取值来源是请求参数(querystring或者post表单字段)

对了,因为它的来源可以是POST字段,所以它支持更丰富和复杂的类型信息。比如文件对象:

 

@RequestMapping("/imageUpload")

public String processImageUpload(

@RequestParam("name") String name,

    @RequestParam("description")String description,

    @RequestParam("image")MultipartFile image) throws IOException {

   this.imageDatabase.storeImage(name, image.getInputStream(),

(int) image.getSize(), description);

   return "redirect:imageList";

}

 

(5)@RequestHeader

   将某一 HTTP 头插入方法中

(6)@RequestBody

   将 HTTP 请求正文插入方法中

(7)@ResponseBody

   将内容或对象作为 HTTP响应正文返回。

(8)HttpEntity<T>

   如果将它作为参数提供,自动插入方法中

(9)ResponseEntity<T>

   返回具有自定义状态或头的HTTP 响应

   例如:

  public @ResponseBody EmployeegetEmployeeBy(

       @RequestParam("name")Stringname,

       @RequestHeader("Accept")String accept,

       @RequestBody String body) {…}

 

public ResponseEntity<String> method(HttpEntity<String> entity) {…}

1.1  @RequestBody和@ResponseBody

这两个注解其实用到了Spring的一个非常灵活的设计——HttpMessageConverter 18.3.2 HTTPMessage Conversion

与@RequestParam不同,@RequestBody和@ResponseBody是针对整个HTTP请求或者返回消息的。前者只是针对HTTP请求消息中的一个 name=value 键值对(名称很贴切)。

        HtppMessageConverter负责将HTTP请求消息(HTTPrequest message)转化为对象,或者将对象转化为HTTP响应体(HTTP response body)。

public interface HttpMessageConverter<T> {

 

    // Indicatewhether the given class is supported by this converter.

    booleansupports(Class<? extends T> clazz);

 

    // Return thelist of MediaType objects supported by this converter.

   List<MediaType> getSupportedMediaTypes();

 

    // Read anobject of the given type form the given input message, and returns it.

    Tread(Class<T> clazz, HttpInputMessage inputMessage) throws IOException,

                                                                   HttpMessageNotReadableException;

 

    // Write angiven object to the given output message.

    void write(T t,HttpOutputMessage outputMessage) throws IOException,

                                                           HttpMessageNotWritableException;

 

}

 

Spring MVC对HttpMessageConverter有多种默认实现,基本上不需要自己再自定义HttpMessageConverter

·        StringHttpMessageConverter -converts strings

·        FormHttpMessageConverter - convertsform data to/from a MultiValueMap<String, String>

·        ByteArrayMessageConverter - convertsbyte arrays

·        SourceHttpMessageConverter - convertto/from a javax.xml.transform.Source

·        RssChannelHttpMessageConverter -convert to/from RSS feeds

·        MappingJacksonHttpMessageConverter -convert to/from JSON using Jackson's ObjectMapper

·        etc...

 

然而对于RESTful应用,用的最多的当然是MappingJacksonHttpMessageConverter。

 

但是MappingJacksonHttpMessageConverter不是默认的HttpMessageConverter:

可以配置如下:

<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">

    <propertyname="messageConverters">

    <list>

        <beanclass="org.springframework.http.converter.StringHttpMessageConverter">

        <propertyname="supportedMediaTypes">

            <list>

           <value>text/plain;charset=GBK</value>

            </list>

        </property>

        </bean>

        <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>

    </list>

    </property>

</bean>

       配置好了之后,就可以享受@Requestbody和@ResponseBody对JONS转换的便利之处了:

@RequestMapping(value = "api", method = RequestMethod.POST)
@ResponseBody
public boolean addApi(@RequestBody
    Api api, @RequestParam(value = "afterApiId", required = false)
    Integer afterApiId) {
        Integer id = apiMetadataService.addApi(api);
        return id > 0;
}
 
@RequestMapping(value = "api/{apiId}", method = RequestMethod.GET)
@ResponseBody
public Api getApi(@PathVariable("apiId")
    int apiId) {
        return apiMetadataService.getApi(apiId, Version.primary);
}

 

 

2.   使用Spring中RestTemplate 对restful服务进行通信测试

RestTemplate支持其他方法,包括:

       exchange:使用请求正文执行一些HTTP 方法并获得响应。

       getForObject:执行 HTTP GET 方法并将响应作为对象获得。

       postForObject:使用特定请求正文执行HTTP POST 方法。

       put:使用特定请求正文执行HTTP PUT 方法。

       delete:执行 HTTPDELETE方法以获得特定 URI。

代码示例

 

(1)显示如何将头添加到请求中,然后调用请求。

       使用MarshallingHttpMessageConverter 您可以获得响应并将其转换为类型类。

 

清单1. XML 具象请求   

HttpHeadersheaders = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_XML);

HttpEntity<String>entity = new HttpEntity<String>(headers);

ResponseEntity<EmployeeList>response = restTemplate.exchange(

       "http://localhost:8080/rest/service/emps",HttpMethod.GET, entity, EmployeeList.class);

EmployeeListingemployees= response.getBody();

// handle theemployees

           

(2)POST请求

显示了如何将新员工发布到服务器。服务器端服务 addEmp() 可接受媒体类型为 application/xml 和 application/json 的数据。

 

清单 2. 发布新员工                     

Employee newEmp= new Employee(99, "guest", "guest@ibm.com");

HttpEntity<Employee>entity = new HttpEntity<Employee>(newEmp);

ResponseEntity<Employee>response = restTemplate.postForEntity(

       "http://localhost:8080/rest/service/emp",entity, Employee.class);

Employee e =response.getBody();

// handle theemployee

            

(3)PUT请求

       显示了如何 PUT 修改的员工以更新旧员工。它还显示了可用作请求 URI 占位符({id})的功能

 

清单3.PUT 以更新员工              

Employee newEmp= new Employee(99, "guest99", "guest99@ibm.com");

HttpEntity<Employee>entity = new HttpEntity<Employee>(newEmp);

restTemplate.put("http://localhost:8080/rest/service/emp/{id}",entity, "99");

 

(4)DELETE请求

       显示了如何 DELETE 现有员工。

 

清单4.DELETE 现有员工                    

restTemplate.delete("http://localhost:8080/rest/service/emp/{id}","99");

 

3.   支持RESTful的URL

在开发功能模块之前,应该先把URL设计好。比查对 消息 这个资源的操作URL可以这么设计:

http://arganzheng.me/messages/show/123456
http://arganzheng.me/messages/preview/123456
http://arganzheng.me/messages/delete/123456
http://arganzheng.me/messages/new
http://arganzheng.me/message/update

说明:可以看到我们的URL中有动作在里面,这个相对简单点。

事实上纯粹的RESTfulURL是把动作隐含在HTTP头中:GET、PUT、DELETE、POST。

/blog/1 HTTP GET =>  得到id = 1的blog
/blog/1 HTTP DELETE => 删除 id = 1的blog
/blog/1 HTTP PUT =>  更新id = 1的blog
/blog   HTTP POST =>  新增BLOG

不过这样对用户编码有要求,。

要支持这种URL,web.xml需要这么配置:

<!-- REST servlet-mapping -->
<servlet-mapping>
    <servlet-name>DispatcherServlet<srvlet-name>
    <url-pattern>/</url-pattern>
<srvlet-mapping>

但是这样的话有个问题,就是静态文件也被mapping了,会导致找不到资源。Spring提供了一个resources配置项支持静态文件的处理16.14.5Configuring Serving of Resources

<!-- Forwards requests to the "/" resource to the "welcome" view -->
<mvc:view-controller path="/" view-name="index"/>
 
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- 注意:配置了mvc:resources就必须配置这个选项,否则handler mapping都失效了
    @see  http://stackoverflow.com/questions/7910845/the-handler-mapping-from-the-mvcresource-override-other-mappings-which-defined 
-->
<mvc:annotation-driven />

这样所有请求:http://arganzheng.me/resources/**会映射到webapp下的resources目录,而不是找我们的controller处理。

但是有个奇怪的问题,就是配置这个之后,原来动态东西就不能访问到了,提示找不到对应的handler,解决方案是增加一个<mvc:annotation-driven />配置。具体参见Thehandler mapping from the mvc:resource override other mappings which definedwith annotation

另外,静态的html页面一般不放在resources路面下,而是直接在根目录下,比如:http://arganzheng.me/index.html或者http://arganzheng.me/404.html。所以应该在web.xml中在配置一个url-mapping规则:

<!-- 避免被Spring DispatcherServlet接管 -->
<servlet-mapping>
    <servlet-name>default<srvlet-name>
    <url-pattern>*.html</url-pattern>
<srvlet-mapping>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值