好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring MVC Controller传递枚举值的实例

Spring MVC Controller传递枚举值

功能描述

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

枚举定义

角色类定义:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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类

?

1

2

3

4

5

6

7

8

9

@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

报错,具体信息如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

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

实现分析:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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参数是一个对象,而对象里面有个枚举类型的属性,死活不能传值。

最后找到解决方案

实体对象:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

@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代码:

?

1

2

3

4

5

6

@RequestMapping ( "/save" )

public String save(ShoppTest st,String tp){

  st.setType(Enum.valueOf(Type. class , tp));

  shoppTestServiceImpl.save(st);

  return "redirect:list.jhtml" ;

}

前台代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

< 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测试数据mon.submit")}" />

< input type = "button" class = "button" value = "${message(" admin测试数据mon.back")}" ο nclick = "location.href='list.jhtml'" />

</ td >

</ tr >

</ table >

</ form >

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

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

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

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

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

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

原文链接:https://blade.blog.csdn.net/article/details/106116025

查看更多关于Spring MVC Controller传递枚举值的实例的详细内容...

  阅读:31次