Über die Verwirrung beim Starten von Java-Servern

In diesem Artikel werden einige Möglichkeiten untersucht, wie diese Dienste in den verwirrenden Situationen, die beim Starten von Java-Servern auftreten, besser ausgerichtet werden können.

Verwenden Sie die Controller-Basisklasse und die Service-Basisklasse

Einführung der Basisklasse

** Controller-Basisklasse **

/** Controller Base Classes */
public class BaseController {    
    /** Injection services related */
    /** User Service */
    @Autowired
    protected UserService userService;
    ...

    /** Static constant correlation */
    /** Phone number mode */
    protected static final String PHONE_PATTERN = "/^[1]([3-9])[0-9]{9}$/";
    ...

    /** Static function related */
    /** Verify phone number */
    protected static vaildPhone(String phone) {...}
    ...
}

Die allgemeine Controller-basierte Klasse umfasst hauptsächlich Injektionsdienste, statische Konstanten und statische Funktionen. Alle Controller erben diese Ressourcen von der Controller-basierten Klasse und können sie direkt in der Funktion verwenden. Ich werde.

** Service Basisklasse ** Die allgemeine Service-Basisklasse lautet wie folgt.

/** Service Base Classes */
public class BaseService {
    /** Injection DAO related */
    /** User DAO */
    @Autowired
    protected UserDAO userDAO;
    ...

    /** Injection services related */
    /** SMS service */
    @Autowired
    protected SmsService smsService;
    ...
    
    /** Injection parameters related */
    /** system name */
    @Value("${example.systemName}")
    protected String systemName;
    ...

    /** Injection constant related */
    /** super user ID */
    protected static final long SUPPER_USER_ID = 0L;
    ...

    /** Service function related */
    /** Get user function */
    protected UserDO getUser(Long userId) {...}
    ...

    /** Static function related */
    /** Get user name */
    protected static String getUserName(UserDO user) {...}
    ...
}

Übliche service-basierte Klassen sind hauptsächlich Injection Datenzugriffsobjekt (DAO), Injection Es enthält Services, Injection-Parameter, statische Konstanten, Servicefunktionen und statische Funktionen. Alle Services erben diese Ressourcen von service-basierten Klassen und können direkt in den Funktionen verwendet werden.

Notwendigkeit für Basisklasse

Zunächst Liskov-Substitutionsprinzip (LSP ) Schauen wir uns das an.

Laut LSP müssen Objekte dieser Unterklasse überall transparent verfügbar sein, wo auf die Basisklasse (Oberklasse) verwiesen wird.

Schauen wir uns als nächstes die Vorteile der Basisklasse an.

  1. Für die Basisklasse verfügt die Unterklasse über alle Methoden und Attribute der Oberklasse, sodass der Arbeitsaufwand für die Erstellung der Unterklasse verringert wird.
  2. Die Basisklasse verbessert die Wiederverwendbarkeit des Codes, da die Unterklasse alle Funktionen der Oberklasse hat.
  3. Die Basisklasse verbessert die Skalierbarkeit des Codes, da Unterklassen ihre eigenen Funktionen hinzufügen können.

Daher können wir die folgenden Schlussfolgerungen ziehen.

  1. Controller-basierte Klassen und Service-basierte Klassen werden an keiner Stelle im Projekt direkt verwendet und nicht durch ihre Unterklassen ersetzt. Daher sind sie nicht LSP-konform.
  2. Controller-basierte Klassen und Service-basierte Klassen haben keine abstrakten Schnittstellenfunktionen oder virtuellen Funktionen. Das heißt, alle Unterklassen, die von der Basisklasse erben, haben keine gemeinsamen Merkmale. Infolgedessen bleibt das, was im Projekt verwendet wird, eine Unterklasse.
  3. Die Controller-Basisklasse und die Service-Basisklasse konzentrieren sich nur auf die Wiederverwendbarkeit. Dies bedeutet, dass Unterklassen Basisklassenressourcen wie Injection-DAOs, Injection-Services, Injection-Parameter, statische Konstanten, Service-Funktionen und statische Funktionen bequem verwenden können. Controller-basierte und Service-basierte Klassen ignorieren jedoch die Notwendigkeit dieser Ressourcen. Das heißt, diese Ressourcen sind für die Unterklasse nicht wesentlich. Infolgedessen wird die Leistung beim Laden der Unterklasse verlangsamt.

Das Fazit ist, dass sowohl Controller-basierte als auch Service-basierte Klassen in verschiedene Klassen fallen. Dies sind keine wirklichen Basisklassen und müssen aufgeteilt werden.

So teilen Sie die Basisklasse

Da die Service-Basisklasse typischer ist als die Controller-Basisklasse, wird in diesem Artikel erläutert, wie die "Basisklasse" am Beispiel der Service-Basisklasse unterteilt wird.

** Fügen Sie die Injection-Instanz in die Implementierungsklasse ein ** Fügen Sie das DAO, die Dienste, Parameter usw., die verwendet werden sollen, in die Implementierungsklasse gemäß dem Prinzip ein: "Führen Sie die Klasse nur ein, wenn sie verwendet wird, und löschen Sie sie, wenn sie nicht benötigt wird."

/** Udser Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** SMS service */
    @Autowired
    private SmsService smsService;

    /** System name */
    @Value("${example.systemName}")
    private String systemName;
    ...
}

** Statische Konstanten in konstante Klasse einordnen ** Kapseln Sie statische Konstanten in die entsprechende Konstantenklasse und verwenden Sie sie bei Bedarf direkt.

/** example constant class */
public class ExampleConstants {
    /** super user ID */
    public static final long SUPPER_USER_ID = 0L;
    ...
}

** Setzen Sie die Servicefunktion in die Serviceklasse ** Kapseln Sie die Servicefunktion in die entsprechende Serviceklasse. Wenn Sie eine andere Serviceklasse verwenden möchten, können Sie eine Instanz dieser Serviceklasse einfügen und Servicefunktionen über die Instanz aufrufen.

/** User service class */
@Service
public class UserService {
    /** Ger user function */
    public UserDO getUser(Long userId) {...}
    ...
}

/** Company service class */
@Service
public class CompanyService {
    /** User service */
    @Autowired
    private UserService userService;
    
    /** Get the administrator */
    public UserDO getManager(Long companyId) {
        CompanyDO company = ...;
        return userService.getUser(company.getManagerId());
    }
    ...
}

** Statische Funktionen in Werkzeugklasse einfügen ** Kapseln Sie statische Funktionen in die entsprechenden Werkzeugklassen und verwenden Sie sie bei Bedarf direkt.

/** User Aid Class */
public class UserHelper {
    /** Get the user name */
    public static String getUserName(UserDO user) {...}
    ...
}

Geschäftscode wird in der Controller-Klasse geschrieben

Erklärung des Phänomens

In der Controller-Klasse wird häufig Code wie der folgende angezeigt.

/** User Controller Class */
@Controller
@RequestMapping("/user")
public class UserController {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** Get user function */
    @ResponseBody
    @RequestMapping(path = "/getUser", method = RequestMethod.GET)
    public Result<UserVO> getUser(@RequestParam(name = "userId", required = true) Long userId) {
        // Get user information
        UserDO userDO = userDAO.getUser(userId);
        if (Objects.isNull(userDO)) {
            return null;
        }
        
        // Copy and return the user
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userDO, userVO);
        return Result.success(userVO);
    }
    ...
}

Der Compiler kann erklären, dass Sie es auf diese Weise schreiben können, da die Schnittstellenfunktion einfach ist und Sie die Schnittstellenfunktion nicht in der Servicefunktion kapseln müssen, aber in Wirklichkeit ist die Schnittstellenfunktion in der Servicefunktion gekapselt. Es besteht keine Notwendigkeit, Änderungen vorzunehmen.

Besonderer Fall

In diesem speziellen Fall sieht der Code folgendermaßen aus:

/** Test Controller Class */
@Controller
@RequestMapping("/test")
public class TestController {
    /** System name */
    @Value("${example.systemName}")
    private String systemName;
    
    /** Access function */
    @RequestMapping(path = "/access", method = RequestMethod.GET)
    public String access() {
        return String.format("You're accessing System (%s)!", systemName);
    }
}

Die Zugriffsergebnisse sind wie folgt.

curl http://localhost:8080/test/access

Sie greifen auf System (null) zu!

Möglicherweise werden Sie gefragt, warum der Parameter systemName nicht eingefügt wurde. In der Dokumentation zu Spring heißt es nun: Es gibt eine Erklärung.

Die eigentliche Verarbeitung der Annotation @Value lautet BeanPostProcessor Beachten Sie, dass dies von a2c65.11461447.0.0.7a631744QsPCA3) ausgeführt wird.

Die BeanPostProcessor-Schnittstelle wird pro Container festgelegt. Dies ist nur relevant, wenn Sie eine Containerhierarchie verwenden. Wenn Sie einen BeanPostProcessor in einem Container definieren, wird diese Arbeit nur für die Beans in diesem Container ausgeführt. In einem Container definierte Beans werden vom BeanPostProcessor in einem anderen Container nicht nachbearbeitet, selbst wenn beide Container Teil derselben Hierarchie sind.

Nach diesen Erläuterungen wird @Value über BeanPostProcessor und WebApplicationContex verarbeitet. //docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/WebApplicationContext.html?spm=a2c65.11461447.0.0.7a631744QsPCA3) und [ApplicationContext](https: / /docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html?spm=a2c65.11461447.0.0.7a631744QsPCA3) wird separat verarbeitet. Daher kann WebApplicationContex den Attributwert des übergeordneten Containers nicht verwenden.

Der Controller erfüllt die Serviceanforderungen nicht. Daher ist es unangemessen, Geschäftscode in die Controller-Klasse zu schreiben.

Dreistufige Serverarchitektur

SpringMVC Server sind Präsentationsschicht, Geschäftsschicht und Persistenz Es verwendet eine klassische dreistufige Architektur mit Ebenen, wobei @Controller, @Service und @Repository für Klassenanmerkungen verwendet werden.

image.png

--Präsentationsschicht: Wird auch als Controller-Schicht bezeichnet. Diese Schicht ist dafür verantwortlich, Anfragen von Kunden zu empfangen und auf Kunden mit Ergebnissen von Kunden zu antworten. Auf dieser Ebene wird häufig HTTP verwendet. --Business-Schicht: Wird auch als Service-Schicht bezeichnet. Diese Schicht ist für die geschäftsbezogene Logikverarbeitung zuständig und nach Funktionen in Dienste und Jobs unterteilt. --Persistenzschicht: Wird auch als Repository-Schicht bezeichnet. Diese Ebene ist für die Datenpersistenz verantwortlich und wird von Unternehmensebenen für den Zugriff auf Caches und Datenbanken verwendet.

Daher entspricht das Schreiben von Geschäftscode in der Controller-Klasse nicht der dreistufigen Architekturspezifikation des Spring MVC-Servers.

Persistenzschichtcode für die Serviceklasse

Auf der funktionalen Seite denke ich, dass es in Ordnung ist, Persistenzschichtcode in die Serviceklasse zu schreiben. Aus diesem Grund akzeptieren viele Benutzer diese Codierungsmethode.

Hauptprobleme

  1. Die Geschäftsschicht und die Persistenzschicht sind gemischt und entsprechen nicht den 3-Schicht-Architekturspezifikationen des Spring MVC-Servers.
  2. Die Komplexität der Geschäftslogik nimmt zu, da Anweisungen und Primärschlüssel mit Geschäftslogik erstellt werden.
  3. Es ist schwierig, die Persistenz-Middleware eines Drittanbieters zu ersetzen, da die Middleware eines Drittanbieters direkt in der Geschäftslogik verwendet wird.
  4. Außerdem ist der Code der Persistenzschicht desselben Objekts in verschiedenen Geschäftslogiken und Objektorientierte Programmierung verteilt. 11461447.0.0.7a631744Qs Entgegen dem Prinzip von PCA3).
  5. Wenn Sie mit dieser Codierungsmethode einen Komponententestfall schreiben, können Sie die Schnittstellenfunktion der Persistenzschicht nicht direkt testen.

Der Datenbankcode wird vom Dienst geschrieben

Hier wird als Beispiel die direkte Abfrage der Datenbankpersistenz-Middleware Hibernate erläutert.

** Erklärung des Phänomens **

/** User Service Class */
@Service
public class UserService {
    /** Session factory */
    @Autowired
    private SessionFactory sessionFactory;

    /** Get user function based on job number */
    public UserVO getUserByEmpId(String empId) {
        // Assemble HQL statement
        String hql = "from t_user where emp_id = '" + empId + "'";
        
        // Perform database query
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        List<UserDO> userList = query.list();
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        
        // Convert and return user
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userList.get(0), userVO);
        return userVO;
    }
}

** Empfohlene Lösung **

/** User DAO CLass */
@Repository
public class UserDAO {
     /** Session factory */
    @Autowired
    private SessionFactory sessionFactory;
    
    /** Get user function based on job number */
    public UserDO getUserByEmpId(String empId) {
        // Assemble HQLstatement
        String hql = "from t_user where emp_id = '" + empId + "'";
        
        // Perform database query
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        List<UserDO> userList = query.list();
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        
        // Return user information
        return userList.get(0);
    }
}

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** Get user function based on job number */
    public UserVO getUserByEmpId(String empId) {
        // Query user based on job number
        UserDO userDO = userDAO.getUserByEmpId(empId);
        if (Objects.isNull(userDO)) {
            return null;
        }
        
        // Convert and return user
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userDO, userVO);
        return userVO;
    }
}

** Über Plug-Ins ** AliGenerator wurde von Alibaba [MyBatis Generator] entwickelt. ](Https://mybatis.org/generator/?spm=a2c65.11461447.0.0.7a631744QsPCA3) -basiertes Tool, das automatisch Code für die DAO-Schicht (Data Access Object) generiert. Für den von AliGenerator generierten Code müssen Sie bei der Ausführung komplexer Abfragen Abfragebedingungen in Ihrem Geschäftscode erstellen. Infolgedessen wird der Geschäftscode besonders aufgebläht.

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** Get user function */
    public UserVO getUser(String companyId, String empId) {
        // Query database
        UserParam userParam = new UserParam();
        userParam.createCriteria().andCompanyIdEqualTo(companyId)
            .andEmpIdEqualTo(empId)
            .andStatusEqualTo(UserStatus.ENABLE.getValue());
        List<UserDO> userList = userDAO.selectByParam(userParam);
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        
        // Convert and return users
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userList.get(0), userVO);
        return userVO;
    }
}

Persönlich mag ich es nicht, Plugins zu verwenden, um Code für DAO-Ebenen zu generieren. Stattdessen bevorzuge ich die Verwendung des ursprünglichen MyBatis XML für die Zuordnung.

Wenn Sie sich für ein Plug-In entscheiden, sollten Sie die Vorteile des Plug-Ins nutzen und gleichzeitig die Nachteile des Plug-Ins akzeptieren.

Redis-Code zur Serviceklasse

Erläuterung

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;
    /** Redistemplate */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /** User primary key mode */
    private static final String USER_KEY_PATTERN = "hash::user::%s";

    /** Save user function */
    public void saveUser(UserVO user) {
        // Convert user information
        UserDO userDO = transUser(user);

        // Save Redis user
        String userKey = MessageFormat.format(USER_KEY_PATTERN, userDO.getId());
        Map<String, String> fieldMap = new HashMap<>(8);
        fieldMap.put(UserDO.CONST_NAME, user.getName());
        fieldMap.put(UserDO.CONST_SEX, String.valueOf(user.getSex()));
        fieldMap.put(UserDO.CONST_AGE, String.valueOf(user.getAge()));
        redisTemplate.opsForHash().putAll(userKey, fieldMap);

        // Save database user
        userDAO.save(userDO);
    }
}

** Empfohlene Lösung **

/** User Redis Class */
@Repository
public class UserRedis {
    /** Redistemplate */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /** Primary key mode */
    private static final String KEY_PATTERN = "hash::user::%s";
    
    /** Save user function */
    public UserDO save(UserDO user) {
        String key = MessageFormat.format(KEY_PATTERN, userDO.getId());
        Map<String, String> fieldMap = new HashMap<>(8);
        fieldMap.put(UserDO.CONST_NAME, user.getName());
        fieldMap.put(UserDO.CONST_SEX, String.valueOf(user.getSex()));
        fieldMap.put(UserDO.CONST_AGE, String.valueOf(user.getAge()));
        redisTemplate.opsForHash().putAll(key, fieldMap);
    }
}

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;
    /** User Redis */
    @Autowired
    private UserRedis userRedis;

    /** Save user function */
    public void saveUser(UserVO user) {
        //Informationen zur Konvertierung
        UserDO userDO = transUser(user);

        // Save Redis user
        userRedis.save(userDO);

        // Save database user
        userDAO.save(userDO);
    }
}

Verkapselt die objektbezogene Operationsschnittstelle von Redis in DAO-Klassen. Es entspricht den objektorientierten Programmierprinzipien des Spring MVC-Servers und den dreistufigen Architekturspezifikationen, wodurch die Verwaltung und Wartung von Code vereinfacht wird.

Die Datenbankmodellklasse ist der Schnittstelle ausgesetzt

Beschreibung der Symptome

/** User DAO Class */
@Repository
public class UserDAO {
    /** Get user function */
    public UserDO getUser(Long userId) {...}
}

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** Get user function */
    public UserDO getUser(Long userId) {
        return userDAO.getUser(userId);
    }
}

/** User Controller Class */
@Controller
@RequestMapping("/user")
public class UserController {
    /** User service */
    @Autowired
    private UserService userService;

    /** Get user function */
    @RequestMapping(path = "/getUser", method = RequestMethod.GET)
    public Result<UserDO> getUser(@RequestParam(name = "userId", required = true) Long userId) {
        UserDO user = userService.getUser(userId);
        return Result.success(user);
    }
}

Der Vorgängercode scheint der dreistufigen Architektur des Spring MVC-Servers zu entsprechen. Das einzige Problem besteht darin, dass das Datenbankmodell UserDO direkt der externen Schnittstelle ausgesetzt ist.

Bestehende Probleme und Lösungen

** Bestehende Probleme **

  1. Das Tabellendesign der Datenbank wird indirekt angezeigt, was für die Analyse konkurrierender Produkte praktisch ist.
  2. Wenn für Datenbankabfragen keine Feldbeschränkungen gelten, ist die Menge der Schnittstellendaten sehr groß und verschwendet wertvollen Benutzerverkehr.
  3. Wenn für Datenbankabfragen keine Feldbeschränkungen gelten, können vertrauliche Felder leicht für die Schnittstelle verfügbar gemacht werden, was zu Datensicherheitsproblemen führt.
  4. Wenn die Datenbankmodellklasse die Anforderungen der Schnittstelle nicht erfüllen kann, müssen der Datenbankmodellklasse weitere Felder hinzugefügt werden, was zu einer Nichtübereinstimmung zwischen der Datenbankmodellklasse und den Feldern der Datenbank führt.
  5. Wenn die Schnittstellendokumentation nicht ordnungsgemäß verwaltet wird, hilft das Lesen des Codes nicht dabei, festzustellen, welche Felder in der Datenbankmodellklasse von der Schnittstelle verwendet werden. Dies macht den Code weniger wartbar.

Lösung

  1. Aus Sicht des Managementsystems muss die Datenbankmodellklasse vollständig unabhängig von der Schnittstellenmodellklasse sein.
  2. Aufgrund der Struktur des Projekts darf der Entwickler die Datenbankmodellklasse nicht für die Schnittstelle verfügbar machen.

3 Möglichkeiten, ein Projekt zu erstellen

Im Folgenden wird beschrieben, wie Sie Java-Projekte wissenschaftlicher erstellen, um effektiv zu verhindern, dass Entwickler Datenbankmodellklassen für die Schnittstelle verfügbar machen.

** Methode 1: Erstellen Sie ein Projekt mit einem gemeinsam genutzten Modell ** Platzieren Sie alle Modellklassen in einem Modellprojekt (Beispielmodell). Alle anderen Projekte (Beispiel-Repository, Beispiel-Service, Beispiel-Website usw.) basieren auf einem Beispielmodell. Das Beziehungsdiagramm ist wie folgt.

image.png

image.png

Risiko Das Präsentationsschichtprojekt (Beispiel-Webanwendung) kann jede Servicefunktion des Geschäftsschichtprojekts (Beispieldienst) aufrufen, und die DAO-Funktion des Persistenzschichtprojekts (Beispiel-Repository) kann direkt auf die Geschäftsschichten angewendet werden. Sie können es auch nennen.

** Methode 2: Erstellen Sie ein Projekt mit einem separaten Modell ** Erstellen Sie ein API-Projekt (Beispiel-API) separat, um die externe Schnittstelle und ihre Modell-VO-Klasse zu abstrahieren. Das Business-Tier-Projekt (Beispieldienst) implementiert diese Schnittstellen und stellt Dienste für das Präsentationsschichtprojekt (Beispiel-Webanwendung) bereit. Das Präsentationsschichtprojekt (Beispiel-Webanwendung) ruft nur die im API-Projekt definierten Dienstschnittstellen (Beispiel-API) auf.

image.png

image.png

Risiko Das Präsentationsschichtprojekt (Beispiel-Webanwendung) kann weiterhin die interne Servicefunktionalität des Geschäftsschichtprojekts (Beispieldienst) und die DAO-Funktionalität des Persistenzschichtprojekts (Beispielrepository) aufrufen. Um diese Situation zu vermeiden, sollte das Managementsystem zulassen, dass das Präsentationsschichtprojekt (Beispiel-Webanwendung) nur die vom API-Projekt definierten Dienstschnittstellenfunktionen (Beispiel-API) aufruft.

** Methode 3: Erstellen Sie ein serviceorientiertes Projekt ** Packen Sie das Business-Tier-Projekt (Beispiel-Service) und das Persistenz-Tier-Projekt (Beispiel-Repository) mithilfe des Dubbo-Projekts (Beispiel-Dubbo) in einen Service. Bietet Schnittstellenfunktionen, die in API-Projekten (example-api) für Business-Layer-Projekte (example-webapp) oder andere Business-Projekte (other-service) definiert sind.

image.png

image.png

Hinweis: Das Dubbo-Projekt (Beispiel-Dubbo) gibt nur die im API-Projekt definierte Dienstschnittstelle frei (Beispiel-API). Dadurch wird sichergestellt, dass das Datenbankmodell nicht verfügbar gemacht wird. Business-Layer-Projekte (z. B. Webapp) und andere Geschäftsprojekte (z. B. andere Services) hängen nur von API-Projekten (z. B. API) ab und können nur in API-Projekten definierte Service-Schnittstellen aufrufen.

Weniger empfohlene Vorschläge

Einige Benutzer haben möglicherweise die folgenden Überlegungen: Unter Berücksichtigung der Tatsache, dass das Schnittstellenmodell und das persistente Schichtmodell getrennt sind, muss die DO-Klasse des Datenabfragemodells auch im persistenten Schichtmodell definiert werden, wenn die VO-Klasse des Datenabfragemodells im Schnittstellenmodell definiert ist. Es wird____geben. Wenn das Schnittstellenmodell die VO-Klasse des Datenrückgabemodells definiert, muss das Persistenzschichtmodell auch die DO-Klasse des Datenrückgabemodells definieren. Dies ist jedoch nicht gut für eine schnelle iterative Entwicklung zu Beginn des Projekts geeignet. Darüber hinaus stellen sich auch folgende Fragen. Ist es möglich, dass die Persistenzschicht das Schnittstellendatenmodell verwendet, ohne das Persistenzschichtdatenmodell über die Schnittstelle verfügbar zu machen?

Diese Methode ist nicht akzeptabel, da sie die Unabhängigkeit der dreistufigen Architektur des Spring MVC-Servers beeinträchtigt. Diese Methode macht die Datenbankmodellklasse jedoch nicht verfügbar und ist für eine schnelle iterative Entwicklung akzeptabel. Daher ist dies ein weniger empfohlener Vorschlag.

/** User DAO Class */
@Repository
public class UserDAO {
    /** Calculate user function */
    public Long countByParameter(QueryUserParameterVO parameter) {...}
    /** Query user function */
    public List<UserVO> queryByParameter(QueryUserParameterVO parameter) {...}
}

/** User Service Class */
@Service
public class UserService {
    /** User DAO */
    @Autowired
    private UserDAO userDAO;

    /** Query user function */
    public PageData<UserVO> queryUser(QueryUserParameterVO parameter) {
        Long totalCount = userDAO.countByParameter(parameter);
        List<UserVO> userList = null;
        if (Objects.nonNull(totalCount) && totalCount.compareTo(0L) > 0) {
            userList = userDAO.queryByParameter(parameter);
        }
        return new PageData<>(totalCount, userList);
    }
}

/** User Controller Class */
@Controller
@RequestMapping("/user")
public class UserController {
    /** User service */
    @Autowired
    private UserService userService;

    /** Query user function (with the page index parameters of startIndex and pageSize) */
    @RequestMapping(path = "/queryUser", method = RequestMethod.POST)
    public Result<PageData<UserVO>> queryUser(@Valid @RequestBody QueryUserParameterVO parameter) {
        PageData<UserVO> pageData = userService.queryUser(parameter);
        return Result.success(pageData);
    }
}

Fazit

Jeder hat seine eigene Meinung darüber, wie man Java nutzt, und natürlich gibt dieser Artikel nur meine persönliche Meinung wieder. Aber für mich war es wichtig, meine Gedanken aufgrund meiner Erfahrungen mit einigen Startups auszudrücken, für die ich zuvor gearbeitet habe. Denn nach meinem Verständnis ist das gesamte System besser, wenn diese chaotischen Konfigurationen behoben sind.

Recommended Posts

Über die Verwirrung beim Starten von Java-Servern
Über die Idee anonymer Klassen in Java
Eine Geschichte über das JDK in der Java 11-Ära
Denken Sie an das JAVA = JAVAscript-Problem (wird in Zukunft benötigt).
Über Java Abstract Class
Erfahren Sie mehr über Spezifikationen, während Sie FizzBuzz verkürzen, das in Java geschrieben wurde
Denken Sie über die Unterschiede zwischen Funktionen und Methoden nach (in Java)
Errate den Zeichencode in Java
Über das Symbol <%%> in Rails erb
Geben Sie den Java-Speicherort in eclipse.ini an
Entpacken Sie die Zip-Datei in Java
Informationen zur aktuellen Entwicklungsumgebung (Java 8)
Analysieren der COTOHA-API-Syntaxanalyse in Java
Informationen zur Dateikopierverarbeitung in Java
Rufen Sie die Super-Methode in Java auf
Informationen zum Zurückgeben einer Referenz in einem Java Getter
Holen Sie sich das Ergebnis von POST in Java
Erraten Sie das Java Persistence Framework 2017 (3) Reladomo
Java-Referenz zum Verständnis in der Abbildung
Versuchen Sie es mit der Stream-API in Java
Rufen Sie die Windows-Benachrichtigungs-API in Java auf
Über das Verfahren, damit Java funktioniert
[Erstellen] Ein Memorandum über das Codieren in Java
Über das neue Release-Modell von Java @ Seki Java (20.07.2018)
Ich habe das neue Yuan-Problem in Java ausprobiert
[Java] Verwenden Sie kryptografische Technologie mit Standardbibliotheken
Notizen im Kopf organisieren (Java-Arrangement)
Versuchen Sie, den CORBA-Dienst unter Java 11+ aufzurufen
Informationen zu Datensätzen, die zur Vorschau in Java JDK 14 hinzugefügt wurden
Was ist die Hauptmethode in Java?
So erhalten Sie das Datum mit Java
Fortsetzung Sprechen Sie über das Schreiben von Java mit Emacs @ 2018
Über das Phänomen, dass StackOverflowError bei der Verarbeitung mit regulären Java-Ausdrücken auftritt
Die Geschichte des Schreibens von Java in Emacs
Konsoleneingabe in Java (Verständnis des Mechanismus)
Eindrücke und Zweifel an der erstmaligen Verwendung von Java in Android Studio
Informationen zur Bedeutung von Typvariablen, E, T usw., die in in Java verwendeten Generika verwendet werden
In Bezug auf transiente Modifikatoren und Serialisierung in Java
Die Geschichte des einfachen String-Vergleichs in Java
[Java] Behandlung von Java Beans in der Methodenkette
Die Geschichte eines gewöhnlichen Othello in Java
Informationen zur Beschreibungsreihenfolge der Java-Systemeigenschaften
ChatWork4j für die Verwendung der ChatWork-API in Java
Organisiertes Memo im Kopf (Java - Control Syntax)
Versuchen Sie, etwa 30 Zeilen in Java zu kratzen (CSV-Ausgabe)
Der in Java 10 eingeführte Schnittpunkttyp ist erstaunlich (?)
Die Geschichte des Lernens von Java in der ersten Programmierung
Messen Sie die Größe eines Ordners mit Java
Informationen zu in Java verwendeten Variablen (lokaler Variablentyp)
Spüren Sie den Lauf der Zeit auch in Java
Notizen im Kopf organisieren (Java - Instance Edition)
[Java] Dateien in src / main / resources lesen
Organisiertes Memo im Kopf (Java - Datentyp)
Zeigen Sie "Hello World" im Browser mit Java an
[Java] Beurteilung durch Eingabe von Zeichen in das Terminal
Zeigen Sie "Hello World" im Browser mit Java an
Versuchen Sie es mit der Syntaxanalyse der COTOHA-API in Java
[Java] In der Ausgabe wird etwas als "-0.0" angezeigt
Importieren Sie Dateien derselben Hierarchie in Java
Über die Java-Schnittstelle
[Java] Informationen zu Java 12-Funktionen