Spring MVC Controller传递枚举值的实例

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

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;
	/**
	 * 枚举
	 * @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";
 }

前台代码:

<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需要两个参数,第一个参数类型就是自己定义的枚举类类型,第二个参数是你枚举里面

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

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

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

(0)

相关推荐

  • Spring MVC处理参数中的枚举类型通用实现方法

    前言 在开发的过程中,会涉及到大量的枚举类型数据,我们都知道,Springmvc本身能自动转换很多的数据类型,也支持你自定义转换类型,非常灵活. 本文主要介绍的是关于Spring MVC处理参数的枚举类型通用实现的相关内容,下面话不多说了,来一起看看详细的介绍吧 业务场景: 前端提交了枚举的一个属性value,想由spring来完成参数类型自动转换成对应的枚举. 比方有一个枚举 @AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @

  • springboot枚举类型传递的步骤

    目录 测试 Converter 灵活化 在本周写项目时,需要将枚举类型作为参数进行传递. 测试 首先先建立一个枚举类: public enum ScoreType { TOTAL_SCORE("总评成绩"), MIDDLE_SCORE("期中成绩"), FINAL_SCORE("期末成绩"); String des; // 描述 ScoreType(String des) { this.des = des; } public String get

  • Spring:如何使用枚举参数

    目录 枚举参数 确认需求 定义枚举 Converter 和 ConverterFactory 加载配置 测试 总结 枚举参数 接口开发过程中不免有表示类型的参数,比如 0 表示未知,1 表示男,2 表示女.通常有两种做法,一种是用数字表示,另一种是使用枚举实现. 使用数字表示就是通过契约形式,约定每个数字表示的含义,接口接收到参数,就按照约定对类型进行判断,接口维护成本比较大. 在 Spring 体系中,使用枚举表示,是借助 Spring 的 Converter 机制,可以将数字或字符串对应到枚

  • springmvc 传递和接收数组参数的实例

    java url中如何传递数组,springMVC框架controller类如何接收数组参数? 下面介绍一下URL中传递数组参数方法: dd.do?titles[]=col1&titles[]=col2&titles[]=col3 或者使用ajax方式传递: var param = {titles:['col1','col2','col3']}; $.ajax({url:"dd.php", type:"post", data:param, async

  • springMVC如何将controller中数据传递到jsp页面

    1> 将方法的返回值该为ModelAndView在返回时,将数据存储在ModelAndView对象中如: newModelAndView("/WEBINF/jsp/showData.jsp","message",message) 其中第一个参数为url,第二个参数为要传递的数据的key,第三个参数为数据对象. 在这里要注意的是 数据是默认被存放在request中的. 示例: @RequestMapping(value="/mad/showData_1

  • Spring MVC Controller传递枚举值的实例

    目录 Spring MVC Controller传递枚举值 功能描述 枚举定义 定义Controller类 请求示例 结论 Spring MVC 枚举传值问题 最后找到解决方案 Spring MVC Controller传递枚举值 功能描述 本文将通过一个小示例,展示在请求参数中传递枚举值. 枚举定义 角色类定义: public enum RoleEnum { EMPLOYEE((short)1, "Employee"), MANAGER((short)2, "Manager

  • Spring MVC+FastJson+Swagger集成的完整实例教程

    基础部分 1. FastJson 简介 Fastjson是一个Java库,可用于将Java对象转换为JSON表示.它也可以被用来将一个JSON字符串转换成一个等效的Java对象.在转换速度上应该是最快的,几乎成为了项目的标配(在ajax请求和接口开发时一般都会用fastjson而不再使用jackson). GitHub: https://github.com/alibaba/fastjson (本地下载) 特性: 在服务器端和android客户端提供最佳性能 提供简单toJSONString()

  • Spring MVC+FastJson+hibernate-validator整合的完整实例教程

    一:hibernate-validator 基础 1. 简介: 通过使用注解Annotations 给类或者类的属性加上约束(constraint),在运行期检查属性值的合法性. 2. 作用: 在API接口开发中参数校验是非常重要的事情,因为客户端很可能会少传参数,或者值不合法,甚至参数值是恶意的,所以对客户端传来的参数的合法性就必须要校验了,其中将参数值的校验规则通过注解的形式注解到属性上是一种比较优雅的方式. 3. 常用的约束注解 @Null 被注释的元素必须为 null @NotNull

  • Spring Mvc中传递参数方法之url/requestMapping详解

    前言 相信大家在使用spring的项目中,前台传递参数到后台是经常遇到的事, 我们必须熟练掌握一些常用的参数传递方式和注解的使用,本文将给大家介绍关于Spring Mvc中传递参数方法之url/requestMapping的相关内容,分享出来供大家参考学习,话不多说,直接上正文. 方法如下 1. @requestMapping: 类级别和方法级别的注解, 指明前后台解析的路径. 有value属性(一个参数时默认)指定url路径解析,method属性指定提交方式(默认为get提交) @Reques

  • Spring MVC处理方法返回值过程解析

    这篇文章主要介绍了Spring MVC处理方法返回值过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 对于Spring MVC处理方法支持支持一系列的返回方式: (1)ModelAndView (2)Model (3)ModelMap (4)Map (5)View (6)String (7)Void (8)Object 一,ModelAndView @RequestMapping("/threadRequest*") publi

  • Spring MVC中自定义拦截器的实例讲解

    1. 引言 拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似于Servlet的Filter. 我们可以让普通的Bean实现HandlerIntercpetor接口或继承HandlerInterceptorAdapter类来实现自定义拦截器. 通过重写WebMvcConfigurerAdapter的addIntercetors方法来注册一个计算每一次请求的处理时间的拦截器. 2. 自定义拦截器的实现 2.1 定义拦截器 新建LogInterceptor类,并继承Ha

  • Spring MVC Mybatis多数据源的使用实例解析

    项目需要从其他网站获取数据,因为是临时加的需求,在开始项目时没想到需要多数据源 于是百度了一下,发现只需要改动一下Spring 的applicationContext.xml文件和编写三个工具类就可以完美实现 applicationContext.xml <!-- 多数据源配置 --> <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource"> <property na

  • Spring MVC 文件上传下载的实例

    Spring MVC 文件上传下载,具体如下: (1) 导入jar包:ant.jar.commons-fileupload.jar.connom-io.jar. (2) 在src/context/dispatcher.xml中添加 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEnc

  • Spring mvc Controller和RestFul原理解析

    控制器Controller 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现. 控制器负责解析用户的请求并将其转换为一个模型. 在Spring MVC中一个控制器类可以包含多个方法 在Spring MVC中,对于Controller的配置方式有很多种 实现Controller接口 Controller是一个接口,在org.springframework.web.servlet.mvc包下,接口中只有一个方法: //实现该接口的类获得控制器功能 public interfa

  • Spring mvc文件上传下载代码实例

    简介 文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作.如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver. 前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data.只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给

随机推荐