最近沒有專案做,閒著沒事,看到一個書城的網站很好,於是就是仿了一個,把裡面的ui直接拿過來用,前端後端自己寫的,目前大部分的功能已經實現了。
一、開發環境的部署
程式結構:
BootStrap Ajax Struts2 Hibernate MySql
僅供參考:可實現相關功能即可
作業系統:ubuntu 14.10
#前端框架:BootStrap 注意:此架構只是為了實現使用者介面,與特定功能無關
資料庫:mysql-5.5 資料庫工具:emma
伺服器:tomcat 伺服器工具:Myeclipse 10(已配置好Struts2和Hibernate環境)
注意:
程式偵錯流程可能會產生亂碼,只需保持所有工具編碼方式相同即可。
二、專案檔案設定
1、新Web Project,命名為ROOT
2、設定/WebRoot/ WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ROOT</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
3 、 設定/src/struts.xml(struts設定檔),其他的action和interceptor被我刪了,這點夠用了。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <!-- 登录 --> <action name="login" class="com.action.Login" method="login"></action> <!-- 登出 --> <action name="logout" class="com.action.Logout" method="logout"></action> <!-- 注册 --> <action name="register" class="com.action.Register" method="register"></action> <!-- 邮件发送 --> <action name="sendmail" class="com.action.SendMail" method="sendmail"></action> </package> </struts>
4、設定/src/hibernate.cfg.xml(hibernate資料庫設定檔),注意倒數第4行有個
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="myeclipse.connection.profile">Myeclipse Mysql</property> <!--指明JDBC路径、指明数据库名称--> <property name="connection.url">jdbc:mysql://localhost:3306/test</property> <!--指明数据库账户和密码--> <property name="connection.username">root</property> <property name="connection.password">root</property> <!--指明JDBC驱动--> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!--指明mysql方言--> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="format_sql">true</property> <mapping resource="com/hibernate/bookchat.hbm.xml" /> </session-factory> </hibernate-configuration>
5、/src下建立com.hibernate包,在該包下建立bookchat.hbm.xml(hibernate物件關係映射檔),並配置
注意
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!--指明Bean类名,指明数据库表名--> <class name="com.hibernate.User" table="user"> <id column="id" type="int"> <generator class="native" /> </id> <!--指明数据库字段名、字段类型--> <property name="user_id" column="user_id" type="int" /> <property name="phone" column="phone" type="int" /> <property name="email" column="email" type="string" /> <property name="username" column="username" type="string" /> <property name="password" column="password" type="string" /> <property name="icon" column="icon" type="string" /> <property name="description" column="description" type="string" /> <property name="followThreadNum" column="followThreadNum" type="int" /> <property name="followPeopleNum" column="followPeopleNum" type="int" /> <property name="fansNum" column="fansNum" type="int" /> <property name="haveMsg" column="haveMsg" type="int" /> </class> </hibernate-mapping>
6、/src下的com.hibernate套件下建立User類
package com.hibernate; public class User { private int user_id; //对应数据库中user_id private int phone; //手机号 private String email; //邮件 private String username; //用户名 private String password; //密码 private String icon; //用户头像 private String description; //自定义描述 private int followThreadNum; //关注书单数量 private int followPeopleNum; //关注的人数量 private int fansNum; //粉丝数量 private int haveMsg; //当前是否有新消息 public User() { super(); } //这个构造方法在注册时有用 public User(String email, String username, String password) { // 用户内容:username,password,email // 系统定义:user_id,icon,followThreadNum,followPeopleNum,fansNum,haveMsg // 留空:phone,description, this.user_id = 39212; // this.phone = phone; this.email = email; this.username = username; this.password = password; this.icon = "images/icon.png"; // this.description = description; this.followThreadNum = 0; this.followPeopleNum = 0; this.fansNum = 0; this.haveMsg = 0; } public int getUser_id() { return user_id; } public void setUser_id(int user_id) { this.user_id = user_id; } public int getPhone() { return phone; } public void setPhone(int phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public int getFollowThreadNum() { return followThreadNum; } public void setFollowThreadNum(int followThreadNum) { this.followThreadNum = followThreadNum; } public int getFollowPeopleNum() { return followPeopleNum; } public void setFollowPeopleNum(int followPeopleNum) { this.followPeopleNum = followPeopleNum; } public int getFansNum() { return fansNum; } public void setFansNum(int fansNum) { this.fansNum = fansNum; } public int getHaveMsg() { return haveMsg; } public void setHaveMsg(int haveMsg) { this.haveMsg = haveMsg; } }
7、/src下的com.db包下建立CreateTable類,之後Run as - Java Application,查看控制台是否輸出了sql語句
package com.db; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; public class CREATTABLEDONOT { public static void main(String[] args) { // 默认读取hibernate.cfg.xml文件 Configuration cfg = new Configuration().configure(); SchemaExport export = new SchemaExport(cfg); export.create(true, true); } }
#三、檢查資料庫
1、開啟資料庫GUI工具,查看test資料庫下方是否有一個user表,若能開啟user表說明之前設定成功。
2、編輯user表:設定欄位預設值,可以向表中新增資料。
#四、網頁UI設計
1、我們在struts.xml檔案設定中已經埋下伏筆:
<action name="login" class="com.action.Login" method="login"></action> <action name="logout" class="com.action.Logout" method="logout"></action> <action name="register" class="com.action.Register" method="register"></action> <action name="sendmail" class="com.action.SendMail" method="sendmail"></action>
我們可以在網頁中請求/login,/logout,/register來存取這三個Action處理類,當然這三個類具體的內容我們還沒寫,先放。
2、現在開始思考網頁設計需要什麼東西...
首頁提供登陸和註冊連結
登陸彈出框和註冊頁面
# 登陸/註冊成功,登陸和註冊消失,顯示用戶名和退出登陸
我們想達到的效果:登陸/註冊成功後顯示用戶名,登陸失敗後動態提示錯誤詳情!
五、JQuery Ajax設計
#1、主要的JQuery和Ajax程式碼
(function(window, $) { var SOKK = {}; ys.common = SOKK; //邮箱验证 SOKK.sendmail = function(){ var email = $("#inputEmail").val().trim(); if(!checkEmail(email)){ return false; } //发送请求 $.get("/sendmail","email="+email,function(data){ data = JSON.parse(data); tip(data.code); }) } //注册 SOKK.signup = function(form){ var form = $(form); //成功方可继续执行 if(!checkSignUp(form.find("input"))) return false; //序列化表单,生成JSON对象 var JStr =form.serialize(); // var JStr = JSON.stringify(JForm); tip(JStr); $.post("/register",JStr,function(data){ data = JSON.parse(data); if (data.code == 200) { location.reload(); //如何跳转到首页? } else { tip(data.code); } }) }; // 登录 SOKK.login = function(form) { var form = $(form); var input = form.find("input"); var username=$.trim(input[0].value); var password=$.trim(input[1].value); if(checkLogin(username,password)){ return false; } var dataParam = {}; dataParam.username = username; dataParam.password = password; // 这里的dataParam是键值对,但服务器获取的时候是?username=xx&password=xx; // 如果使用json传输那么就不能用这种方式而必须用$.ajax,而且json在服务器端还要再解析, // 所以在发送请求时,不建议使用json。接受数据可以使用json $.post("/login", dataParam, function(data) { // json字符串->json对象 data = JSON.parse(data); if (data.code == 200) { location.reload(); } else { tip(data.code); } }) }; //登出 SOKK.logout = function(){ $.get("/logout", function (data) { //json字符串->json对象 data = JSON.parse(data); if (data.code==200){ location.reload(); } }) }; })(window, $)
2、自訂工具程式碼
// 自定义提示 function tip(info){ if(isNaN(info)){ toastr.info(info); }else{ var msg; if(info<300){ switch(info){ case 100: msg="加入书架成功!"; break; case 101: msg="关注本书成功!"; break; case 102: msg="已移动到【正在看】!"; break; case 103: msg="已移动到【准备看】!"; break; case 104: msg="已移动到【已看完】!"; break; case 105: msg="已移动到【回收站】!"; break; case 110: msg="验证邮件已发送到你的邮箱!";break; case 200: msg="请求成功!"; break; case 202: msg="请求已接受,但尚未处理。"; break; case 204: msg="请求成功,但无返回内容。"; break; default : break; } toastr.success(msg); }else if(info<1000){ switch(info){ case 301: msg="请求网页的位置发生改变!"; break; case 400: msg="错误请求,请输入正确信息!"; break; case 401: msg="非法请求,未授权进入此页面!"; break; case 403: msg="拒绝请求!"; break; case 404: msg="请求页面不存在!"; break; case 408: msg="请求超时!"; break; case 500: msg="服务器出错!"; break; case 500: msg="服务不可用!"; break; case 900: msg="用户名/密码错误,请重新输入"; break; case 903: msg="服务器出错,请重试!"; break; case 904: msg="服务器无返回信息!"; break; case 905: msg="网络出错!"; break; case 906: msg="注册失败,请重试!";break; case 907: msg="邮箱验证码错误!";break; case 908: msg="用户名已存在!";break; case 909: msg="邮箱已被注册!";break; case 910: msg="验证邮件发送失败!";break; default : break; } toastr.error(msg); }else{ toastr.info(info); } } } //注册检查 function checkSignUp(input){ var username = $.trim(input[0].value); var password1 = $.trim(input[1].value); var password2 = $.trim(input[2].value); var email = $.trim(input[3].value); var emailcode = $.trim(input[4].value); for (var i = 0; i < input.length; i++) { if(input[i].value.length<=0){ tip("所有内容不得为空!"); return false; } }; if(username.length<4){ tip("用户名不得少于4个字符!"); return false; } if(password1!==password2){ tip("两次输入的密码不同!"); return false; } if(password1.length<6){ tip("密码不得少于6个字符!"); return false; } return true; } function checkLogin(username,password){ if(!username){ tip("请输入用户名!"); return false; } if(!password){ tip("请输入密码!"); return false; } } function checkEmail(email){ var reg = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/; if(email){ if(reg.test(email)){ return true; }else{ tip("邮箱地址不符合规范!"); return false; } }else{ tip("邮箱地址不得为空!"); return false; } }
3、toastr是一個前端非阻塞的提示插件,可以到http://www.bootcdn.cn/toastr.js/ 下載使用
#六、Action設計
1、Login.java
package com.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.service.BaseService; import com.service.BaseServiceImpl; import com.util.OperateJSON; public class Login extends ActionSupport { private static final long serialVersionUID = 4679952956618457478L; private String username; private String password; public void login() { HttpServletRequest request = ServletActionContext.getRequest(); BaseService hs = new BaseServiceImpl(); OperateJSON oj = new OperateJSON(); username = request.getParameter("username"); password = request.getParameter("password"); System.out.println("用户名:" + username + "--密码:" + password); // 登陆返回用户id Object obj = hs.login(username, password); if (obj != null) { System.out.println("用户名密码正确"); request.getSession().setAttribute("username", username); request.getSession().setAttribute("userid", obj); System.out.println("用户名" + username + "的Session设置完毕~"); System.out.println("用户id的Session设置完毕~"); oj.putCode(200); } else { System.out.println("用户名密码错误"); oj.putCode(900); } oj.send(); } }
2、Logout.java
package com.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.util.OperateJSON; public class Logout extends ActionSupport { private static final long serialVersionUID = -6758897982192371466L; HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); OperateJSON oj = new OperateJSON(); public void logout() { request.getSession().removeAttribute("username"); request.getSession().invalidate(); if (request.getSession().getAttribute("username") == null) { oj.putCode(200); } else { oj.putCode(903); } oj.send(); } }
3、 Register.java
package com.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import com.hibernate.User; import com.opensymphony.xwork2.ActionSupport; import com.service.BaseService; import com.service.BaseServiceImpl; import com.util.OperateJSON; public class Register extends ActionSupport { private static final long serialVersionUID = -3356620731966076779L; HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); BaseService bs = new BaseServiceImpl(); OperateJSON oj = new OperateJSON(); SendMail sm = new SendMail(); public void register() { String username = request.getParameter("username"); String password1 = request.getParameter("password1"); String password2 = request.getParameter("password2"); String password = (password1.equals(password2) ? password1 : null); String email = request.getParameter("email"); String emailcode = request.getParameter("emailcode"); // 判断用户输入和生成的邮箱验证码是否相同 if (!(emailcode.equals(sm.getMailCode()))) { oj.putCode(907); oj.send(); return; } // 检测用户名/邮箱是否唯一 if (!bs.isUnique("User", "username", username)) { oj.putCode(908); oj.send(); return; } if (!bs.isUnique("User", "email", email)) { oj.putCode(909); oj.send(); return; } // 构建User对象 User user = new User(email, username, password); // 建立对象关系映射 Boolean reged = bs.register(user); if (reged) { System.out.println("用户注册成功"); request.getSession().setAttribute("username", username); oj.putCode(200); } else { System.out.println("注册失败"); oj.putCode(906); } oj.send(); } }
4、 SendMail.java SMTP協定發送郵件的類,使用前需要導入mail的jar包,同時,還要設定開啟發件人郵箱的smtp服務
package com.action; import java.util.Date; import java.util.Properties; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.util.OperateJSON; public class SendMail extends ActionSupport { private static final long serialVersionUID = -4724909293302616101L; private static String QQ = "392102018"; // qq private static String HOST = "qq.com"; // SMTP服务器主机名 private static String PASS = "xxxxxxxx"; // SMTP服务器密码 private static String mailCode; // 邮件验证码 OperateJSON oj = new OperateJSON(); public void sendmail() { HttpServletRequest request = ServletActionContext.getRequest(); String email = request.getParameter("email"); System.out.println(email); String mailCode = SendMail.setMailCode(); try { beginSend(email, mailCode); oj.putCode(110); } catch (MessagingException e) { oj.putCode(910); } finally { oj.send(); } } public static String setMailCode() { mailCode = 100000 + (int) (Math.random() * 900000) + "BC"; System.out.println(mailCode); return mailCode; } public String getMailCode() { return SendMail.mailCode; } public void beginSend(String email, String mailCode) throws MessagingException { String mailTo = email; // 收件方mail地址 String mailTitle = "欢迎您使用书聊网! 立即激活您的账户"; String mailContent = "<p>尊敬的用户:</p><p>你好!立即激活您的账户,和书聊网会员一起看书交流。要激活您的账户,只需复制下面的验证码到注册页面确认。 </p>" + mailCode + "<p>版权所有© 1999 - 2015 BookChat。保留所有权利。</p>"; // 设置主要信息 Properties props = new Properties(); props.put("mail.smtp.host", "smtp." + HOST); props.put("mail.smtp.auth", "true"); Session session = Session.getInstance(props); session.setDebug(true); // 开启邮件对象 MimeMessage message = new MimeMessage(session); // 设置发件人/收件人/主题/发信时间 InternetAddress from = new InternetAddress(QQ + "@" + HOST); message.setFrom(from); InternetAddress to = new InternetAddress(mailTo); message.setRecipient(Message.RecipientType.TO, to); message.setSubject(mailTitle); message.setSentDate(new Date()); // 设置消息对象内容 BodyPart mdp = new MimeBodyPart();// 新建一个存放信件内容的BodyPart对象 mdp.setContent(mailContent, "text/html;charset=utf-8");// 给BodyPart对象设置内容和格式/编码方式 Multipart mm = new MimeMultipart();// 新建一个MimeMultipart对象用来存放BodyPart对象(事实上可以存放多个) mm.addBodyPart(mdp);// 将BodyPart加入到MimeMultipart对象中(可以加入多个BodyPart) message.setContent(mm);// 把mm作为消息对象的内容 message.saveChanges(); // 开启传输对象 Transport transport = session.getTransport("smtp"); transport.connect("smtp." + HOST, QQ, PASS); // 这里的115798090也要修改为您的QQ号码 transport.sendMessage(message, message.getAllRecipients()); transport.close(); } }
5、OpreateJSON
package com.util; import java.io.IOException; import java.io.PrintWriter; import org.apache.struts2.ServletActionContext; import net.sf.json.JSONObject; public class OperateJSON { JSONObject json; public OperateJSON() { json = new JSONObject(); json.put("code", ""); json.put("msg", ""); json.put("data", ""); } public OperateJSON(String str) { json = JSONObject.fromObject(str); } public void put(String key, Object value) { json.remove(key); json.put(key, value); } public void putCode(Object value) { json.remove("code"); this.put("code", value); } public void putMsg(Object value) { json.remove("msg"); this.put("msg", value); } public void remove(String key) { json.remove(key); } public void send() { System.out.println("----------返回的数据是:" + json); try { PrintWriter out = ServletActionContext.getResponse().getWriter(); out.print(json); out.flush(); } catch (IOException e) { e.printStackTrace(); } } }
七、Hibernate Dao設計
這塊都是一些操作資料庫的內容,大家都有自己的風格,仔細一點寫就好了。代碼太亂,我就不放出來嚇人了-.-! 。
八、總結
開始想展示下結果的還是算了,也就那麼回事。一個小例子,瑕疵難免,還望大神們指正。
寫完了,心情好多了,招募會去看看也好,找不找工作不重要,重要的是我走在正確的路上,只有依靠自己才是強者...
上面是我整理給大家的,希望未來會對大家有幫助。
相關文章:
#Ajax請求過程中下載檔案在FireFox(火狐)瀏覽器下的相容問題
以上是JQuery+Ajax+Struts2+Hibernate框架整合實現完整的登入註冊的詳細內容。更多資訊請關注PHP中文網其他相關文章!

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver CS6
視覺化網頁開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。