독립적인 데이터베이스 액세스를 위한 중간 서비스 생성
회사 비즈니스의 지속적인 변화에 따라 몇 년 전 프로젝트 A와 기본 DB_A 데이터베이스가 핵심 비즈니스 서비스와 핵심 데이터베이스로 전환되었습니다.
DB_A 데이터베이스에서 데이터를 얻으려는 웹 서비스가 점점 더 많아지고 프로젝트 간의 관계는 점차 다음과 같이 발전했습니다.
개발 추세를 쉽게 볼 수 있습니다. 위 그림처럼 문제가 많습니다(프로젝트 관계는 개인이 추상화한 단순화된 버전이므로 실제 상황은 이보다 훨씬 더 복잡합니다).
a. webappA 실행 중 예외가 발생하여 접속할 수 없는 경우 webappB/webappC .... DB_A 데이터를 정상적으로 가져올 수 있나요?
b. webappB/webappC에 제공되는 다양한 서비스... DB_A 데이터를 얻기 위해 webappA의 양은 수평적으로 무한히 확장될 것입니다.
c. 실행 과정에서 webappA 프로젝트는 사용자에게 자체 서비스를 정상적으로 제공할 뿐만 아니라 데이터를 얻기 위한 다른 프로젝트의 요청도 고려해야 하며 이로 인해 필연적으로 성능 병목 현상이 발생합니다.
이러한 문제 중 일부는 프로젝트의 온라인 진행 중에 이미 나타났습니다. 때때로 유지 관리가 중단되어 프로젝트 팀의 면전을 크게 때리는 것은 정말 불편합니다.
여담: 현재 인터넷의 발전 속도와 다양한 기업의 사업 확장에 따라 2년 안에 프로젝트의 발전 방향을 정확하게 예측하고/미리 확장을 준비할 수 있는 건축가는 이미 매우 훌륭합니다.
프로젝트 팀원 중 누군가가 프로젝트 webappA를 우회하자고 제안했고, 나머지 webappB/webappC는... 상호 작용을 위해 DB_A에 직접 연결했지만 빠르게 거부되었습니다(프로젝트마다 데이터베이스 액세스 레이어를 재정의하고 작성해야 함). ).
데이터베이스 접근 레이어를 분리하여 승인된 항목에 접근할 수 있는 서비스로 사용할 수 있나요? 다음과 같습니다:
핵심 아이디어는 무제한의 N wabapp에 대해 특정 데이터베이스에 대한 액세스를 제공하는 것입니다. 이는 프로젝트 간의 결합을 방지할 뿐만 아니라 데이터 액세스 계층의 재사용률도 향상시킵니다.
이미 아이디어가 있으니 시작해 보세요. BB는 문제를 해결할 수 없습니다. 만들고 수많은 구멍을 메우는 데 이틀 정도 걸렸고, 드디어 예상했던 대로 딱 맞았습니다.
원본 프로젝트는 상업적 사용으로 인해 오픈소스화할 수 없습니다. 데모를 재구성한 후 다음 위치에 오픈소스화했습니다.
이 분야에서 실습이 필요한 학생들의 경우 로컬에서 복제하고 실행하면 모든 것이 명확해집니다.
1. 서비스 인터페이스 계층
dao-service-impl 서비스에 액세스하려면 dap-service-api에 의존하는 DB_A 데이터 프로젝트가 필요합니다.
dao-service-api는 외부 레이어에 제공되는 인터페이스입니다. 최종 프레젠테이션 방법은 jar이며, Maven 프로젝트는 이에 직접 의존할 수 있습니다.
maven이 아닌 오래된 프로젝트가 있는 경우 maven-jar-plugin/maven-assemblies-plugin을 사용하여 모든 종속 jar을 어셈블하고 프로젝트 lib에 추가하세요.
2. 서비스 구현 계층
dao-service-impl은 cxf + spring + druid + jpa(hibernate impl) 오픈 소스 클래스 라이브러리로 구축된 순수 백엔드 구성 요소 서비스입니다.
서비스 인터페이스의 구현 레이어로서 최종 프리젠테이션 방법은 war이며 클러스터로 배포하거나 배포하여 다른 프로젝트에 서비스를 제공할 수 있습니다.
디렉토리 구조가 한눈에 명확하고, 개발 시작이 매우 빠릅니다. 간단한 코드 생성(GenCodeServlet)을 구현했으며, dao 레이어 + webService 레이어 인터페이스 및 구현을 자동으로 생성할 수 있습니다.
webService는 레이어 주입 dao 레이어 인터페이스를 구현하고 단일 테이블을 추가, 삭제, 수정 및 확인하는 5가지 방법을 캡슐화합니다. 일반적으로 중복된 방법을 작성할 필요가 없으며 SQL의 90% 작성을 피할 수 있습니다.
@WebService @SOAPBinding(style = SOAPBinding.Style.RPC)public interface UserWs {/** * 通过 ID 过去单个 User 实体对象 * cxf 传输返回对象不可为null,Dao 层获取为null时 * 实例化返回空对象,判空时使用对象主键进行判断即可 * * @param id 主键ID */UserPO getUser(String id);/** * 通过类似的 PO 获取多个 User 实体对象 * * @param userPO 对照的实体对象 */List<UserPO> listUser(UserPO userPO);/** * 通过类似的 PO 获取多个 User 实体对象 * * @param userPO 对照的实体对象 * @param orderby 排序字段 * @param asc 是否升序 */List<UserPO> listUserOrdrBy(UserPO userPO, String orderby, Boolean asc);/** * 新增 User 实体对象 * * @param userPO 要新增的对象 */UserPO addUser(UserPO userPO);/** * 更新 User 实体对象 * * @param userPO 要更新的对象 */UserPO updateUser(UserPO userPO); }
개발 방법은 간단하고 투박합니다. 도구를 사용하여 최대 절전 모드 데이터베이스 po를 역으로 생성하고 GenCodeServlet에 액세스하여 dao/ws 계층 인터페이스 및 구현을 생성합니다.
구성 파일 옵션을 추가하고 cxf webService 서비스를 게시하는 데는 5분 이상 걸리지 않습니다.
3. 서비스 호출자
게시된 단일 테이블 서비스는 비즈니스 논리를 결합하기 위해 프로젝트에서 지정한 위치에 주입되는 호출자의 데이터베이스 액세스 계층으로 이해됩니다.
이 모듈의 목적은 cxf에서 게시한 서비스를 통합하는 방법을 시연하는 것입니다. ㅋㅋㅋ
b. Spring은 호출자 프로젝트에 통합되지 않습니다(dao-service-api에 따라 다름).
도구나 명령을 사용하여 cxf 서비스 클라이언트를 생성하고, 사용되는 서비스 인스턴스를 얻기 위해 팩토리 모드를 도입하고, 결합합니다. 그게 다야.
<jaxws:client id="UserWs" serviceClass="com.rambo.dsd.sys.ws.inter.UserWs" address="${cxf.server.url}/UserWs"><jaxws:outInterceptors><ref bean="wss4JOutInterceptor"/></jaxws:outInterceptors></jaxws:client>
4. cxf 보안 인증 메커니즘
보안 인증이 cxf ws-security wss4j 인터셉터 구현에 도입되어 비누 헤더에 인증 정보가 추가됩니다.
a. 서버 구성
Map<String, Object> map = new HashMap<>();
UserWs userWs = (UserWs) SpringContextUtil.getBean("UserWs");
UserPO user = userWs.getUser("031e7a36972e11e6acede16e8241c0fe");
map.put("1.获取单个用户:", user);
user.setPhone("18975468245");
UserPO userPO1 = userWs.updateUser(user);
map.put("2.更新单个用户:", userPO1);
UserPO userPO2 = new UserPO();
userPO2.setName("rambo");
userPO2.setPasswd(SecurityUtil.encryptMD5("123456"));
userPO2.setSex("男");
userPO2.setYxbz("Y");
UserPO userPO3 = userWs.addUser(userPO2);
map.put("3.新增单个用户:", userPO3);
UserPO userPO4 = new UserPO();
userPO4.setSex("男");
List<UserPO> userPOList = userWs.listUser(userPO4);
map.put("4.获取所有的男用户:", userPOList);
UserPO userPO5 = new UserPO();
userPO5.setSex("男");
List<UserPO> userPOList1 = userWs.listUserOrdrBy(userPO5, "sorts", true);
map.put("5.获取所有的男用户并按照 sorts 字段排序:", userPOList1);return map;
로그인 후 복사
서버는 javax.security.auth.callback.CallbackHandler의 보안 콜백 기능을 구현합니다. Map<String, Object> map = new HashMap<>(); UserWs userWs = (UserWs) SpringContextUtil.getBean("UserWs"); UserPO user = userWs.getUser("031e7a36972e11e6acede16e8241c0fe"); map.put("1.获取单个用户:", user); user.setPhone("18975468245"); UserPO userPO1 = userWs.updateUser(user); map.put("2.更新单个用户:", userPO1); UserPO userPO2 = new UserPO(); userPO2.setName("rambo"); userPO2.setPasswd(SecurityUtil.encryptMD5("123456")); userPO2.setSex("男"); userPO2.setYxbz("Y"); UserPO userPO3 = userWs.addUser(userPO2); map.put("3.新增单个用户:", userPO3); UserPO userPO4 = new UserPO(); userPO4.setSex("男"); List<UserPO> userPOList = userWs.listUser(userPO4); map.put("4.获取所有的男用户:", userPOList); UserPO userPO5 = new UserPO(); userPO5.setSex("男"); List<UserPO> userPOList1 = userWs.listUserOrdrBy(userPO5, "sorts", true); map.put("5.获取所有的男用户并按照 sorts 字段排序:", userPOList1);return map;
UserWsImplService userWsImplService = new UserWsImplService(new URL(cxfServerUrl + "/UserWs?wsdl")); UserWs userWs = userWsImplService.getUserWsImplPort(); addWSS4JOutInterceptor(userWs); UserPO user = userWs.getUser("031e7a36972e11e6acede16e8241c0fe"); map.put("1.获取单个用户:", user); user.setPhone("18975468245"); UserPO userPO1 = userWs.updateUser(user); map.put("2.更新单个用户:", userPO1); UserPO userPO2 = new UserPO(); userPO2.setUuid(StringUtil.getUUID()); userPO2.setName("rambo"); userPO2.setPasswd(SecurityUtil.encryptMD5("123456")); userPO2.setSex("男"); userPO2.setYxbz("Y"); UserPO userPO3 = userWs.addUser(userPO2); map.put("3.新增单个用户:", userPO3); UserPO userPO4 = new UserPO(); userPO4.setSex("男"); UserPOArray userPOArray1 = userWs.listUser(userPO4); map.put("4.获取所有的男用户:", userPOArray1); UserPO userPO5 = new UserPO(); userPO5.setSex("男"); UserPOArray userPOArray2 = userWs.listUserOrdrBy(userPO5, "sorts", true); map.put("5.获取所有的男用户并按照 sorts 字段排序:", userPOArray2.getItem());
b. Spring 클라이언트 구성
<!--服务端安全认证回调函数--><bean id="serverAuthCallback" class="com.rambo.dsd.base.handler.CXFServerAuthHandler"/><!--安全日志认证拦截器--><bean id="wss4JInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"><constructor-arg><map><entry key="action" value="UsernameToken"/><entry key="passwordType" value="PasswordDigest"/><entry key="passwordCallbackRef" value-ref="serverAuthCallback"/></map></constructor-arg></bean>
public class CXFServerAuthHandler implements CallbackHandler { protected final static Logger log = LoggerFactory.getLogger(CXFServerAuthHandler.class); private static final Map<String, String> userMap = new HashMap<String, String>(); static { userMap.put("webappA", "webappA2017"); userMap.put("webappB", "webappB2017"); } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { WSPasswordCallback pc = (WSPasswordCallback) callback; String clientUsername = pc.getIdentifier(); String serverPassword = userMap.get(clientUsername); log.info(" client:{} is starting webservice...", clientUsername); int usage = pc.getUsage(); if (usage == WSPasswordCallback.USERNAME_TOKEN) { pc.setPassword(serverPassword); } else if (usage == WSPasswordCallback.SIGNATURE) { pc.setPassword(serverPassword); } } } }
클라이언트는 javax.security.auth.callback.CallbackHandler의 보안 콜백 기능을 구현합니다.
<!--客户端安全认证回调函数--><bean id="wsClientAuthHandler" class="com.rambo.dsc.handler.WsClientAuthHandler"/><!--安全认证对外拦截器--><bean id="wss4JOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"><constructor-arg><map><entry key="action" value="UsernameToken"/><entry key="user" value="webappA"/><entry key="passwordType" value="PasswordDigest"/><entry key="passwordCallbackRef" value-ref="wsClientAuthHandler"/></map></constructor-arg></bean>
c .인코딩 Spring 통합이 없는 클라이언트
<jaxws:outInterceptors><ref bean="wss4JOutInterceptor"/></jaxws:outInterceptors>
프로젝트의 서버 측 보안 인증은 UsernameToken을 사용합니다. cxf는 다양한 인증 방법/비밀번호 유형을 지원합니다. 물론 보안 인증 방법을 사용자 정의할 수도 있습니다.
4. 결론인터넷 기업의 서비스 아키텍처는 혈통과 습관입니다. 각 기업마다 루틴과 구조가 있고 세부 사항은 다르지만 핵심 개념은 동일합니다.
이 연습에는 약간의 마이크로서비스 느낌이 있지만 서비스 등록/라우팅/내결함성/캐싱 등 충분하지 않습니다. 프로젝트가 너무 많습니다. 오픈소스로 제공됩니다. 관심이 있으시면 함께 개선해 보세요.
위 내용은 독립적인 데이터베이스 액세스를 위한 중간 서비스 생성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Go 언어는 효율적이고 간결하며 배우기 쉬운 프로그래밍 언어입니다. 동시 프로그래밍과 네트워크 프로그래밍의 장점 때문에 개발자들이 선호합니다. 실제 개발에서 데이터베이스 작업은 필수적인 부분입니다. 이 기사에서는 Go 언어를 사용하여 데이터베이스 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. Go 언어에서는 일반적으로 사용되는 SQL 패키지, Gorm 등과 같은 타사 라이브러리를 사용하여 데이터베이스를 운영합니다. 여기서는 sql 패키지를 예로 들어 데이터베이스의 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. MySQL 데이터베이스를 사용하고 있다고 가정합니다.

MySQLi를 사용하여 PHP에서 데이터베이스 연결을 설정하는 방법: MySQLi 확장 포함(require_once) 연결 함수 생성(functionconnect_to_db) 연결 함수 호출($conn=connect_to_db()) 쿼리 실행($result=$conn->query()) 닫기 연결( $conn->close())

Hibernate 다형성 매핑은 상속된 클래스를 데이터베이스에 매핑할 수 있으며 다음 매핑 유형을 제공합니다. Join-subclass: 상위 클래스의 모든 열을 포함하여 하위 클래스에 대한 별도의 테이블을 생성합니다. 클래스별 테이블: 하위 클래스별 열만 포함하는 하위 클래스에 대한 별도의 테이블을 만듭니다. Union-subclass: Joined-subclass와 유사하지만 상위 클래스 테이블이 모든 하위 클래스 열을 통합합니다.

Apple의 최신 iOS18, iPadOS18 및 macOS Sequoia 시스템 릴리스에는 사진 애플리케이션에 중요한 기능이 추가되었습니다. 이 기능은 사용자가 다양한 이유로 손실되거나 손상된 사진과 비디오를 쉽게 복구할 수 있도록 설계되었습니다. 새로운 기능에는 사진 앱의 도구 섹션에 '복구됨'이라는 앨범이 도입되었습니다. 이 앨범은 사용자가 기기에 사진 라이브러리에 포함되지 않은 사진이나 비디오를 가지고 있을 때 자동으로 나타납니다. "복구된" 앨범의 출현은 데이터베이스 손상으로 인해 손실된 사진과 비디오, 사진 라이브러리에 올바르게 저장되지 않은 카메라 응용 프로그램 또는 사진 라이브러리를 관리하는 타사 응용 프로그램에 대한 솔루션을 제공합니다. 사용자는 몇 가지 간단한 단계만 거치면 됩니다.

HTML은 데이터베이스를 직접 읽을 수 없지만 JavaScript 및 AJAX를 통해 읽을 수 있습니다. 단계에는 데이터베이스 연결 설정, 쿼리 보내기, 응답 처리 및 페이지 업데이트가 포함됩니다. 이 기사에서는 JavaScript, AJAX 및 PHP를 사용하여 MySQL 데이터베이스에서 데이터를 읽는 실제 예제를 제공하고 쿼리 결과를 HTML 페이지에 동적으로 표시하는 방법을 보여줍니다. 이 예제에서는 XMLHttpRequest를 사용하여 데이터베이스 연결을 설정하고 쿼리를 보내고 응답을 처리함으로써 페이지 요소에 데이터를 채우고 데이터베이스를 읽는 HTML 기능을 실현합니다.

MySQL 데이터베이스 관리 시스템의 기본 원리 분석 MySQL은 데이터 저장 및 관리를 위해 구조화된 쿼리 언어(SQL)를 사용하는 일반적으로 사용되는 관계형 데이터베이스 관리 시스템입니다. 이 글에서는 데이터베이스 생성, 데이터 테이블 설계, 데이터 추가, 삭제, 수정 및 쿼리 등을 포함한 MySQL 데이터베이스 관리 시스템의 기본 원리를 소개하고 구체적인 코드 예제를 제공합니다. 1. 데이터베이스 생성 MySQL에서는 먼저 데이터를 저장할 데이터베이스 인스턴스를 생성해야 합니다. 다음 코드는 "my

PHP는 웹사이트 개발에 널리 사용되는 백엔드 프로그래밍 언어로, 강력한 데이터베이스 운영 기능을 갖추고 있으며 MySQL과 같은 데이터베이스와 상호 작용하는 데 자주 사용됩니다. 그러나 한자 인코딩의 복잡성으로 인해 데이터베이스에서 잘못된 한자를 처리할 때 문제가 자주 발생합니다. 이 기사에서는 잘못된 문자의 일반적인 원인, 솔루션 및 특정 코드 예제를 포함하여 데이터베이스에서 중국어 잘못된 문자를 처리하기 위한 PHP의 기술과 사례를 소개합니다. 문자가 왜곡되는 일반적인 이유는 잘못된 데이터베이스 문자 집합 설정 때문입니다. 데이터베이스를 생성할 때 utf8 또는 u와 같은 올바른 문자 집합을 선택해야 합니다.

GoWebSocket을 데이터베이스와 통합하는 방법: 데이터베이스 연결 설정: 데이터베이스/sql 패키지를 사용하여 데이터베이스에 연결합니다. WebSocket 메시지를 데이터베이스에 저장: INSERT 문을 사용하여 데이터베이스에 메시지를 삽입합니다. 데이터베이스에서 WebSocket 메시지 검색: SELECT 문을 사용하여 데이터베이스에서 메시지를 검색합니다.
