자바 원본 코드 완성 pdf 온라인 미리 보기 및 pdf 인쇄 및 다운로드
1.프로젝트 에 최소한 도입 해 야 할 jar 패키지,버 전 주의:
a) core-renderer.jar
b) freemarker-2.3.16.jar
c) iText-2.0.8.jar
d) iTextAsian.jar
상위 코드:
설명:사용자 정의 태그 류 의 기본 클래스 입 니 다.action 에서 데 이 터 를 어떻게 넣 는 지,ftl 에서 데 이 터 를 어떻게 찾 는 지 간단명료 합 니 다.
1.태그 클래스 의 기본 클래스 사용자 정의
/**
* pdf html
*
* @author xg
*
*/
public abstract class PDFTag extends BodyTagSupport {
private static final long serialVersionUID = 1L;
//
private String json = "";
private String tempDir = "";
//
private Map<String, Object> rootMap = new HashMap<String, Object>();
private String templateStr = null;
private String freemarkereConfigurationBeanName = null;
private String fileName = null;
private String basePath = null;
private String fileEncoding = "utf-8";
@Override
public int doStartTag() throws JspException {
setConfigParams();
WebApplicationContext application = WebApplicationContextUtils.getWebApplicationContext(pageContext
.getServletContext());
doServiceStart();
String ctx = (String) pageContext.getAttribute("ctx");
rootMap.put("ctx", ctx);
Map<String, Object> map = parseJSON2Map(json);
rootMap.putAll(map);
if (freemarkereConfigurationBeanName == null) {
try {
throw new CstuException("FreemarkereConfigurationBeanName !");
} catch (CstuException e) {
e.printStackTrace();
}
}
Configuration cptFreemarkereConfiguration = (Configuration) application
.getBean(freemarkereConfigurationBeanName);
try {
if (templateStr == null) {
throw new CstuException(" !");
}
Template template = cptFreemarkereConfiguration.getTemplate(templateStr);
if (basePath == null) {
throw new CstuException(" ( ) !");
}
File htmlPath = new File(tempDir + File.separator + basePath);
if (!htmlPath.exists()) {
htmlPath.mkdirs();
}
if (fileName == null) {
throw new CstuException(" html !");
}
File htmlFile = new File(htmlPath, File.separator + fileName);
if (!htmlFile.exists()) {
htmlFile.createNewFile();
}
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(htmlFile), fileEncoding));
template.process(rootMap, out);
out.flush();
doServiceDoing();
//
template.process(rootMap, pageContext.getResponse().getWriter());
} catch (Exception e) {
e.printStackTrace();
}
doServiceEnd();
return SKIP_BODY;
}
/**
* ,
*/
public abstract void setConfigParams();
/**
* -
*
* @return
*/
public abstract void doServiceStart();
/**
* - , , rootMap
*
* @return
*/
public abstract void doServiceDoing();
/**
* - rootMap ,
*
* @return
*/
public abstract void doServiceEnd();
/**
* rootMap
*/
public void putKV(String key, Object value) {
rootMap.put(key, value);
}
/**
* map rootMap
*
* @param m
*/
public void putMap(Map m) {
rootMap.putAll(m);
}
public void clear() {
rootMap.clear();
rootMap = null;
}
/**
*
*
* @param key
* @return
*/
public Object remove(String key) {
return rootMap.remove(key);
}
public static Map<String, Object> parseJSON2Map(String jsonStr) {
Map<String, Object> map = new HashMap<String, Object>();
JSONObject json = JSONObject.fromObject(jsonStr);
for (Object k : json.keySet()) {
Object v = json.get(k);
if (v instanceof JSONArray) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Iterator<JSONObject> it = ((JSONArray) v).iterator();
while (it.hasNext()) {
JSONObject json2 = it.next();
list.add(parseJSON2Map(json2.toString()));
}
map.put(k.toString(), list);
} else {
map.put(k.toString(), v);
}
}
return map;
}
public String getJson() {
return json;
}
public void setJson(String json) {
this.json = json;
}
public String getTempDir() {
return tempDir;
}
public void setTempDir(String tempDir) {
this.tempDir = tempDir;
}
public String getTemplateStr() {
return templateStr;
}
public void setTemplateStr(String templateStr) {
this.templateStr = templateStr;
}
public String getFreemarkereConfigurationBeanName() {
return freemarkereConfigurationBeanName;
}
public void setFreemarkereConfigurationBeanName(String freemarkereConfigurationBeanName) {
this.freemarkereConfigurationBeanName = freemarkereConfigurationBeanName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getBasePath() {
return basePath;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public String getFileEncoding() {
return fileEncoding;
}
public void setFileEncoding(String fileEncoding) {
this.fileEncoding = fileEncoding;
}
}
설명:setConfigParams 방법 은 인터페이스 가 정의 하 는 설정 매개 변 수 를 호출 하 는 방법 입 니 다.예 를 들 어 templateSt,basePath 등,doServiceStart,doServiceDoing 과 doServiceEnd 등 방법 은 업무 논 리 를 처리 하 는 데 사 용 됩 니 다.예 를 들 어 제 수 요 는 계약 을 한 페이지 에 표시 하고 페이지 를 나 누 려 면 워 터 마크 를 추가 해 야 하지만 생 성 된 pdf 스타일 은 미리 보 는 것 과 다 릅 니 다.그래서 저 는 doServiceDoing 에 rootMap 에 판단 조건 을 추가 하면 flt 파일 하나 에 두 가지 효 과 를 낼 수 있 습 니 다(미리 보기 와 인쇄).물론 미리 보기 와 인쇄 가 똑 같은 효 과 를 원한 다 면 doServiceDoing 방법 은 비어 있 을 수 있 습 니 다.이 네 가지 방법 을 총괄 해 보면 다음 과 같다.1.setConfigParams:설정 매개 변수
2.doServiceStart:데이터/조건 채 우기
3.doServiceDoing:데이터/조건 을 채 우 고 여 기 는 경계선 입 니 다.이 방법 전에 rootMap 데 이 터 는 html 에 들 어가 서 브 라 우 저(미리 보기)에 들 어 갑 니 다.이 방법 을 사용 한 후에 rootMap 데 이 터 는 html 파일 에 다시 들 어가 서 끝 납 니 다.따라서 판단 을 쓸 수 있 습 니 다.
4.doServiceEnd:있 으 나 마 나 저 는 적 었 습 니 다.만약 에 어느 날 데이터 세트 가 너무 크 면 여기 서 데 이 터 를 다 채 운 후에 정리 하고 메모리 공간 을 절약 할 수 있 습 니 다.
2.PDFTag 의 하위 클래스
/**
* PDFTag
*
* @author xg
*
*/
public class ViewPDFTag extends PDFTag {
private static final long serialVersionUID = 4528567203497016087L;
private String prjNature = "";
private String bookName = "";
private String prjCode = "";
/**
*
*/
public PDFConfigurationInterface pDFConfigurationInterface = new PDFConfigurationInterface() {
@Override
public void configTemplateStr() {
// ,
if (prjNature.equalsIgnoreCase("2") || prjNature.equalsIgnoreCase("1")) {
setTemplateStr("wj-project-print.ftl");
}
}
@Override
public void configFreemarkereConfigurationBeanName() {
setFreemarkereConfigurationBeanName("cptFreemarkereConfiguration");
}
@Override
public void configFileName() {
// html
setFileName(prjCode + ".html");
}
@Override
public void configFileEncoding() {
// utf-8
}
@Override
public void configBasePath() {
setBasePath("html_pdf");
}
};
@Override
public void doServiceStart() {
putKV("prjNature", prjNature);
putKV("bookName", bookName);
putKV("flag", "0");
}
@Override
public void doServiceDoing() {
putKV("flag", "1");
}
@Override
public void doServiceEnd() {
clear();
System.gc();
}
public String getPrjNature() {
return prjNature;
}
public void setPrjNature(String prjNature) {
this.prjNature = prjNature;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getPrjCode() {
return prjCode;
}
public void setPrjCode(String prjCode) {
this.prjCode = prjCode;
}
@Override
public void setConfigParams() {
pDFConfigurationInterface.configTemplateStr(); pDFConfigurationInterface.configFreemarkereConfigurationBeanName();
pDFConfigurationInterface.configFileName();
pDFConfigurationInterface.configBasePath();
pDFConfigurationInterface.configFileEncoding();
}
}
설명:PDFConfigurationInterface 는 사용자 정의 탭 매개 변수 설정 인터페이스 입 니 다.하위 클래스 는 이 인터페이스의 구현 클래스 의 구성원 변 수 를 정의 하거나 구성원 변수 내부 클래스 를 정의 하고 setConfigParams 방법 에서 호출 해 야 합 니 다.하위 클래스 의 구성원 변 수 는 td 파일 에 설 정 된 속성 을 받 습 니 다.
3.사용자 정의 탭 매개 변수 설정 인터페이스
/**
* PdfTag
*
* @author xg
*
*/
public interface PDFConfigurationInterface {
/**
*
*/
void configTemplateStr();
/**
* FreemarkereConfigurationBean
*/
void configFreemarkereConfigurationBeanName();
/**
* html
*/
void configFileName();
/**
* html ( )
*/
void configBasePath();
/**
* , utf-8
*/
void configFileEncoding();
}
4.사용자 정의 이상 클래스
/**
*
*
* @author Administrator
*
*/
public class CstuException extends Exception {
private static final long serialVersionUID = 4266461814747405870L;
public CstuException(String msg) {
super(msg);
}
}
5.tld 파일 설정
<tag>
<name>print</name> <tagclass>com.iris.taglib.web.PreviewPDFTag</tagclass>
<bodycontent>JSP</bodycontent>
<attribute>
<name>json</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>prjNature</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>bookName</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>tempDir</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>prjCode</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
6. action
/**
* PDF
*
*/
@Namespace("/export")
@Results({ @Result(name = "exceltemplate", location = "/WEB-INF/content/pdf/export-pdf.jsp"),
@Result(name = "exprotPdf2", location = "/WEB-INF/content/project/project/export/export-pdf2.jsp") })
public class ExportPdfAction extends ActionSupport {
private static final long serialVersionUID = -5454188364706173477L;
@Value("${tempDir}")
private String tempDir;
@Value("${pdfFont}")
private String pdfFont;
@Value("${staticResRootDir}")
private String staticResRootDir;
@Value("${staticResRootDir2}")
private String staticResRootDir2;
@Value("${WaterMarkImgDir}")
private String waterMarkImgDir;
@Autowired
private ProjectService projectService;
@Autowired
private PersonService personService;
@Autowired
private ConstDictionaryService constDictionaryService;
@Autowired
private FdPlanDetailService fdPlanDetailService;
@Autowired
private ServiceFactory serviceFactory;
@Action("exprotPdf2")
public String exprotPdf2() {
String prjCode = Struts2Utils.getParameter("prjCode");
prjCode = Struts2Utils.decodeDesString(prjCode);
Project project = projectService.getProjectById(Long.parseLong(prjCode));
Map<String, String> baseInfo = new HashMap<String, String>();
baseInfo.put("tempDir", tempDir);
//
baseInfo.put("prjCode", prjCode);
//
String prjNature = project.getPrjNature();
baseInfo.put("prjNature", prjNature);
// :watermark+"-"+prjNature
baseInfo.put("waterMarkImg", waterMarkImgDir + File.separator + "watermark-" + prjNature + ".png");
//
Person person = personService.getPerson(project.getPsnCode());
String zhName = person.getZhName();
baseInfo.put("zhName", addStr(9, "<br/>", zhName));
//
String prjNo = project.getPrjNo();
baseInfo.put("prjNo", prjNo);
//
ConstDictionary cd = constDictionaryService.findCdByCategoryCode("project_from", project.getGrantNo());
String project_from = cd.getzh_cn_caption();
baseInfo.put("project_from", addStr(9, "<br/>", project_from));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//
String startDate = sdf.format(project.getStartDate());
String endDate = sdf.format(project.getEndDate());
String startEndDate = startDate + "~" + endDate;
baseInfo.put("startEndDate", startEndDate);
// --
String grantName = project.getGrantName();
baseInfo.put("grantName", addStr(9, "<br/>", grantName));
//
String totalAmt = project.getTotalAmt().toString();
BigDecimal totalAmt_ = checkNumber(totalAmt);
baseInfo.put("totalAmt", totalAmt_.toString());
//
String zhTitle = project.getZhTitle();
baseInfo.put("zhTitle", addStr(38, "<br/>", zhTitle));
List<Map<String, String>> ps = null;
try {
ps = getMembers(project.getPrjXml());
} catch (Exception e) {
e.printStackTrace();
}
String bookName = "";
//
Map<String, Object> itemMap = new HashMap<String, Object>();
if (prjNature.equalsIgnoreCase("1")) {
bookName = " ";
// fdPlanDetail
List<Map<String, Object>> list = fdPlanDetailService.getFdPlanDetailsByPrjCode(Long.parseLong(prjCode));
// test
/*
* Map<String, Object> test = new HashMap<String, Object>(); test.put("itemValue", "6");
* test.put("itemName", " "); test.put("remark", "xxxxx"); list.add(test);
*/
for (Map<String, Object> m : list) {
String key = (String) m.get("ITEMNAME");
BigDecimal itemValue = (BigDecimal) m.get("ITEMVALUE");
BigDecimal proportion = new BigDecimal(0.00);
if (itemValue != null && totalAmt_.compareTo(new BigDecimal("0.00")) != 0) {
proportion = itemValue.divide(totalAmt_, 6, BigDecimal.ROUND_HALF_EVEN);
}
if (itemValue == null) {
itemValue = new BigDecimal("0.00");
}
proportion = checkNumber(proportion.toString());
Map<String, Object> data = new HashMap<String, Object>();
//
data.put("proportion", proportion.toString());
//
BigDecimal amt = checkNumber(itemValue.toString());
data.put("itemValue", amt.toString());
// remark
String remark = (String) m.get("REAMRK");
data.put("remark", remark == null ? "" : remark);
itemMap.put(key, data);
}
} else if (prjNature.equalsIgnoreCase("2")) {
bookName = " ";
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("baseInfo", baseInfo);
map.put("projectMember", ps);
map.put("itemMap", itemMap);
map.put("psCount", ps.size());
map.put("psSum", 25 - ps.size());
String json = JSONObject.fromObject(map).toString();
Struts2Utils.getRequest().setAttribute("jsonData", json);
Struts2Utils.getRequest().setAttribute("prjNature", prjNature);
Struts2Utils.getRequest().setAttribute("bookName", bookName);
Struts2Utils.getRequest().setAttribute("tempDir", tempDir);
Struts2Utils.getRequest().setAttribute("prjCode", prjCode);
return "exprotPdf2";
}
public List<Map<String, String>> getMembers(String xmlData) throws Exception {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
Document doc = DocumentHelper.parseText(xmlData);
Node ps = doc.selectSingleNode("/data/project/persons");
List<Node> psList = ps.selectNodes("person");
String totalAmt = doc.selectSingleNode("/data/project/basic_info/total_amt").getText();
for (Node person : psList) {
Map<String, String> map = new HashMap<String, String>();
Node fund_proportion = person.selectSingleNode("fund_proportion");
String fund_proportion_text = "";
if (fund_proportion == null) {
map.put("proportion", "0.00");
map.put("fpAmt", "0.00");
} else {
fund_proportion_text = fund_proportion.getText();
BigDecimal fp = new BigDecimal(fund_proportion_text);
fp = fp.multiply(new BigDecimal("0.01"));
fp = checkNumber(fp.toString());
map.put("proportion", fp.toString());
BigDecimal fdAmt_ = fp.multiply(new BigDecimal(totalAmt));
fdAmt_ = checkNumber(fdAmt_.toString());
map.put("fpAmt", fdAmt_.toString());
}
Node psn_name = person.selectSingleNode("psn_name");
String psn_name_text = psn_name.getText();
map.put("zhName_p", addStr(9, "<br/>", psn_name_text));
Node psn_work = person.selectSingleNode("psn_work");
String psn_work_text = "";
if (psn_work != null) {
psn_work_text = psn_work.getText();
}
map.put("work", addStr(9, "<br/>", psn_work_text));
Node dept_code_name = person.selectSingleNode("dept_code_name");
String dept_code_name_text = "";
if (dept_code_name != null) {
dept_code_name_text = dept_code_name.getText();
}
map.put("deptName", addStr(9, "<br/>", dept_code_name_text));
Node psn_type_name = person.selectSingleNode("psn_type_name");
String psn_type_name_text = "";
if (psn_type_name != null) {
psn_type_name_text = psn_type_name.getText();
}
map.put("psnTypeName", psn_type_name_text);
list.add(map);
}
return list;
}
/**
*
*
* @param num
* @param splitStr
* @param str
* @return
*/
public String addStr(int num, String splitStr, String str) {
StringBuffer sb = new StringBuffer();
String temp = str;
int len = str.length();
while (len > 0) {
if (len < num) {
num = len;
}
sb.append(temp.substring(0, num)).append(splitStr);
temp = temp.substring(num);
len = temp.length();
}
return sb.toString();
}
/**
* /
*
* @param str
* @param num
* @return
*/
public static int getEndIndex(String str, double num) {
int idx = 0;
int count = 0;
double val = 0.00;
// /
for (int i = 0; i < str.length(); i++) {
if ((str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') || (str.charAt(i) >= 'a' && str.charAt(i) <= 'z')
|| Character.isDigit(str.charAt(i))) {
val += 0.50;
} else {
val += 1.00;
}
count = i + 1;
if (val >= num) {
idx = i;
break;
}
}
if (idx == 0) {
idx = count;
}
return idx;
}
/**
* pdf
*
* @return
*/
@Action("downLoad")
public String downLoad() {
String prjCode = Struts2Utils.getParameter("prjCode");
String basePath = "html_pdf";
Project project = projectService.getProjectById(Long.parseLong(prjCode));
String zhTitle = project.getZhTitle();
FileOutputStream fos = null;
// html
File htmlFile = new File(tempDir + File.separator + basePath + File.separator + prjCode + ".html");
String pdfPath = tempDir + File.separator + basePath + File.separator + zhTitle + ".pdf";
try {
fos = new FileOutputStream(pdfPath);
String url = htmlFile.toURI().toURL().toString();
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(pdfFont + File.separator + "SimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//
String wartermark = "";
if (project.getPrjNature().equalsIgnoreCase("1")) {
//
wartermark = "CTGU ";
} else if (project.getPrjNature().equalsIgnoreCase("2")) {
//
wartermark = "CTGU ";
}
String wm_pdf = tempDir + File.separator + "wm_" + project.getZhTitle() + ".pdf";
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(wm_pdf));
waterMark(bos, pdfPath, wartermark, staticResRootDir2 + File.separator + waterMarkImgDir + File.separator
+ "watermark-" + project.getPrjNature() + ".png");
} catch (Exception e2) {
e2.printStackTrace();
}
// pdf
File pdfFile = new File(wm_pdf);
BufferedOutputStream out = null;
FileInputStream in = null;
try {
in = new FileInputStream(pdfFile);
HttpServletResponse response = Struts2Utils.getResponse();
response.reset();
String fileName = zhTitle + ".pdf";
String fileName2 = URLEncoder.encode(fileName, "UTF-8");
String agent = Struts2Utils.getRequest().getHeader("USER-AGENT");
// IE
if (null != agent && -1 != agent.indexOf("MSIE")) {
fileName2 = new String(fileName.getBytes("GBK"), "ISO8859-1");
} else if (null != agent && -1 != agent.indexOf("Mozilla")) {
fileName2 = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
}
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName2 + "\"");
response.setContentType(FileContentTypes.getContentType(zhTitle + ".pdf"));
out = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[16 * 1024];
int len = 0;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//
// if (htmlFile.exists()) {
// htmlFile.delete();
// }
File temp_file = new File(pdfPath);
if (temp_file.exists()) {
temp_file.delete();
}
if (pdfFile.exists()) {
pdfFile.delete();
}
return null;
}
public BigDecimal checkNumber(String number) {
// 6
DecimalFormat df = new DecimalFormat("0.000000");
String num = df.format(Double.parseDouble(number));
BigDecimal bd = new BigDecimal(num);
String val = bd.toString();
val = val.replaceAll("^(0+)", "");
val = val.replaceAll("(0+)$", "");
int idx = val.indexOf(".");
int len = val.substring(idx + 1).length();
if (len < 2) {
if (len == 0 && idx == 0) {
bd = new BigDecimal("0.00");
} else {
bd = new BigDecimal(val).setScale(2);
}
} else {
bd = new BigDecimal(val).setScale(len);
}
return bd;
}
private String replaceStr(String str, String reVal) {
Pattern pattern = Pattern.compile("^" + reVal + "+|" + reVal + "+$");
Matcher matcher = pattern.matcher(str);
return matcher.replaceAll("");
}
/**
*
*/
private void waterMark(BufferedOutputStream bos, String input, String waterMarkName, String imagePath) {
try {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
int total = reader.getNumberOfPages() + 1;
PdfContentByte content;
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
PdfGState gs = new PdfGState();
for (int i = 1; i < total; i++) {
content = stamper.getOverContent(i);//
content.setGState(gs);
content.beginText();
Image image = Image.getInstance(imagePath);
image.setAbsolutePosition(-30, 200);
image.scalePercent(80);
content.addImage(image);
content.endText();
}
stamper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
7.ftl 파일(템 플 릿 파일)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> </title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
......
</head>
<body>
</body>
</html>
미리 보기 효과:인쇄 효과:
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.