Android 和 Hibernate Validator - 可以一起使用吗?

Ale*_*rek 2 java android hibernate hibernate-validator bean-validation

我想知道是否可以在 Android 上使用 Hibernate Validator。我尝试过,但 Android 平台上似乎缺少一些 javax 包(javax.xml.stream.XMLInputFactory)。

\n\n

这是我的代码、依赖项和错误:

\n\n
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();\nValidator validator = validatorFactory.getValidator();\n\ncompile \'org.hibernate:hibernate-validator:5.1.3.Final\'\ncompile \'javax.el:javax.el-api:2.2.4\'\ncompile \'org.glassfish.web:javax.el:2.2.4\'\n\n03-28 10:07:15.562    6477-6477/foo E/AndroidRuntime\xef\xb9\x95 FATAL EXCEPTION: main\n    Process: foo, PID: 6477\n    java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/stream/XMLInputFactory;\n            at org.hibernate.validator.internal.xml.XmlParserHelper.<init>(XmlParserHelper.java:66)\n            at org.hibernate.validator.internal.xml.ValidationXmlParser.<init>(ValidationXmlParser.java:60)\n            at org.hibernate.validator.internal.engine.ConfigurationImpl.getBootstrapConfiguration(ConfigurationImpl.java:287)\n            at org.hibernate.validator.internal.engine.ConfigurationImpl.parseValidationXml(ConfigurationImpl.java:361)\n            at org.hibernate.validator.internal.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:214)\n            at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)\n            at foo.FooActivity.onCreate(FooActivity.java:35)\n            at android.app.Activity.performCreate(Activity.java:5933)\n            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)\n            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)\n            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)\n            at android.app.ActivityThread.access$800(ActivityThread.java:144)\n            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)\n            at android.os.Handler.dispatchMessage(Handler.java:102)\n            at android.os.Looper.loop(Looper.java:135)\n            at android.app.ActivityThread.main(ActivityThread.java:5221)\n            at java.lang.reflect.Method.invoke(Native Method)\n            at java.lang.reflect.Method.invoke(Method.java:372)\n            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)\n            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)\n     Caused by: java.lang.ClassNotFoundException: Didn\'t find class "javax.xml.stream.XMLInputFactory" on path: DexPathList[[zip file "/data/app/foo-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]\n            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)\n            at java.lang.ClassLoader.loadClass(ClassLoader.java:511)\n            at java.lang.ClassLoader.loadClass(ClassLoader.java:469)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at org.hibernate.validator.internal.xml.XmlParserHelper.<init>(XmlParserHelper.java:66)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at org.hibernate.validator.internal.xml.ValidationXmlParser.<init>(ValidationXmlParser.java:60)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at org.hibernate.validator.internal.engine.ConfigurationImpl.getBootstrapConfiguration(ConfigurationImpl.java:287)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at org.hibernate.validator.internal.engine.ConfigurationImpl.parseValidationXml(ConfigurationImpl.java:361)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at org.hibernate.validator.internal.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:214)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at foo.FooActivity.onCreate(FooActivity.java:35)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.Activity.performCreate(Activity.java:5933)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.ActivityThread.access$800(ActivityThread.java:144)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.os.Handler.dispatchMessage(Handler.java:102)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.os.Looper.loop(Looper.java:135)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at android.app.ActivityThread.main(ActivityThread.java:5221)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at java.lang.reflect.Method.invoke(Native Method)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at java.lang.reflect.Method.invoke(Method.java:372)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)\n    Suppressed: java.lang.ClassNotFoundException: javax.xml.stream.XMLInputFactory\n            at java.lang.Class.classForName(Native Method)\n            at java.lang.BootClassLoader.findClass(ClassLoader.java:781)\n            at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)\n            at java.lang.ClassLoader.loadClass(ClassLoader.java:504)\n            ... 21 more\n     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available\n
Run Code Online (Sandbox Code Playgroud)\n

Ale*_*rek 5

我设法解决了这个问题。由于缺少 xml 包,我们必须在配置中禁用此选项。这是我提出的解决方案。

    ValidatorFactory validatorFactory = Validation
            .byDefaultProvider()
            .configure()
            .ignoreXmlConfiguration()
            .buildValidatorFactory();

    Validator validator = validatorFactory.getValidator();
Run Code Online (Sandbox Code Playgroud)

必须具有以下依赖关系:

compile 'org.hibernate:hibernate-validator:5.1.3.Final'
compile 'javax.el:javax.el-api:2.2.4'
compile 'org.glassfish.web:javax.el:2.2.4'
Run Code Online (Sandbox Code Playgroud)

对于来自字符串资源的自定义消息,必须实现 MessageInterpolator。首先,必须扩展应用程序以访问整个项目的全局上下文。

public class ApplicationContext extends Application {
    private static Application application;

    @Override
    public void onCreate() {
        super.onCreate();
        application = this;
    }

    public static Application getApplication() {
        return application;
    }
}
Run Code Online (Sandbox Code Playgroud)

配置:

    ValidatorFactory validatorFactory = Validation
            .byDefaultProvider()
            .configure()
            .ignoreXmlConfiguration()
            .messageInterpolator(new MessageInterpolator() {
                @Override
                public String interpolate(String messageTemplate, Context context) {
                    int id = ApplicationContext.getApplication().getResources().getIdentifier(messageTemplate, "string", R.class.getPackage().getName());
                    return ApplicationContext.getApplication().getString(id);
                }

                @Override
                public String interpolate(String messageTemplate, Context context, Locale locale) {
                    return interpolate(messageTemplate, context);
                }
            })
            .buildValidatorFactory();
Run Code Online (Sandbox Code Playgroud)

例子:

@NotEmpty(message = "error_empty")
private String foo;

<resources>
    <string name="error_empty">Cannot be empty</string>
</resources>
Run Code Online (Sandbox Code Playgroud)