文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring MVC Controller传递枚举值的实例

2024-04-02 19:55

关注

Spring MVC Controller传递枚举值

功能描述

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

枚举定义

角色类定义:


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之内作为@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.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

实现分析:


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());
        }
    }
}

底层实现为将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;
	
	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";
 }

前台代码:


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

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

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

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

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

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯