Heim > Java > javaLernprogramm > So erstellen Sie ein mandantenfähiges Springboot-SaaS

So erstellen Sie ein mandantenfähiges Springboot-SaaS

WBOY
Freigeben: 2023-05-12 16:49:06
nach vorne
1663 Leute haben es durchsucht

Technisches Framework

Springboot-Version ist 2.3.4.RELEASE

Die Persistenzschicht übernimmt JPA

Mandantenmodelldesign

Da alle Mandanten der Saas-Anwendung denselben Dienst und dieselbe Datenbank verwenden, um Mandantendaten zu isolieren, eine BaseSaasEntity wird hier erstellt

Es gibt nur ein Feld „tenantId“ in
public abstract class BaseSaasEntity {
    @JsonIgnore
    @Column(nullable = false, updatable = false)
    protected Long tenantId;
    }
Nach dem Login kopieren

, das der Mieter-ID entspricht. Alle Mandanten-Geschäftseinheiten erben diese übergeordnete Klasse. Schließlich wird die „tenantId“ verwendet, um zu unterscheiden, zu welchem ​​Mandanten die Daten gehören.

SQL-Mandantendatenfilterung

Wie üblich sollte nach der Erstellung der Tabelle der CURD des entsprechenden Moduls befolgt werden. Die grundlegendste Anforderung für Saas-Anwendungen ist jedoch die Isolierung der Mandantendaten, d von: Fügen Sie wheremieter=? zu allen Mandantengeschäfts-SQL hinzu, um die Mandantendatenfilterung zu implementieren.

Hibernate-Filter

Wenn wir unserem Unternehmen Mandanten-SQL-Filtercode hinzufügen, ist nicht nur die Arbeitsbelastung enorm, sondern auch die Fehlerwahrscheinlichkeit hoch. Ideal ist es, das gefilterte SQL-Splicing zusammenzuarbeiten und die SQL-Filterung auf der Mandanten-Geschäftsschnittstelle zu aktivieren. Da JPA von Hibernate implementiert wird, können wir hier einige Funktionen von Hibernate nutzen. Hibernate-Filter sind global gültige, benannte Filter, die Parameter annehmen können. Sie können wählen, ob ein Filter für eine bestimmte Hibernate-Sitzung aktiviert (oder deaktiviert) werden soll.

Hier definieren wir eine SQL-Filterbedingung über @FilterDef und @Filter vor. Verwenden Sie dann eine @TenantFilter-Annotation, um zu identifizieren, dass die Schnittstelle eine Datenfilterung erfordert

@MappedSuperclass
@Data
@FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "long")})
@Filter(condition = "tenant_id=:tenantId", name = "tenantFilter")
public abstract class BaseSaasEntity {
    @JsonIgnore
    @Column(nullable = false, updatable = false)
    protected Long tenantId;


    @PrePersist
    public void onPrePersist() {
        if (getTenantId() != null) {
            return;
        }
        Long tenantId = TenantContext.getTenantId();
        Check.notNull(tenantId, "租户不存在");
        setTenantId(tenantId);
    }
}
Nach dem Login kopieren
Es ist ersichtlich, dass diese Schnittstelle auf der Methode platziert ist, die der Controller-Ebene entspricht. Die Bedeutung des Hinzufügens der Transaktionsanmerkung @Transactional besteht darin, dass eine Transaktion aktiviert sein muss, um den Ruhezustandsfilter zu aktivieren. Die Standardeinstellung ist hier eine schreibgeschützte Transaktion. Definieren Sie abschließend einen Aspekt, um den Filter zu aktivieren

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Transactional
public @interface TenantFilter {

    boolean readOnly() default true;

}
Nach dem Login kopieren

Das Objekt des Aspekts ist die gerade angepasste @TenantFilter-Anmerkung. Rufen Sie die aktuelle Mandanten-ID ab, bevor die Methode ausgeführt wird, und aktivieren Sie auf diese Weise die Mandantendatenisolierung Sie müssen nur die Geschäftsschnittstelle des Mandanten festlegen. Fügen Sie einfach die Annotation @TenantFilter hinzu, und die Entwicklung muss sich nur um den Geschäftscode kümmern. Der TenantContext im obigen Bild ist der aktuelle Thread-Mandantenkontext. Durch die Vereinbarung mit dem Front-End wird die Mandanten-ID zum Schnittstellenanforderungsheader hinzugefügt. Der Server verwendet den Interceptor, um die erhaltene Mandanten-ID in der ThreadLocal-Unterbibliothek zwischenzuspeichern

Mit zunehmender Anzahl von Mandanten werden die Daten in einer einzelnen MySQL-Datenbank und einer einzelnen Tabelle definitiv einen Engpass erreichen. Hier wird nur die Methode der Unterdatenbank verwendet. Nutzen Sie mehrere Datenquellen, um eine n:1-Zuordnung von Mandanten und Datenquellen durchzuführen.

@Aspect
@Slf4j
@RequiredArgsConstructor
public class TenantSQLAspect {
    private static final String FILTER_NAME = "tenantFilter";
    private final EntityManager entityManager;
    @SneakyThrows
    @Around("@annotation(com.lvjusoft.njcommon.annotation.TenantFilter)")
    public Object aspect(ProceedingJoinPoint joinPoint) {
        Session session = entityManager.unwrap(Session.class);
        try {
            Long tenantId = TenantContext.getTenantId();
            Check.notNull(tenantId, "租户不存在");
            session.enableFilter(FILTER_NAME).setParameter("tenantId", tenantId);
            return joinPoint.proceed();
        } finally {
            session.disableFilter(FILTER_NAME);
        }
    }
}
Nach dem Login kopieren
Deklarieren Sie eine dynamische Routing-Datenquelle, indem Sie AbstractRoutingDataSource implementieren. Bevor das Framework datesource verwendet, ruft Spring die Methode „determineCurrentLookupKey()“ auf, um zu bestimmen, welche Datenquelle verwendet werden soll. Der DataSourceContext ähnelt hier dem TenantContext oben. Nachdem Sie die TenantInfo im Interceptor erhalten haben, suchen Sie den Datenquellenschlüssel, der dem aktuellen Mandanten entspricht, und legen Sie ihn in ThreadLocal fest.

Das obige ist der detaillierte Inhalt vonSo erstellen Sie ein mandantenfähiges Springboot-SaaS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage