spring mvc本身对restful支持非常好。它的@requestmapping、@requestparam、@pathvariable、@responsebody注解很好的支持了rest。18.2 creating restful services
1. @requestmapping
spring uses the @requestmapping method annotation to define the uri template for the request. 类似于struts的action-mapping。 可以指定post或者get。
2. @pathvariable
the @pathvariable method parameter annotation is used to indicate that a method parameter should be bound to the value of a uri template variable. 用于抽取url中的信息作为参数。(注意,不包括请求字符串,那是@requestparam做的事情。)
@requestmapping("/owners/{ownerid}", method=requestmethod.get)
public string findowner(@pathvariable string ownerid, model model) {
// ...
}
如果变量名与pathvariable名不一致,那么需要指定:
@requestmapping("/owners/{ownerid}", method=requestmethod.get)
public string findowner(@pathvariable("ownerid") string theowner, model model) {
// implementation omitted
}
tip
method parameters that are decorated with the @pathvariable annotation can be of any simple type such as int, long, date... spring automatically converts to the appropriate type and throws a typemismatchexception if the type is not correct.
3. @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";
}
还可以设置defaultvalue:
@requestmapping("/imageupload")
public string processimageupload(@requestparam(value="name", defaultvalue="arganzheng") 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";
}
4. @requestbody和@responsebody
这两个注解其实用到了spring的一个非常灵活的设计——httpmessageconverter 18.3.2 http message conversion
与@requestparam不同,@requestbody和@responsebody是针对整个http请求或者返回消息的。前者只是针对http请求消息中的一个 name=value 键值对(名称很贴切)。
htppmessageconverter负责将http请求消息(http request message)转化为对象,或者将对象转化为http响应体(http response body)。
public interface httpmessageconverter
{
// indicate whether the given class is supported by this converter.
boolean supports(class extends t> clazz);
// return the list of mediatype objects supported by this converter.
list getsupportedmediatypes();
// read an object of the given type form the given input message, and returns it.
t read(class clazz, httpinputmessage inputmessage) throws ioexception,
httpmessagenotreadableexception;
// write an given object to the given output message.
void write(t t, httpoutputmessage outputmessage) throws ioexception,
httpmessagenotwritableexception;
}
spring mvc对httpmessageconverter有多种默认实现,基本上不需要自己再自定义httpmessageconverter
stringhttpmessageconverter - converts strings
formhttpmessageconverter - converts form data to/from a multivaluemap
bytearraymessageconverter - converts byte arrays
sourcehttpmessageconverter - convert to/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:
public class annotationmethodhandleradapter extends webcontentgenerator
implements handleradapter, ordered, beanfactoryaware {
...
public annotationmethodhandleradapter() {
// no restriction of http methods by default
super(false);
// see spr-7316
stringhttpmessageconverter stringhttpmessageconverter = new stringhttpmessageconverter();
stringhttpmessageconverter.setwriteacceptcharset(false);
this.messageconverters = new httpmessageconverter[]{new bytearrayhttpmessageconverter(), stringhttpmessageconverter,
new sourcehttpmessageconverter(), new xmlawareformhttpmessageconverter()};
}
}
如上:默认的httpmessageconverter是bytearrayhttpmessageconverter、stringhttpmessageconverter、sourcehttpmessageconverter和xmlawareformhttpmessageconverter转换器。所以需要配置一下:
text/plain;charset=gbk
配置好了之后,就可以享受@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);
}
一般情况下我们是不需要自定义httpmessageconverter,不过对于restful应用,有时候我们需要返回jsonp数据:
package me.arganzheng.study.springmvc.util;
import java.io.ioexception;
import java.io.printstream;
import org.codehaus.jackson.map.objectmapper;
import org.codehaus.jackson.map.annotate.jsonserialize.inclusion;
import org.springframework.http.httpoutputmessage;
import org.springframework.http.converter.httpmessagenotwritableexception;
import org.springframework.http.converter.json.mappingjacksonhttpmessageconverter;
import org.springframework.web.context.request.requestattributes;
import org.springframework.web.context.request.requestcontextholder;
import org.springframework.web.context.request.servletrequestattributes;
public class mappingjsonphttpmessageconverter extends mappingjacksonhttpmessageconverter {
public mappingjsonphttpmessageconverter() {
objectmapper objectmapper = new objectmapper();
objectmapper.setserializationconfig(objectmapper.getserializationconfig().withserializationinclusion(inclusion.non_null));
setobjectmapper(objectmapper);
}
@override
protected void writeinternal(object o, httpoutputmessage outputmessage) throws ioexception, httpmessagenotwritableexception {
string jsonpcallback = null;
requestattributes reqattrs = requestcontextholder.currentrequestattributes();
if(reqattrs instanceof servletrequestattributes){
jsonpcallback = ((servletrequestattributes)reqattrs).getrequest().getparameter("jsonpcallback");
}
if(jsonpcallback != null){
new printstream(outputmessage.getbody()).print(jsonpcallback + "(");
}
super.writeinternal(o, outputmessage);
if(jsonpcallback != null){
new printstream(outputmessage.getbody()).println(");");
}
}
}
断掉 bean init 就行了
即所对应的bean 并不是直接注入, 而是在调用的时候在 init
new ApplicationContext().getBean(beanID);
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息