Spring MVC Controller传递枚举值的实例

网友投稿 1002 2022-12-06

Spring MVC Controller传递枚举值的实例

Spring MVC Controller传递枚举值的实例

目录Spring MVC Controller传递枚举值功能描述枚举定义定义Controller类请求示例结论Spring MVC 枚举传值问题最后找到解决方案

Spring MVC ContrYcXhEEYtoller传递枚举值

功能描述

本文将通过一个小示例,展示在请求参数中传递枚举值。

枚举定义

角色类定义:

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 HomeConthttp://roller {

@GetMapping("/home")

public String getDemo(@RequestParam("role") RoleEnum role) {

log.info("Role Enum:{}" + role);

return role.desc();

}

}

说明: 在这里RoleEnum之内作为@RequestParam参数。

请求示例

Case1: http://localhost:8080/home?role=EMPLOYEE

结论: 正确返回, Employee

Case2: http://localhost:8080/home?role=Employee

报错,具体信息如下:

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-.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)

at org.apache.tomcat.util-.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

实现分析:

final class StringToEnumConverterFactory implements ConverterFactory {

StringToEnumConverterFactory() {

}

public Converter getConverter(Class targetType) {

return new StringToEnumConverterFactory.StringToEnum(ConversionUtils.getEnumType(targetType));

}

private class StringToEnum implements Converter {

private final Class enumType;

public StringToEnum(Class enumType) {

this.enumType = enumType;

}

public T convert(String source) {

return source.isEmpty() ? null : Enum.valueOf(this.enumType, source.trim());

}

}

}

底层实现为将String转换为Enum值的过程。

结论

基于枚举可以限定具体值,简单易用。但是缺点是在扩展enum之时,无法做法平滑过度升级,会吹安短暂的异常情况。

Spring MVC 枚举传值问题

今天遇到算是棘手的一个枚举的问题,后台Controller参数是一个对象,而对象里面有个枚举类型的属性,死活不能传值。

最后找到解决方案

实体对象:

@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,

/** 发货单 */

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";

}

前台代码:

${message("test.lastValue")}:

*${message("test.type")}:

因为springMVC对于枚举这种特殊的数据类型不能直接进行数据注入,所以访问Controller的时候直接就是400错误。

所以我这里用String去接收前台传来的枚举需要的数据,也就是“tp”,用到Enum.ValueOf();

ValueOf需要两个参数,第一个参数类型就是自己定义的枚举类类型,第二个参数是你枚举里面

定义的字段名字,这个字段就对应了你枚举所得到的值。

最终取到值后赋值给对象里面的枚举。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:超细致讲解Spring框架 JdbcTemplate的使用
下一篇:使用spring注入枚举类型作为参数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~