[JAVA] Lorsque j'ai défini un bean de portée de session dans Spring Boot, il se comportait étrangement et devait être ajusté.

introduction

Une histoire lors de la construction d'une application avec la configuration de Spring Boot (Freemarker + Doma2). C'est mal de l'implémenter avec une compréhension vague, mais quand j'ai défini un bean à portée de session, je ne pouvais pas accéder à des propriétés comme hoge.fuga sur ftl. J'aurais dû y accéder via Getter comme hoge.getFuga (), mais j'ai pensé que je devrais enquêter sur la cause et rendre possible l'accès à la propriété, et je pourrais le faire. Au fait, lorsque je l'ai renvoyé en JSON, il avait des propriétés étranges, alors j'ai essayé de ne pas l'utiliser.

Cause d'un problème

Les beans de session ont été enveloppés dans un proxy créé avec cglib. Peut-être que ce proxy a une variable ThreadLocal, qui est un proxy d'objet différent pour chaque requête.

Politique de correspondance

Vous pouvez écrire une configuration qui supprime le proxy et gère les objets bruts en sortie. Heureusement, le proxy semble avoir une interface appelée ScopedObject, que je pourrais supprimer avec ScopedObject # getTargetObject.

Cliquez ici pour obtenir de l'aide sur Freemarker

FreemarkerConfig.java




@Configuration
public class FreemarkerConfig {

  @Autowired
  void configureFreemarkerConfigurer(FreeMarkerConfig config) {
    freemarker.template.Configuration templateConfig = config.getConfiguration();
    templateConfig.setObjectWrapper(new CustomWrapper());
  }

  private static class CustomWrapper extends DefaultObjectWrapper {
    CustomWrapper() {
      super(freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    }

    @Override
    protected TemplateModel handleUnknownType(Object obj) throws TemplateModelException {
      if (obj instanceof ScopedObject) {
        return super.handleUnknownType(((ScopedObject) obj).getTargetObject());
      }
      return super.handleUnknownType(obj);
    }
  }
}

Cliquez ici pour l'assistance Jackson

JacksonConfig.java



@Configuration
public class JacksonConfig {

  @Autowired
  public void configureObjectMapperConfig(ObjectMapper objectMapper) {
    objectMapper.registerModule(new ScopedObjectModule());
  }

  private static class ScopedObjectModule extends Module {

    @Getter
    private final String moduleName = "scopedObjectModule";

    @Override
    public Version version() {
      return PackageVersion.VERSION;
    }

    @Override
    public void setupModule(SetupContext context) {
      context.addSerializers(new Serializers.Base() {
        @Override
        public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) {
          Class<?> raw = type.getRawClass();
          if (ScopedObject.class.isAssignableFrom(raw)) {
            return new ScopedObjectSerializer(type.getSuperClass());
          }
          return super.findSerializer(config, type, beanDesc);
        }
      });
    }
  }

  @AllArgsConstructor
  private static class ScopedObjectSerializer extends JsonSerializer<ScopedObject> {

    private JavaType type;

    @Override
    public void serialize(ScopedObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
      serializers.findValueSerializer(type).serialize(value.getTargetObject(), gen, serializers);
    }
  }
}

Recommended Posts

Lorsque j'ai défini un bean de portée de session dans Spring Boot, il se comportait étrangement et devait être ajusté.
Lorsque je soutiens l'internationalisation avec Spring Boot, je suis accro à ne pas traduire une langue spécifique
Jusqu'à ce que vous créiez un projet Spring Boot dans Intellij et que vous le transmettiez à Github
Comment ajouter un chemin de classe dans Spring Boot
Je souhaite établir une connexion lorsqu'une base de données est créée à l'aide de Spring et MyBatis
Ce à quoi j'étais accro lors du développement d'une application Spring Boot avec VS Code
Notez que j'étais accro au traitement par lots avec Spring Boot
Un site facile à comprendre lorsque j'ai commencé à apprendre Spring Boot
Comment créer un projet Spring Boot dans IntelliJ
J'ai créé un serveur et un client Restful au printemps.
Obtenez une liste des autres sessions du même utilisateur lorsque vous utilisez Redis Session avec Spring Boot (série 2). Jetez-le également.
Session était un cookie conçu pour être effacé lorsque le navigateur était fermé et était une méthode pour l'échanger: Tutoriel Rails Note - Qu'est-ce qu'une session Rails?
Ce que j'ai corrigé lors de la mise à jour vers Spring Boot 1.5.12 ・ Ce à quoi j'étais accro
Comment appeler et utiliser l'API en Java (Spring Boot)
Créez une application Web Spring Boot qui utilise IBM Cloudant et déployez-la sur Cloud Foundry
Spring Boot 2.2 prend désormais en charge RSocket, alors essayez-le
Intégré dans Spring Boot à l'aide d'un fichier de définition de bean nommé application.xml
Ce que j'ai fait lors de la migration de la série Spring Boot 1.4 vers la série 2.0
J'ai écrit un programme de recherche d'itinéraire dans TDD et j'ai essayé de le refactoriser
Ce que j'ai fait lors de la migration de la série Spring Boot 1.5 vers la série 2.0
Comment afficher les caractères saisis dans Spring Boot sur le navigateur et les liens de référence [Introduction à Spring Boot / Pour les débutants]