§环境构筑
可以选择用maven新建工程再导入到ide中,也可以直接在ide中新建maven应用。
这里选择后者。下载安装eclipse javaEE版本、maven和Tomcat。
exlipse可以直接安装maven插件,网址是http://m2eclipse.sonatype.org/sites/m2e。
新建Maven Project,搭建web工程,注意选择maven-archetype-webapp类型。
GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
创建项目后修改项目Project Facets -> Dynamic web Module版本为2.5
http://www.cnblogs.com/shangxiaofei/p/5447150.html
新建maven工程后在pom.xml中添加所需的库。一般包括spring有关的jar包以及jackson(封装了json相关的功能,也有教程说需要commons-*,暂时没用到),其他库如有需要在进行添加。简单的方法是:打开pom.xml的Dependencies页面,选择add在搜索相应库就可以了。当然从网上直接copy所有依赖项更简单。
再为工程绑定Tomcat服务器。
§配置
- 先配置WEB-INF/web.xml,注意
mvc-dispatcher
/
这个标签是实现RESTful风格开发所必须的,即对所有Action请求路径作出修改。
-
再配置WEB-INF/mvc-dispatcher-servlet.xml,注意
这个标签注册了Spring MVC分发请求到控制器所必须的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例。保证了@Controll注解的前提配置,同时注意在头中添加相关地址,否则会出错。 xmlns:mvc="http://www.springframework.org/schema/mvc"
注意返回的jsp文件路径,这个没那么重要了,只要不出错就行。
配置applicationContext.xml,目前还不清楚有什么用。
数据的接收与处理
添加controller包以及实现类BaseController(包名称WEB-INF/mvc-dispatcher-servlet.xml中有设置)。
@Controller
public class BaseController {
/*@RequestMapping(value="/fruit", method = POST)
这是对RESTful风格请求映射的注解,默认是不区分GET还是POST等方法的,
如果需要限定再增加method=相应方法。*/
@RequestMapping("/index")
public String index() {
return "index";
}
@RequestMapping(value="/jsonfeed")
/*@ResponseBody用于将Controller的方法返回的对象,
通过适当的HttpMessageConverter转换为指定格式后,
写入到Response对象的body数据区。并不需要我们手动处理。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用*/
public @ResponseBody MyJson getJSON() {
System.out.println("Your Message : ");
MyJson json = new MyJson();
json.setResult(1);
json.setInfo("apple");
return json;
}
@RequestMapping(value="/fruit", method = POST)
public @ResponseBody Fruits getFruit(@RequestBody Fruits fr) {
System.out.println("Your Message : "+fr);
Fruits fruit = new Fruits();
fruit.setNumber(fr.getNumber());
fruit.setFruit(fr.getFruit());
fruit.setStatus(1);
return fruit;
}
}
@RequestMapping和@ResponseBody注解的作用都写在注释里,这里主要再说一下@RequestBody注解。
一般客户端发送POST请求的的请求都会写在header里的body里,通常使用JSON.stringify()转换成成字符串了,所以服务器在处理post请求时使用@PathVariable注解时并不能直接拿到请求数据的属性,但是好像可以用@RequestParam注解获取数据(需要其他依赖),这里我还不是很清楚,有待进一步探究。我在遇到这个问题时首先想到的方法是将字符串转换成java中的Map、List或者对象等数据结构。因此,我创建了Fruits
对象:
public class Fruits {
private int number;
private String fruit;
private int status;
public int getNumber() {
return number;
}
public void setNumber(int name) {
number = name;
}
public String getFruit() {
return fruit;
}
public void setFruit(String name) {
fruit = name;
}
public int getStatus() {
return status;
}
public void setStatus(int name) {
status = name;
}
}
框架会自动帮我转换JSON和对象。这样基于RESTful风格的Spring MVC web服务器就创建成功了。下一步准备调查如何传送文件。
客户端我是用React Native写的,其中POST请求的API使用的fetch。
续 文件上传服务
项目要求新增文件上传功能,在原有项目基础上对应了一下。
这个教程不错:http://www.yiibai.com/spring_mvc/spring-mvc-file-upload-tutorial.html。
主要是在pom.xml添加commons.io和commons.fileupload依赖,在mvc-dispatcher-servlet里加入multipartResolver的配置,包括上传文件大小的限制等等。
由于客户端上传文件是放在表单里的,所以这里要对应一下,@RequesParam("files")中的files是表单中自己设置的属性。
最后贴出所有xml文件和处理文件上传的controller吧。
pom.xml
4.0.0
com.psh
xxxDemoServer
war
0.0.1-SNAPSHOT
xxxDemoServer Maven Webapp
http://maven.apache.org
junit
junit
3.8.1
test
org.springframework
spring-web
4.3.9.RELEASE
org.springframework
spring-webmvc
4.3.9.RELEASE
org.springframework
spring-beans
4.3.9.RELEASE
org.springframework
spring-expression
4.3.9.RELEASE
org.springframework
spring-core
4.3.9.RELEASE
org.springframework
spring-aop
4.3.9.RELEASE
org.springframework
spring-context
4.3.9.RELEASE
javax.servlet
javax.servlet-api
3.0.1
com.fasterxml.jackson.core
jackson-core
2.9.1
com.fasterxml.jackson.core
jackson-annotations
2.9.1
com.fasterxml.jackson.core
jackson-databind
2.9.1
commons-fileupload
commons-fileupload
1.3.2
commons-io
commons-io
2.5
xxxDemoServer
web.xml
xxxDemoServer
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
CharacterEncodingFilter
/*
mvc-dispatcher
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/mvc-dispatcher-servlet.xml
1
mvc-dispatcher
/
org.springframework.web.context.ContextLoaderListener
applicationContext.xml
BaseController.java片段
@RequestMapping(value="/upload/audio", method = POST)
public @ResponseBody Fruits saveAudio(HttpServletRequest request,
@RequestParam("files") MultipartFile[] files) {
System.out.println("Your Message got ");
// Root Directory.
String uploadRootPath = request.getServletContext().getRealPath(
"upload");
System.out.println("uploadRootPath=" + uploadRootPath);
File uploadRootDir = new File(uploadRootPath);
//
// Create directory if it not exists.
if (!uploadRootDir.exists()) {
uploadRootDir.mkdirs();
}
//
List uploadedFiles = new ArrayList();
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
// Client File Name
String name = file.getOriginalFilename();
System.out.println("Client File Name = " + name);
if (name != null && name.length() > 0) {
try {
byte[] bytes = file.getBytes();
// Create the file on server
File serverFile = new File(uploadRootDir.getAbsolutePath()
+ File.separator + name);
// Stream to write data to file in server.
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
//
uploadedFiles.add(serverFile);
System.out.println("Write file: " + serverFile);
} catch (Exception e) {
System.out.println("Error Write file: " + name);
}
}
}
Fruits fruit = new Fruits();
fruit.setNumber(1);
fruit.setFruit("pineapple");
fruit.setStatus(1);
return fruit;
}