Spring MVC Controller傳遞枚舉值的實(shí)例
Spring MVC Controller傳遞枚舉值
功能描述
本文將通過一個(gè)小示例,展示在請(qǐng)求參數(shù)中傳遞枚舉值。
枚舉定義
角色類定義:
public enum RoleEnum {
EMPLOYEE((short)1, "Employee"), MANAGER((short)2, "Manager");
private Short value;
private String desc;
private RoleEnum(Short value, String desc) {
this.value = value;
this.desc = desc;
}
public Short value() {
return value;
}
public String desc() {
return desc;
}
}
定義Controller類
@RestController
@Slf4j
public class HomeController {
@GetMapping("/home")
public String getDemo(@RequestParam("role") RoleEnum role) {
log.info("Role Enum:{}" + role);
return role.desc();
}
}
說明: 在這里RoleEnum之內(nèi)作為@RequestParam參數(shù)。
請(qǐng)求示例
Case1: http://localhost:8080/home?role=EMPLOYEE
結(jié)論: 正確返回, Employee
Case2: http://localhost:8080/home?role=Employee
報(bào)錯(cuò),具體信息如下:
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Thu May 14 11:21:32 CST 2020 There was an unexpected error (type=Bad Request, status=400). Failed to convert value of type 'java.lang.String' to required type 'org.course.data.domain.RoleEnum'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam org.course.data.domain.RoleEnum] for value 'employee'; nested exception is java.lang.IllegalArgumentException: No enum constant org.course.data.domain.RoleEnum.employee org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'org.course.data.domain.RoleEnum'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam org.course.data.domain.RoleEnum] for value 'employee'; nested exception is java.lang.IllegalArgumentException: No enum constant org.course.data.domain.RoleEnum.employee at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:133) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:127) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:798) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam org.course.data.domain.RoleEnum] for value 'employee'; nested exception is java.lang.IllegalArgumentException: No enum constant org.course.data.domain.RoleEnum.employee at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129) at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73) at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:53) at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:693) at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:125) ... 51 more Caused by: java.lang.IllegalArgumentException: No enum constant org.course.data.domain.RoleEnum.employee at java.lang.Enum.valueOf(Enum.java:238) at org.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:52) at org.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:38) at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:436) at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ... 57 more
實(shí)現(xiàn)分析:
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
StringToEnumConverterFactory() {
}
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnumConverterFactory.StringToEnum(ConversionUtils.getEnumType(targetType));
}
private class StringToEnum<T extends Enum> implements Converter<String, T> {
private final Class<T> enumType;
public StringToEnum(Class<T> enumType) {
this.enumType = enumType;
}
public T convert(String source) {
return source.isEmpty() ? null : Enum.valueOf(this.enumType, source.trim());
}
}
}
底層實(shí)現(xiàn)為將String轉(zhuǎn)換為Enum值的過程。
結(jié)論
基于枚舉可以限定具體值,簡(jiǎn)單易用。但是缺點(diǎn)是在擴(kuò)展enum之時(shí),無法做法平滑過度升級(jí),會(huì)吹安短暫的異常情況。
Spring MVC 枚舉傳值問題
今天遇到算是棘手的一個(gè)枚舉的問題,后臺(tái)Controller參數(shù)是一個(gè)對(duì)象,而對(duì)象里面有個(gè)枚舉類型的屬性,死活不能傳值。
最后找到解決方案
實(shí)體對(duì)象:
@Entity
@Table(name="xx_sn")
@SequenceGenerator(name = "sequenceGenerator", sequenceName = "xx_sn_sequence")
public class ShoppTest extends BaseEntity{
private static final long serialVersionUID = 2756395514949325790L;
/**
* 枚舉
* @author Administrator
*
*/
public enum Type{
/** 商品 */
product,
/** 訂單 */
order,
/** 收款單 */
payment,
/** 退款單 */
refunds,
/** 發(fā)貨單 */
shipping,
/** 退貨單 */
returns
}
@Column(nullable = false, updatable = false, unique = true)
private Type type;
@Column(nullable = false)
private String lastValue;
public String getLastValue() {
return lastValue;
}
public void setLastValue(String lastValue) {
this.lastValue = lastValue;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
Controller代碼:
@RequestMapping("/save")
public String save(ShoppTest st,String tp){
st.setType(Enum.valueOf(Type.class, tp));
shoppTestServiceImpl.save(st);
return "redirect:list.jhtml";
}
前臺(tái)代碼:
<form id="inputForm" action="save.jhtml" method="post">
<table class="input">
<tr>
<th>
${message("test.lastValue")}:
</th>
<td colspan="2">
<input type="text" name="lastValue" class="text">
</td>
</tr>
<tr>
<th>
<span class="requiredField">*</span>${message("test.type")}:
</th>
<td colspan="2">
<input type="text" name="tp" class="text" maxlength="200" />
</td>
</tr>
</table>
<table class="input">
<tr>
<th>
</th>
<td>
<input type="submit" class="button" value="${message("admin.common.submit")}" />
<input type="button" class="button" value="${message("admin.common.back")}" οnclick="location.href='list.jhtml'" />
</td>
</tr>
</table>
</form>
因?yàn)閟pringMVC對(duì)于枚舉這種特殊的數(shù)據(jù)類型不能直接進(jìn)行數(shù)據(jù)注入,所以訪問Controller的時(shí)候直接就是400錯(cuò)誤。
所以我這里用String去接收前臺(tái)傳來的枚舉需要的數(shù)據(jù),也就是“tp”,用到Enum.ValueOf();
ValueOf需要兩個(gè)參數(shù),第一個(gè)參數(shù)類型就是自己定義的枚舉類類型,第二個(gè)參數(shù)是你枚舉里面
定義的字段名字,這個(gè)字段就對(duì)應(yīng)了你枚舉所得到的值。
最終取到值后賦值給對(duì)象里面的枚舉。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實(shí)戰(zhàn)案例之用戶注冊(cè)并發(fā)送郵件激活/發(fā)送郵件驗(yàn)證碼
現(xiàn)在很多的網(wǎng)站都提供有用戶注冊(cè)功能,當(dāng)我們注冊(cè)成功之后就會(huì)收到封注冊(cè)網(wǎng)站的郵件,郵件里包含了我們的注冊(cè)的用戶名和密碼及激活賬戶的超鏈接等信息,這篇文章主要給大家介紹了關(guān)于java實(shí)戰(zhàn)案例之用戶注冊(cè)并發(fā)送郵件激活/發(fā)送郵件驗(yàn)證碼的相關(guān)資料,需要的朋友可以參考下2021-09-09
關(guān)于SpringBoot靜態(tài)資源路徑管理問題
這篇文章主要介紹了SpringBoot靜態(tài)資源路徑管理,主要包括默認(rèn)靜態(tài)資源路徑,增加靜態(tài)資源路徑前綴的相關(guān)操作,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
Mybatis一對(duì)多和多對(duì)一處理的深入講解
Mybatis可以通過關(guān)聯(lián)查詢實(shí)現(xiàn),關(guān)聯(lián)查詢是幾個(gè)表聯(lián)合查詢,只查詢一次,通過在resultMap里面的association,collection節(jié)點(diǎn)配置一對(duì)一,一對(duì)多的類就可以完成,這篇文章主要給大家介紹了關(guān)于Mybatis一對(duì)多和多對(duì)一處理的相關(guān)資料,需要的朋友可以參考下2021-09-09
詳解Java中的增強(qiáng) for 循環(huán) foreach
foreach 是 Java 中的一種語法糖,幾乎每一種語言都有一些這樣的語法糖來方便程序員進(jìn)行開發(fā),編譯期間以特定的字節(jié)碼或特定的方式來對(duì)這些語法進(jìn)行處理。能夠提高性能,并減少代碼出錯(cuò)的幾率。2017-05-05
SpringBoot環(huán)境配置知識(shí)總結(jié)
今天帶大家了解SpringBoot環(huán)境配置的相關(guān)知識(shí),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05
java json 省市級(jí)聯(lián)實(shí)例代碼
這篇文章介紹了java json 省市級(jí)聯(lián)實(shí)例代碼,有需要的朋友可以參考一下2013-09-09

