leftso 329 0 2019-04-13 20:25:45 编程技术 spring boot Enums

一.情景说明

在许多企业应用程序中,通常需要使用分类变量限制用户请求。在java中,我们使用枚举来实现它。大多数情况下,我们在模型类中定义枚举,并期望用户在请求中提供确切的枚举。这还在对服务器的任何传入请求中添加了一级验证。但是在使用Spring控制器公开REST端点时,这些枚举不会直接在方法输入中作为请求参数进行匹配,因为我们得到的请求是普通的String,但我们的控制器方法需要枚举。

在本文中,我们将了解如何在使用Spring REST时在requet参数中接受和解析这些String作为枚举。我们将公开一个接受枚举类型作为请求参数的示例REST端点。我们将使用spring boot功能来构建这个应用程序。虽然枚举将以大写字母定义,但请求String将为小写

二.如何将请求参数中的字符串转换为枚举

因为,我们在Spring REST中的控制器方法将enum作为输入参数而不是普通的String,我们需要想出在控制器方法处理请求并开始执行之前将请求参数中的String转换为枚举。因此,如果我们希望在Spring REST中将枚举作为请求参数,我们需要在注释方法开始执行之前将请求中的String转换为correpsonding枚举。

Spring提供了一个@InitBinder注释,用于标识初始化的方法,WebDataBinder此WebDataBinder将填充带注释的方法的参数。因此,简单的方法是在Spring中注册一些自定义编辑器,这些编辑器将这些字符串转换为枚举作为请求参数。现在让我们看看我们如何在spring中实现它。我们将公开一个REST端点,它接受path参数中的问题类型并根据问题类型返回响应。问题类型将是java中的枚举。

maven依赖
$title(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<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>com.devglan</groupId>
    <artifactId>spring-mvc-enum-example</artifactId>
    <version>0.1.0</version>

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
	
    <dependencies>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
		
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
		
    </dependencies>

</project>
现在让我们定义我们的Application.java以利用spring boot功能。
@SpringBootApplication等效于使用@Configuration@EnableAutoConfiguration@ComponentScan使用其默认属性:
Application.java
$title(Application.java)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
现在让我们定义我们的枚举。
QuestionCategory.java
$title(QuestionCategory.java)
import java.util.Arrays;

public enum QuestionCategory {
	
	CSE("cse"),ECE("ece");
	
	private String value;

	private QuestionCategory(String value) {
		this.value = value;
	}

	public static QuestionCategory fromValue(String value) {
		for (QuestionCategory category : values()) {
			if (category.value.equalsIgnoreCase(value)) {
				return category;
			}
		}
		throw new IllegalArgumentException(
				"Unknown enum type " + value + ", Allowed values are " + Arrays.toString(values()));
	}

}
以下是具有上面定义为私有成员变量的枚举的模型类\
Question.java
$title(Question.java)
public class Question {
	
	private QuestionCategory type;
	private String question;
	private String answer;
	
	public QuestionCategory getType() {
		return type;
	}
	public void setType(QuestionCategory type) {
		this.type = type;
	}
	public String getQuestion() {
		return question;
	}
	public void setQuestion(String question) {
		this.question = question;
	}
	public String getAnswer() {
		return answer;
	}
	public void setAnswer(String answer) {
		this.answer = answer;
	}

}
现在是时候定义我们的控制器了 - QuestionController.java.get()方法接受问题类型作为路径参数,问题类型是枚举。它还注册@InitBinder了在本文开头如上所述注释的自定义编辑器。每次调用此api时,我们的自定义转换器都将执行,请求参数中的String将转换为相应的枚举。
QuestionController.java
import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
$title(QuestionController.java)
import com.devglan.model.Question;
import com.devglan.model.QuestionCategory;
import com.devglan.model.QuestionCategoryConverter;

@RestController
public class QuestionController {

	@RequestMapping(value = "/{type}", method = RequestMethod.GET)
	public List get(@PathVariable(value = "type") QuestionCategory category) {
		return getQuestionsByCategory(category);
	}

	private List getQuestionsByCategory(QuestionCategory category) {
		List questions = new ArrayList();
		Question question = new Question();
		question.setType(category);
		if(category == QuestionCategory.CSE){
			question.setQuestion("What is Operating System.");
			question.setAnswer("This is the answer of what is os.");
		} else if(category == QuestionCategory.ECE){
			question.setQuestion("What is a transistor.");
			question.setAnswer("This is the answer of what is transistor.");
		}
		questions.add(question);
		return questions;
	}
	
	@InitBinder
	public void initBinder(final WebDataBinder webdataBinder) {
		webdataBinder.registerCustomEditor(QuestionCategory.class, new QuestionCategoryConverter());
	}

}
以下是转换器类
QuestionCategoryConverter.java
$title(QuestionCategoryConverter.java)
import java.beans.PropertyEditorSupport;

public class QuestionCategoryConverter extends PropertyEditorSupport{

	 public void setAsText(final String text) throws IllegalArgumentException {
	        setValue(QuestionCategory.fromValue(text));
	    }

}

三.测试

1.将Application.java作为Java应用程序运行
2.点击url localhost://8080/cse。您可以期待以下结果,其中questionType为ECE
运行结果