Ajax 핵심 API(소위 XMLHttpRequest)의 유일한 목적은 웹 브라우저와 서버 간에 데이터를 교환하기 위해 HTTP 요청을 보내는 것입니다. 웹 페이지에서 실행되는 JavaScript 코드는 XMLHttpRequest를 사용하여 서블릿이나 JSP 페이지와 같은 서버측 스크립트에 요청 매개변수를 제출할 수 있습니다. 호출하는 Servlet/JSP는 전체 페이지를 새로 고치지 않고 일반적으로 사용자 보기를 업데이트하는 데 사용되는 데이터가 포함된 응답을 다시 보냅니다. 이 접근 방식은 네트워크 트래픽이 감소하고 웹 UI가 데스크탑 GUI만큼 유용하기 때문에 성능 및 유용성 측면에서 고유한 이점을 제공합니다.
그러나 클라이언트 측에서는 JavaScript를 사용하고 서버 측에서는 Java(또는 이에 상응하는 언어)를 사용하여 데이터 교환, 유효성 검사 및 처리를 구현해야 하기 때문에 이러한 사용자 인터페이스를 개발하는 것은 간단하지 않습니다. 그러나 많은 경우 Ajax 기반 인터페이스를 구축하기 위한 추가 노력은 얻을 수 있는 이점을 고려하면 그만한 가치가 있습니다.
이 기사에서는 Ajax 클라이언트와 서버 간에 데이터를 전송하는 주요 방법 중 하나를 소개하고 기존 웹 애플리케이션 모델과 Ajax 모델 간의 차이점을 비교해 보겠습니다. 또한 이 기사에서는 서버 측과 클라이언트 측에서 데이터를 처리하는 기술도 살펴봅니다.
먼저 JavaScript를 사용하여 클라이언트 측에서 요청 개체의 매개변수를 인코딩하는 방법을 알아봅니다. 소위 URL 인코딩(웹 브라우저에서 사용되는 기본 인코딩)을 사용하거나 XML 문서에 요청 매개변수를 포함할 수 있습니다. 서버는 요청을 처리하고 데이터도 인코딩되어야 하는 응답을 반환합니다. 이 기사에서는 주요 응답 데이터 형식 옵션인 JSON(JavaScript Object Notation)과 XML을 살펴봅니다.
이 기사의 대부분은 Ajax 애플리케이션에서 일반적으로 사용되는 XML 관련 API에 중점을 둘 것입니다. 클라이언트 측에서는 XML API가 매우 제한되어 있지만 충분합니다. 대부분의 경우 필요한 모든 작업은 XMLHttpRequest를 사용하여 수행할 수 있습니다. 또한 JavaScript를 사용하여 웹 브라우저에서 XML 문서를 구문 분석하고 DOM 트리를 직렬화할 수 있습니다. 서버 측에는 XML 문서 처리에 사용할 수 있는 많은 API와 프레임워크가 있습니다. 이 기사에서는 XML 스키마, XPath, DOM 및 기타 여러 표준을 지원하는 XML용 표준 Java API를 사용하여 기본 작업을 수행하는 방법을 설명합니다.
이 기사를 통해 Ajax 애플리케이션의 데이터 교환을 위한 최고의 기술과 최신 API에 대해 배울 수 있습니다. 관련된 샘플 코드는 util, model 및 Feed의 세 가지 패키지에 있습니다. util 패키지의 클래스는 XML 구문 분석, 스키마 기반 유효성 검사, XPath 기반 쿼리, DOM 직렬화 및 JSON 인코딩을 위한 메서드를 제공합니다. 모델 패키지에는 XML 문서에서 초기화한 후 JSON 형식으로 변환할 수 있는 샘플 데이터 모델이 포함되어 있습니다. 모델 디렉터리에는 XML 유효성 검사에 사용할 수 있는 스키마 예제도 있습니다. 피드 패키지의 클래스는 웹 페이지를 새로 고치기 위해 5초마다 Ajax를 통해 정보를 검색하는 데이터 피드를 시뮬레이션하는 데 사용할 수 있습니다. 이 기사에서는 처리되지 않은 Ajax 요청을 종료하고 사용이 끝나면 XMLHttpRequest 객체를 삭제하여 웹 브라우저에서 메모리 누수를 방지하는 방법을 설명합니다.
JSP 및 JavaScript 샘플은 웹 디렉토리에 포함되어 있습니다. ajaxUtil.js에는 Ajax 요청 전송, 요청 종료 및 HTTP 오류 처리를 위한 유틸리티 함수가 포함되어 있습니다. 이 파일은 또한 XML 및 URL 인코딩, XML 구문 분석 및 DOM 직렬화를 위한 JavaScript 유틸리티를 제공합니다. ajaxCtrl.jsp 파일은 Ajax 컨트롤러 역할을 하여 각 Ajax 요청을 수신하고 매개변수를 데이터 모델에 전달하거나 처리를 제공한 다음 Ajax 응답을 반환합니다. 나머지 웹 파일은 이 실용적인 방법을 사용하는 방법을 보여주는 예입니다.
웹 서버에 데이터를 보내기 위해클라이언트 측에서 요청을 구성하는
가장 간단한 방법은 요청을 쿼리 문자열로 인코딩하는 것입니다. 쿼리 문자열은 사용된 HTTP 방법에 따라 URL에 추가되거나 요청 본문에 포함될 수 있습니다. 복잡한 데이터 구조를 보내야 하는 경우 더 나은 솔루션은 정보를 XML 문서로 인코딩하는 것입니다. 이 섹션에서는 두 가지 방법을 모두 다루겠습니다.
요청 매개변수를 인코딩합니다. 기존 웹 애플리케이션을 개발할 때 사용자가 데이터를 제출하면 웹 브라우저가 자동으로 양식 데이터 인코딩을 수행하므로 양식 데이터 인코딩에 대해 걱정할 필요가 없습니다. 그러나 Ajax 애플리케이션에서는 요청 매개변수를 직접 인코딩해야 합니다. JavaScript는 URL에 포함될 수 없는 모든 문자를 %HH(여기서 HH는 16진수 코드)로 바꾸는 매우 유용한 함수 escape()를 제공합니다. 예를 들어 공백 문자는 %20으로 대체됩니다.
샘플 코드 다운로드는 배열에서 검색된 매개변수를 연결하고 각 매개변수의 이름과 값을 =로 구분하고 각 이름-값 쌍 사이에 & 문자를 배치하는 유틸리티 함수인 buildQueryString()을 제공합니다
. function buildQueryString(params) {
var 쿼리 = "";
for (var i = 0; i < params.length; i++) {
쿼리 += (i > 0 ? "&" : "")
+ escape(params[i].name) + "="
+ escape(params[i].value);
}
쿼리 반환;
}
다음 매개변수를 인코딩한다고 가정해 보겠습니다.
var someParams = [
{ 이름: "이름", 값: "John Smith" },
{ 이름: "이메일", 값: " [email protected] " },
{ 이름:"전화", 값: "(123) 456 7890" }
];
buildQueryString(someParams)을 호출하면 다음이 포함된 결과가 생성됩니다.
name=John%20Smith&[email protected]&phone=%28123%29%20456%207890
GET 메소드를 사용하려면 ? 문자 뒤의 URL에 쿼리를 추가해야 합니다. POST를 사용할 때 Content-Type 헤더는 setRequestHeader()를 통해 application/x-www-form-urlencoded로 설정되어야 하며 쿼리 문자열은 HTTP 요청을 보내는 XMLHttpRequest의 send() 메서드에 전달되어야 합니다. 섬기는 사람.
XML 문서를 만듭니다. 문자열을 사용하여 해당 속성과 데이터에서 요소를 만드는 것은 JavaScript로 XML 문서를 만드는 가장 간단한 방법입니다. 이 솔루션을 채택하는 경우 &, <, >, " 및 문자를 이스케이프하는 유틸리티 메서드가 필요합니다.
function escapeXML(content) {
if (콘텐츠 == 정의되지 않음)
반품 "";
if (!content.length || !content.charAt)
내용 = 새로운 문자열(내용);
var 결과 = "";
var 길이 = content.length;
for (var i = 0; i < 길이; i++) {
var ch = content.charAt(i);
스위치(채널) {
사례 &:
결과 += "&";
부서지다;
사례 < :
결과 += "< ";
부서지다;
케이스 >:
결과 += ">";
부서지다;
사례 ":
결과 += """;
부서지다;
사례 \:
결과 += "'";
부서지다;
기본:
결과 += ch;
}
}
결과 반환;
}
작업을 더 간단하게 만들려면 다음과 같은 몇 가지 추가 유틸리티 메서드가 필요합니다.
function attribute(name, value) {
return " " + 이름 + "="" + escapeXML(값) + """;
}
다음 예제에서는 세 가지 속성(symbol, share 및paidPrice)을 가진 객체 배열에서 XML 문서를 작성합니다.
function buildPortfolioDoc(stocks) {
var xml = "<포트폴리오>";
for (var i = 0; i < stocks.length; i++) {
var 주식 = 주식[i];
xml += "< 재고 ";
xml += attribute("symbol", stock.symbol);
xml += attribute("shares", stock.shares);
xml += attribute("paidPrice", stock.paidPrice);
xml += "";
}
xml += "< /포트폴리오>";
XML을 반환;
}
DOM 작업을 선호하는 경우 웹 브라우저의 API를 사용하여 XML을 구문 분석하고 DOM 트리를 직렬화할 수 있습니다. IE를 사용하면 새 ActiveXObject("Microsoft.XMLDOM")를 사용하여 빈 문서를 만들 수 있습니다. 그런 다음 각각 loadXML() 또는 load() 메서드를 사용하여 문자열이나 URL에서 XML을 구문 분석할 수 있습니다. IE의 경우 각 노드에는 노드와 모든 하위 노드의 XML 표현을 얻을 수 있는 xml이라는 속성이 있습니다. 따라서 XML 문자열을 구문 분석하고 DOM 트리를 수정한 다음 DOM을 다시 XML로 직렬화할 수 있습니다.
Firefox 및 Netscape 브라우저에서는 document.implementation.createDocument(...)를 사용하여 빈 문서를 만들 수 있습니다. 그런 다음 createElement(), createTextNode(), createCDATASection() 등을 사용하여 DOM 노드를 생성할 수 있습니다. Mozilla 브라우저는 DOMParser 및 XMLSerializer라는 두 가지 API도 제공합니다. DOMParser API에는parseFromStream() 및parseFromString() 메서드가 포함되어 있습니다. XMLSerializer 클래스에는 DOM 트리를 직렬화하는 해당 메서드인 serializeToStream() 및 serializeToString()이 있습니다.
다음 함수는 XML 문자열을 구문 분석하고 DOM 문서를 반환합니다
.
var 돔;
노력하다{
dom = new ActiveXObject("Microsoft.XMLDOM");
dom.async = 거짓;
dom.loadXML(xml);
} 잡기(오류) {
노력하다{
var 파서 = 새로운 DOMParser();
dom = 파서.parseFromString(xml, "text/xml");
파서 삭제;
} 잡기 (오류2) {
만약(디버그)
Alert("XML 파싱은 지원되지 않습니다.");
}
}
돔을 반환;
}
두 번째 함수는 DOM 노드와 모든 하위 노드를 직렬화하여 XML을 문자열로 반환합니다.
function serialize(dom) {
var xml = dom.xml;
if (xml == 정의되지 않음) {
노력하다{
var serializer = new XMLSerializer();
xml = serializer.serializeToString(dom);
시리얼라이저 삭제;
} 잡기(오류) {
만약(디버그)
Alert("DOM 직렬화는 지원되지 않습니다.");
}
}
XML을 반환;
}
XMLHttpRequest를 파서 또는 직렬 변환기로 사용할 수도 있습니다. Ajax 요청에 대한 응답이 서버로부터 수신되면 응답이 자동으로 구문 분석됩니다. 텍스트 버전과 DOM 트리는 각각 XMLHttpRequest의 responseText 및 responseXML 속성을 통해 액세스할 수 있습니다. 또한 DOM 트리는 send() 메서드에 전달될 때 자동으로 직렬화됩니다.
요청을 보냅니다. 이전 기사에서는 다운로드용으로 제공되는 샘플의 ajaxUtil.js 파일에서 찾을 수 있는 XMLHttpRequest API와 유틸리티 함수 sendHttpRequest()를 소개했습니다. 이 함수는 4개의 매개변수(HTTP 메소드, URL, 매개변수 배열 및 콜백)를 사용하여 XMLHttpRequest 객체를 생성하고 해당 속성을 설정하고 send() 메소드를 호출합니다. 콜백 매개변수가 제공되면 요청은 비동기적으로 전송되고 응답이 수신된 후 콜백 함수가 호출됩니다. 그렇지 않으면 요청이 동기적으로 전송되며 sendHttpRequest()가 반환되는 즉시 응답을 처리할 수 있습니다.
보시다시피 XMLHttpRequest를 사용할 때 몇 가지 중요한 선택을 해야 합니다
(GET 또는 POST).
요청 매개변수를 인코딩하는 데 사용되는 형식(XML 및 URL 인코딩은 이 문서의 앞부분에서 논의됨)
동기식(응답 대기) 또는 비동기식(콜백 사용) 호출 여부 XML, XHTML, HTML 또는 JSON(JavaScript Object Notation)과 같은 응답 형식(이 문서의 뒷부분에서 설명) 데이터 피드에서 일부 주가 정보를 얻고 사용자 개입 없이 주기적으로 정보를 새로 고치고 싶다고 가정해 보겠습니다. 이 경우 정보를 검색하는 동안 사용자 인터페이스가 차단되지 않도록 HTTP 요청을 비동기식으로 전송해야 합니다. 요청 매개변수는 URL에 인코딩될 수 있는 기호 배열입니다. 서버에 과부하가 걸릴 수 있으므로 요청이 자주 발생할 때 XML 문서를 보내고 싶지 않습니다. 최신 주가에만 관심이 있으므로 미해결된 이전 요청은 모두 종료되어야 합니다.
var ctrlURL = "ajaxCtrl.jsp";
var FeedRequest = null;
함수 sendInfoRequest(기호, 콜백) {
if(피드요청)
abortRequest(feedRequest);
var params = 새로운 배열();
for(var i = 0; i < 기호.길이; i++)
매개변수[i] = {
이름 : "기호",
값:기호[i]
};
FeedRequest = sendHttpRequest(
"GET", ctrlURL, 매개변수, 콜백);
}
요청 객체의 abort() 메서드를 호출하기 전에 abortRequest() 함수(ajaxUtil.js 파일에 있음)는 onreadystatechange 속성을 아무 작업도 하지 않는 콜백으로 설정합니다. 또한 메모리 누수를 방지하려면 요청 객체를 삭제하는 것이 중요합니다.
function abortRequest(request) {
함수 doNothing() {
}
request.onreadystatechange = doNothing;
요청.중단();
피드요청 삭제;
}
또 다른 경우를 생각해 봅시다. 전체 사용자 데이터를 데이터베이스에 저장할 때 요청은 동기적으로 전송되어야 합니다. 왜냐하면 이 데이터를 저장하는 동안 사용자가 요청을 수정하는 것을 원하지 않을 것이기 때문입니다. 이 경우 많은 문자열 매개 변수를 사용하는 것보다 문서에서 개체 모델을 인코딩하는 것이 더 간단하기 때문에 XML 형식이 선호됩니다. 또한 데이터 저장 요청이 자주 발생하지 않으며 서버가 문제 없이 로드를 처리합니다. XML 문서는 EL 구문(${param.xml})을 사용하여 JSP 페이지에서 액세스할 수 있도록 매개변수로 인코딩될 수 있습니다. 다음은 XML 문서로 인코딩된 모델 데이터를 보내는 함수입니다.
function sendSaveRequest(xml) {
var params = [ { 이름:"xml", 값:xml } ];
var saveRequest = sendHttpRequest("POST", ctrlURL, params);
if(저장요청)
saveRequest 삭제;
}
개체 모델을 복원해야 하는 경우 동기적으로 요청을 보내 서버에서 데이터를 검색할 수도 있습니다. 이 경우 서버는 eval(loadRequest.responseText)를 사용하여 JavaScript 객체 트리로 쉽게 변환할 수 있도록 JSON 응답을 반환해야 합니다.
function sendLoadRequest() {
var 모델 = null;
var loadRequest = sendHttpRequest("GET", ctrlURL);
if (로드요청) {
모델 = eval(loadRequest.responseText);
로드요청 삭제;
}
반품 모델;
}
다음 두 섹션에서는 서버의 XML 문서에서 일반적으로 수행되는 작업과 Ajax 요청에 응답하는 방법을 설명합니다.
서버 측에서 요청 처리
Servlet/JSP 컨테이너는 각 HTTP 요청을 분석하고 ServletRequest 인스턴스를 생성합니다. 이를 통해 getParameter() / getParameterValues()를 통해 요청 매개변수를 가져오거나 getInputStream()을 통해 요청 본문을 가져올 수 있습니다. JSP 페이지에서는 EL 구문(${param...} 및 ${paramValues...})을 사용하여 이러한 매개변수를 얻을 수도 있습니다. getParameter 전달은 Ajax 클라이언트가 buildQueryString()과 같은 유틸리티 함수를 사용하여 데이터를 application/x-www-form-urlencoded 형식(이 기사의 이전 섹션에서 설명)() 또는 $로 인코딩하는 경우에만 가능합니다. {param...} 요청 매개변수를 가져옵니다. 클라이언트 측 XMLHttpRequest의 send() 메소드에 XML 문서나 DOM 트리를 전달하는 경우, 서버 측에서는 ServletRequest의 getInputStream() 메소드를 사용해야 합니다.
데이터 검증. 일반적인 웹 애플리케이션은 많은 데이터 유효성 검사 작업을 수행합니다. 발생할 수 있는 대부분의 오류는 요청 매개변수 누락, 잘못된 숫자 형식 등과 같이 매우 간단합니다. 이러한 오류는 일반적으로 사용자가 양식 요소에 대한 값을 입력하는 것을 잊었거나 잘못된 값을 제공함으로써 발생합니다. JSF 및 Oracle ADF Faces와 같은 웹 프레임워크는 이러한 사용자 오류를 처리하는 데 매우 능숙합니다. Ajax 애플리케이션에서는 JavaScript를 사용하여 클라이언트 측에서 이러한 오류를 포착하고 처리할 수 있습니다. 예를 들어 isNaN(new Number(value))을 사용하여 숫자 값이 유효하지 않은지 확인할 수 있습니다.
보안 및 안정성상의 이유로 데이터는 서버 측에서 다시 검증되어야 하며 XML 요청의 형식이 올바른 것으로 가정해서는 안 됩니다. XML 스키마는 서버 측에서 복잡한 요청의 유효성을 검사하는 데 유용한 도구입니다. 샘플 코드 다운로드에는 스키마 문서를 로드하고 사용하기 위한 메서드를 제공하는 XMLUtil이라는 클래스가 포함되어 있습니다. 다음 코드 조각은 SchemaFactory를 초기화하는 방법을 보여줍니다.
import javax.xml.*;
import javax.xml.validation.*;
...
보호된 정적 SchemaFactory 스키마Factory;
정적 {
스키마Factory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
SchemaFactory.setErrorHandler(newErrorHandler());
}
newErrorHandler() 메서드는 SAX 오류 처리기를 반환합니다.
import org.xml.sax.*;
...
공개 정적 ErrorHandler newErrorHandler() {
새로운 ErrorHandler() 반환 {
공개 무효 경고(SAXParseException e)
SAXException 발생 {
Logger.global.warning(e.getMessage());
}
공개 무효 오류(SAXParseException e)
SAXException 발생 {
전자를 던져;
}
공개 무효 fatalError(SAXParseException e)
SAXException 발생 {
전자를 던져;
}
};
}
getResourceAsStream()을 사용하여 디렉토리 또는 CLASSPATH에 지정된 JAR에서 XSD 파일을 찾고 로드할 수 있습니다.
public static InputStream getResourceAsStream(String name)
IOException이 발생합니다.
InputStream in = XMLUtil.class.getResourceAsStream(이름);
if (== null)
새로운 FileNotFoundException(이름)을 던져라;
돌아오다;
}
그런 다음 SchemaFactory 인스턴스를 사용하여 newSchema() 메서드를 통해 Schema 객체를 가져옵니다.
import javax.xml.validation.*;
...
공개 정적 스키마 newSchema(문자열 이름)
IOException, SAXException 발생 {
스키마 스키마;
InputStream in = getResourceAsStream(이름);
노력하다{
스키마 = SchemaFactory.newSchema(새 StreamSource(in));
}마지막으로{
넣다();
}
반환 스키마;
}
다음을 사용하여 Oracle XMLSchema 객체를 생성할 수도 있습니다.
import oracle.xml.parser.schema.XMLSchema;
oracle.xml.parser.schema.XSDBuilder 가져오기;
...
공개 정적 XMLSchema newOracleSchema(문자열 이름)
IOException, SAXException 발생 {
XMLSchema 스키마;
InputStream in = getResourceAsStream(이름);
노력하다{
XSDBuilder 빌더 = 새 XSDBuilder();
스키마 = builder.build(new InputSource(in));
} 잡기(예외 e){
새로운 SAXException(e)을 던져라;
}마지막으로{
넣다();
}
반환 스키마;
}
다음으로 DocumentBuilderFactory를 만들어야 합니다. JAXP 1.1 구현이 CLASSPATH에 있는 경우 JAXP 1.2에 의해 정의된 setSchema() 메소드는 UnsupportedOperationException을 발생시킬 수 있으며, 이 경우 JAXP 1.1 구현은 Java SE 5.0의 JAXP 1.2 구현으로 대체되어야 합니다. 이 경우에도 newOracleSchema()를 사용하여 스키마 객체를 생성하고 setAttribute() 메소드를 통해 설정할 수 있습니다.
import javax.xml.parsers.*;
import oracle.xml.jaxp.JXDocumentBuilderFactory;
...
공개 정적 DocumentBuilderFactory newParserFactory(
문자열 SchemaName)은 IOException, SAXException을 발생시킵니다.
DocumentBuilderFactory 파서Factory
= DocumentBuilderFactory.newInstance();
노력하다{
parserFactory.setSchema(newSchema(schemaName));
} catch(UnsupportedOperationException e) {
if (JXDocumentBuilderFactory의 파서 팩토리 인스턴스) {
파서Factory.setAttribute(
JXDocumentBuilderFactory.SCHEMA_OBJECT,
newOracleSchema(스키마이름));
}
}
파서팩토리를 반환합니다;
}
그런 다음 DocumentBuilder 객체를 생성하고 이를 사용하여 XML 문서의 유효성을 검사하고 구문 분석합니다.
import javax.xml.parsers.*;
...
공개 정적 DocumentBuilder newParser(
DocumentBuilderFactory 파서Factory)
ParserConfigurationException이 발생합니다.
DocumentBuilder 파서 = parserFactory.newDocumentBuilder();
파서.setErrorHandler(newErrorHandler());
파서를 반환합니다.
};
Portfolio.xsd 스키마 예에 대해 XML 문서의 유효성을 검사한다고 가정합니다.
< xsd:schema xmlns:xsd=" http://www.w3.org/2001/XMLSchema ">
< xsd:element name="portfolio" type ="portfolioType "
< xsd:complexType name="portfolioType">
<xsd:순서>
< xsd:요소 이름="재고"
minOccurs="0" maxOccurs="무제한">
<xsd:복합 유형>
< xsd:속성 이름="기호"
type="xsd:string" use="필수"/>
< xsd:속성 이름="공유"
유형="xsd:긍정적 정수" 사용="필수"/>
< xsd:속성 이름="paidPrice"
type="xsd:decimal" use="필수"/>
< /xsd:복합 유형>
< /xsd:요소>
< /xsd:순서>
< /xsd:복합 유형>
< /xsd:스키마>
DataModel 클래스의 parsePortfolioDoc() 메소드는 XMLUtil을 사용하여 xml 매개변수를 검증 및 구문 분석하고 DOM 문서를 반환합니다.
private static final String SCHEMA_NAME
= "/ajaxapp/model/portfolio.xsd";
개인 정적 DocumentBuilderFactory 파서Factory;
개인 정적 문서 파싱PortfolioDoc(String xml)
IOException, SAXException이 발생합니다.
ParserConfigurationException {
동기화됨(DataModel.class) {
if (parserFactory == null)
parserFactory = XMLUtil.newParserFactory(SCHEMA_NAME);
}
DocumentBuilder 파서 = XMLUtil.newParser(parserFactory);
InputSource in = new InputSource(new StringReader(xml));
return 파서.parse(in);
}
이제 DOM 트리가 있으므로 DOM 노드를 형성하는 데 필요한 데이터를 가져와야 합니다.
필요한 정보를 추출합니다. DOM API 또는 쿼리 언어(예: XQuery 또는 XPath)를 사용하여 DOM 트리를 탐색할 수 있습니다. Java는 나중에 사용될 XPath용 표준 API를 제공합니다. XMLUtil 클래스는 newXPath() 메서드를 사용하여 XPathFactory를 만듭니다.
import javax.xml.xpath.*;
...
보호된 정적 XPathFactory xpathFactory;
정적 {
xpathFactory = XPathFactory.newInstance();
}
공개 정적 XPath newXPath() {
xpathFactory.newXPath()를 반환합니다.
}
다음 메소드는 지정된 컨텍스트에서 XPath 표현식을 평가하고 결과 값을 반환합니다.
import javax.xml.xpath.*;
org.w3c.dom.* 가져오기;
...
공개 정적 문자열 evalToString(문자열 표현식,
개체 컨텍스트)에서 XPathExpressionException이 발생합니다.
return(문자열) newXPath().evaluate(표현식, 컨텍스트,
XPathConstants.STRING);
}
공개 정적 부울 evalToBoolean(문자열 표현식,
개체 컨텍스트)에서 XPathExpressionException이 발생합니다.
return ((Boolean) newXPath().evaluate(표현식, 컨텍스트,
XPathConstants.BOOLEAN)).booleanValue();
}
public static double evalToNumber(문자열 표현식,
개체 컨텍스트)에서 XPathExpressionException이 발생합니다.
return ((Double) newXPath().evaluate(표현식, 컨텍스트,
XPathConstants.NUMBER)).doubleValue();
}
공개 정적 노드 evalToNode(문자열 표현식,
개체 컨텍스트)에서 XPathExpressionException이 발생합니다.
return (노드) newXPath().evaluate(표현식, 컨텍스트,
XPathConstants.NODE);
}
공개 정적 NodeList evalToNodeList(문자열 표현식,
개체 컨텍스트)에서 XPathExpressionException이 발생합니다.
return (NodeList) newXPath().evaluate(표현식, 컨텍스트,
XPathConstants.NODESET);
}
DataModel의 setData() 메서드는 XPath 솔버 메서드를 사용하여 결합된 XML 문서에서 정보를 추출합니다.
public synced void setData(String xml)
IOException, SAXException이 발생합니다.
파서 구성예외,
XPathExpressionException {
노력하다{
배열 목록 재고 목록
= 새로운 ArrayList();
문서 문서 = parsPortfolioDoc(xml);
NodeList nodeList = XMLUtil.evalToNodeList(
"/포트폴리오/재고", 문서);
for (int i = 0; i < nodeList.getLength(); i++) {
노드 node = nodeList.item(i);
StockBean 재고 = 새로운 StockBean();
stock.setSymbol(
XMLUtil.evalToString("@symbol", node));
stock.setShares(
(int) XMLUtil.evalToNumber("@shares", node));
stock.setPaidPrice(
XMLUtil.evalToNumber("@paidPrice", node));
stockList.add(재고);
}
this.stockList = 재고목록;
} 잡기(예외 e){
Logger.global.logp(Level.SEVERE, "DataModel", "setData",
e.getMessage(), e);
}
}
서버 측 데이터 모델에서 데이터를 사용할 수 있게 되면 애플리케이션의 요구 사항에 따라 처리할 수 있습니다. 그런 다음 Ajax 요청에 응답해야 합니다.
서버측에서 응답 생성
Ajax 요청에 대한 응답으로 HTML을 반환하는 것이 가장 간단한 솔루션입니다. 왜냐하면 JSP 구문을 사용하여 마크업을 구축할 수 있고 Ajax 클라이언트는 단순히 <div> 또는 <span> 요소를 사용하기 때문입니다. innerHTML 속성은 HTML을 삽입합니다. 페이지 어딘가에. 그러나 프레젠테이션 마크업 없이 Ajax 클라이언트에 데이터를 반환하는 것이 더 효율적입니다. XML 형식이나 JSON을 사용할 수 있습니다.
XML 응답을 생성합니다. Java EE는 JSP를 통해 생성되거나 JAXB를 통해 객체 트리에서 생성되거나 javax.xml.transform을 사용하여 생성되는 XML 문서 생성을 위한 다양한 옵션을 제공합니다. 다음 예의 변환기는 DOM 트리를 직렬화합니다.
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
...
공개 정적 TransformerFactory serializerFctory;
정적 {
serializerFctory = TransformerFactory.newInstance();
}
공개 정적 무효 직렬화(노드 노드, OutputStream 출력)
TransformerException이 발생합니다.
변환기 직렬 변환기 = serializerFctory.newTransformer();
속성 serializerProps = 새 속성();
serializerProps.put(OutputKeys.METHOD, "xml");
serializer.setOutputProperties(serializerProps);
소스 소스 = new DOMSource(node);
결과 결과 = new StreamResult(out);
serializer.transform(소스, 결과);
}
서버 측에서 XML을 생성하기 위한 표준 옵션과 개발 소스 프레임워크가 너무 많아서 자신에게 맞는 것을 선택하기만 하면 됩니다. 그러나 클라이언트에서는 XML이 DOM을 통해서만 구문 분석될 수 있으므로 상황이 매우 다릅니다. 일부 브라우저는 XPath 및 XSLT도 지원합니다.
이전 Ajax 기사에서는 JSP를 통해 XML을 생성한 다음 JavaScript와 DOM을 사용하여 클라이언트에서 이를 구문 분석하는 방법을 배웠습니다. 또 다른 해결책은 Ajax 요청에 응답하기 위한 데이터 형식으로 XML 대신 JSON을 사용하는 것입니다. 앞서 언급했듯이 JSON 문자열은 eval() 함수를 사용하여 JavaScript 개체 트리로 변환될 수 있습니다. 이는 JavaScript를 사용하여 DOM 트리에서 정보를 추출하는 것보다 간단합니다. 필요한 것은 서버 측에서 JSON을 생성하는 좋은 유틸리티 클래스뿐입니다.
JSON 인코딩. JSONEncoder 클래스는 리터럴, 객체 및 배열을 인코딩하기 위한 메서드를 제공합니다. 결과는 java.lang.StringBuilder에 저장됩니다.
package ajaxapp.util
public class JSONEncoder {
개인 StringBuilder buf;
공개 JSONEncoder() {
buf = 새로운 StringBuilder();
}
...
}
Character() 메소드는 단일 문자를 인코딩합니다.
public void Character(char ch) {
스위치(채널) {
사례 \:
사례 \":
사례 \ :
buf.append( \\ );
buf.append(ch);
부서지다;
사례 :
buf.append( \\ );
buf.append( );
부서지다;
사례
:
buf.append( \\ );
buf.추가(
);
부서지다;
사례
:
buf.append( \\ );
buf.추가(
);
부서지다;
기본:
if (ch >= 32 && ch < 128)
buf.append(ch);
또 다른{
buf.append( \\ );
buf.append(u);
for (int j = 12; j >= 0; j-=4) {
int k = (((int) ch) >> j) & 0x0f;
int c = k < 10 ? + k :a + k - 10;
buf.append((char) c);
}
}
}
}
string() 메소드는 전체 문자열을 인코딩합니다.
public void string(String str) {
int 길이 = str.length();
for (int i = 0; i < 길이; i++)
문자(str.charAt(i));
}
literal() 메서드는 JavaScript 리터럴을 인코딩합니다.
public void literal(Object value) {
if (문자열 값 인스턴스) {
buf.append(");
string((문자열) 값);
buf.append(");
} else if (문자 인스턴스 값) {
buf.append(\);
Character(((문자) 값).charValue());
buf.append(\);
} 또 다른
buf.append(value.toString());
}
comma() 메소드는 쉼표 문자를 추가합니다:
private void comma() {
buf.append(,);
}
deleteLastComma() 메소드는 버퍼 끝에 있는 마지막 쉼표 문자(있는 경우)를 제거합니다.
private void deleteLastComma() {
if (buf.length() > 0)
if (buf.charAt(buf.length()-1) == ,)
buf.deleteCharAt(buf.length()-1);
}
startObject() 메소드는 JavaScript 객체의 시작을 나타내기 위해 { 문자를 추가합니다:
public void startObject() {
buf.append({);
}
property() 메소드는 JavaScript 속성을 인코딩합니다.
public void property(String name, Object value) {
buf.append(이름);
buf.append(:);
리터럴(값);
콤마();
}
endObject() 메소드는 } 문자를 추가하여 JavaScript 객체의 끝을 나타냅니다.
public void endObject() {
deleteLastComma();
buf.append(});
콤마();
}
startArray() 메서드는 JavaScript 배열의 시작을 나타내기 위해 [ 문자를 추가합니다.
public void startArray() {
buf.append([);
}
element() 메소드는 JavaScript 배열의 요소를 인코딩합니다.
public void element(Object value) {
리터럴(값);
콤마();
}
endArray() 메서드는 ] 문자를 추가하여 JavaScript 배열의 끝을 나타냅니다.
public void endArray() {
deleteLastComma();
buf.append(]);
콤마();
}
toString() 메서드는 JSON 문자열을 반환합니다.
public String toString() {
deleteLastComma();
buf.toString()을 반환합니다.
}
Clear() 메소드는 버퍼를 지웁니다.
public voidclear() {
buf.setLength(0);
}
DataModel은 JSONEncoder 클래스를 사용하여 유지 관리하는 데이터를 인코딩합니다.
publicsynchronous String getData() {
JSONEncoder json = 새로운 JSONEncoder();
json.startArray();
for (int i = 0; i < stockList.size(); i++) {
StockBean 재고 = stockList.get(i);
json.startObject();
json.property("symbol", stock.getSymbol());
json.property("shares", stock.getShares());
json.property("paidPrice", stock.getPaidPrice());
json.endObject();
}
json.endArray();
json.toString()을 반환합니다.
}
xml 요청 매개변수가 제공되면 ajaxCtrl.jsp 페이지가 모델의 데이터를 설정합니다. 그렇지 않으면 페이지는 ${dataModel.data} EL 표현식을 사용하여 getData()에서 반환된 JSON 문자열을 출력합니다.
< %@ taglib prefix="c" uri=" http://java.sun.com/jsp/ jstl /core " %>
...
< jsp:useBean id="dataModel" 범위="세션"
class="ajaxapp.model.DataModel" />
< c:선택>
...
< c:when test="${!empty param.xml}">
< c:set target="${dataModel}"
속성="데이터"
value="${param.xml}" />
< /c:언제>
<c:그렇지 않으면>
${dataModel.data}
< /c:그렇지 않으면>
< /c:선택>
Ajax 클라이언트가 JSON 데이터를 처리해야 하므로 이 작업은 완료되지 않았습니다.
클라이언트 측에서 응답 처리
일반적인 웹 애플리케이션에서는 JSP, 웹 프레임워크 및 태그 라이브러리를 사용하여 서버 측에서 컨텐츠를 생성합니다. JavaServer Faces 및 Oracle ADF Faces와 같은 웹 프레임워크는 Ajax 애플리케이션 구축에 매우 유용하기 때문에 Ajax 애플리케이션은 이러한 상황에 이상적입니다. 그러나 Ajax 애플리케이션과 Ajax가 아닌 애플리케이션 간에는 여전히 상당한 차이가 있습니다. Ajax를 사용하는 경우 클라이언트 측에서 데이터를 처리하고 JavaScript를 사용하여 동적으로 콘텐츠를 생성하여 사용자에게 데이터를 제공해야 합니다.
데이터 변환을 위해 JSON 형식을 사용하는 경우 JavaScript에서 제공하는 eval() 함수를 사용하면 텍스트를 개체 트리로 변환하는 것이 매우 쉽습니다. XML을 사용하려는 경우 수행해야 할 다른 작업이 많이 있지만 이 형식에는 고유한 장점도 있습니다. 예를 들어 XML은 다양한 유형의 클라이언트에서 사용할 수 있는 반면 JSON은 JavaScript 환경에서만 구문 분석하기 쉽습니다. 또한 XML을 사용하면 오류를 더 빨리 찾아 수정할 수 있으므로 디버깅 시간이 단축됩니다.
JavaScript를 사용하여 DOM 트리에 액세스합니다. JavaScript의 DOM API는 Java의 org.w3c.dom 패키지와 매우 유사합니다. 주요 차이점은 속성에 대한 액세스입니다. JavaScript에서는 속성에 직접 액세스할 수 있지만 Java에서는 속성을 비공개로 처리하므로 get 및 set 메서드를 통해 속성에 액세스해야 합니다. 예를 들어, dom.documentElement를 통해 문서의 루트 요소를 얻을 수 있습니다.
DOM은 구문 분석된 문서의 구조에 대한 액세스를 제공하는 저수준 API입니다. 예를 들어 대부분의 경우 주석을 무시하고 텍스트 노드가 인접하지 않도록 할 수 있습니다. 다음의 간단한 예를 고려해 보십시오:
var xml = "< element>da< !--comment-->ta&"
+ "< ![CDATA[cdata< /요소>";
앞서 소개한 유틸리티 함수를 사용하여 위의 XML 문자열을 구문 분석할 수 있습니다.
var dom = pars(xml);
ajaxUtil.js에서 구문 분석() 함수에 대한 코드를 찾을 수 있습니다. 이 경우 함수는 루트 요소에 텍스트 노드, 주석, 다른 텍스트 노드 및 문자 데이터 노드가 포함된 DOM 트리를 반환합니다. 주석 없이 텍스트를 포함하려면 요소의 하위 요소를 반복하여 텍스트 및 문자 데이터 노드(각각 유형 3과 4가 있음)의 값을 연결해야 합니다.
var element = dom.documentElement;
var childNodes = element.childNodes;
var 텍스트 = "";
for(var i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeValue) {
var type = childNodes[i].nodeType;
if (유형 == 3 || 유형 == 4)
텍스트 += childNodes[i].nodeValue;
}
DOM으로 작업할 때 이러한 하위 수준 세부 사항을 다루지 않도록 작은 유틸리티 함수 세트를 구축해야 합니다.
JavaScript를 사용하여 동적 콘텐츠를 생성합니다. 웹 브라우저를 사용하면 문서 개체를 통해 웹 페이지의 DOM 구조에 액세스할 수 있습니다. 예를 들어 document.getElementById(...)를 사용하면 요소를 매우 쉽게 찾을 수 있습니다. 기존 문서에 삽입할 수 있는 새 요소와 텍스트 노드를 만들 수도 있습니다. 그러나 아래와 같이 문자열을 연결하여 HTML을 작성하는 것이 더 간단합니다.
function updateInfo(request) {
var share = eval(request.responseText);
var table = "< 테이블 테두리=1 cellpadding=5>";
테이블 += "<tr>";
테이블 += "< th>기호< /th>";
table += "< th>추세< /th>";
table += "< th>마지막 가격< /th>";
테이블 += "< /tr>";
for (var i = 0; i < share.length; i++) {
var 공유 = 공유[i];
var 기호 = escapeXML(share.symbol)
var trend = share.trend > 0 "+" : "-";
var lastPrice = new Number(share.lastPrice).toFixed(2);
테이블 += "<tr>";
테이블 += "< td>" + 기호 + "< /td>";
테이블 += "< td>" + 추세 + "< /td>";
테이블 += "< td>" + lastPrice + "< /td>";
테이블 += "< /tr>";
}
테이블 += "< /테이블>";
document.getElementById("table").innerHTML = 테이블;
}
생성된 HTML은
getElementById()에서 반환된 객체의 innerHTML 속성을 설정하여 빈 요소에 삽입할 수 있습니다. 예:
<div id="table">
< /div>
이 기사의 예제는 ajaxLogic.js 파일의 sendInforequest를 통해 서버로 전송 된 ajax 요청에 대한 응답을 처리하기위한 updateInfo () 함수를 콜백으로 사용합니다. 5 초마다 정보를 업데이트하려면 JavaScript의 setInterVal () 함수를 사용할 수 있습니다.
var symbols = [...];
setInterval ( "sendInforequest (symbols, updateInfo)", 5000);
DataFeed라는 클래스는 서버 측 피드를 시뮬레이션합니다. ajaxctrl.jsp 페이지는 피드의 getData () 메소드를 호출하여 응답을 JSON 문자열로 반환합니다. 클라이언트 측에서 updateInfo () 함수는 이전 코드 예제에 표시된대로 Eval (request.ResponsETXT)을 사용하여 JSON 문자열을 구문 분석합니다.