使用SpringMVC搭建Rest服务(2)

时间:2017-06-16 09:59

学生的基本结构已经搭建完成,现在需要提供一个管理类,用于来管理学生集合(注意,正常情况下,应当将学生数据存入数据库,这里为了简化,仅将这些信息出入一个Map中进行管理)。学生管理类维护这学生集合,以及基于集合之上的操作。

StudentManager.java

@Component

public class StudentManager {

Map<String, Student> students = new ConcurrentHashMap<String, Student>();

public synchronized void addStudent(Student student){

if(students.containsKey(student.getId()))

return;

students.put(student.getId(), student);

}

public synchronized void deleteStudent(String id){

if(students.containsKey(id))

students.remove(id);

}

public synchronized void updateStudent(String id,Student student){

deleteStudent(id);

if(student.getId()==null || student.getId().equals(""))

student.setId(id);

addStudent(student);

}

public synchronized Student getStudent(String id){

return students.get(id);

}

public synchronized StudentList getStudent() {

StudentList sl = new StudentList();

for(String key : students.keySet())

{

sl.getStudents().add(students.get(key));

}

return sl;

}

}

可以看出,我们将StudentManager标记成component,以便Spring能够将这个类的实例注入到使用它的类中(注意,这个类必须是一个单例模式,因为这个类中维护着学生的集合)。此外,StudentManager中的所有方法都标记成了同步方法,并且Map集合也是一个同步集合。StudentManager提供了对学生集合Map的基本操作。

4.  Rest服务实现

下面提供了使用Spring MVC实现Rest服务的方法。

@Controller

@RequestMapping(value="/students")

public class StudentServer {

private StudentManager manager;

@RequestMapping(method=RequestMethod.POST)

@ResponseBody

public String createStudent(@RequestBody Student student){

manager.addStudent(student);

return student.getId();

}

@RequestMapping(value="/{id}",method=RequestMethod.GET)

@ResponseBody

public Student getStudent(@PathVariable String id){

return manager.getStudent(id);

}

@RequestMapping(method=RequestMethod.GET)

@ResponseBody

public StudentList getStudent(){

return manager.getStudent();

}

@RequestMapping(value="/{id}",method=RequestMethod.PUT)

@ResponseBody

public void updateStudent(@RequestBody Student student,@PathVariable String id){

manager.updateStudent(id, student);

}

@RequestMapping(value="/{id}",method=RequestMethod.DELETE)

@ResponseBody

public void deleteStudent(@PathVariable String id){

manager.deleteStudent(id);

}

@Autowired

public void setManager(StudentManager manager) {

this.manager = manager;

}

}

用Control标记,Spring会认为这是一个Web服务,使用RequestMapping指明了服务映射的URI内容和映射的Http请求的方法。使用PathVariable可以从URI中获取参数,使用RequestBody,Spring会将Http消息体内部的数据使用配置策略转换成一个对象(参考5. Spring的配置),使用ResponseBody,Spring会将返回值转换成消息体需要的格式(参考5.Spring的配置)。

5.  Spring的配置

现在,我们需要对Spring进行基本的配置,以便Spring能够使用正确的方式对接收到(发送出)的Http请求(相应)使用正确的方法处理(生成)消息体。我们的基本策略是,如果接收到的是XML文档(即Content-type是***/xml类型),则使用JAXB2将消息体转换成对象,否则将消息体作为普通文本进行处理;如果要发送的消息是复杂对象(不是简单类型,例如:String、Integer、void等),则将消息使用JAXB2进行编组,否则仅生成文本消息。

Spring的配置如下:

SpringConfig.java

@Configuration

public class SpringConfig {

private Jaxb2Marshaller marshaller;

public @Bean Jaxb2Marshaller jaxb2Marshaller()//配置JAXB2Context

{  

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();//创建JAXB上下文环境

marshaller.setClassesToBeBound(Student.class,StudentList.class);//映射的xml类放入JAXB环境中    

this.marshaller = marshaller;

return marshaller;

}

public @Bean AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()

{

AnnotationMethodHandlerAdapter adapter = new AnnotationMethodHandlerAdapter();//创建消息体转换器

HttpMessageConverter<?>[] converters = new HttpMessageConverter<?>[2];//创建转换数组

StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();//创建字符转换器

MarshallingHttpMessageConverter marshallerConverter = new MarshallingHttpMessageConverter();//创建xom转换器

marshallerConverter.setMarshaller(marshaller);//设置marshaller

marshallerConverter.setUnmarshaller(marshaller);//设置unmarshaller

//将两个转换器放入列表

converters[0] = (stringConverter);

converters[1] = (marshallerConverter);

//将转换器列表赋值给消息体转换器

adapter.setMessageConverters(converters);

return adapter;   //返回消息体转换器  

}

}

SpringConfig中先配置了JAXB2,在JAXB2中需要指定在2学生数据结构中生成的两个类,因此JAXB环境会知道如何将Student和StudentList编组和解组。