【javaweb】自己动手实现简易的Tomcat2
一个服务器server中可以存放jd,oa这样的多个web应用;
Web应用是通过sun公司制定的servlet接口与Tomcat,JBoss等多个服务器解耦合的
所以,同一个web应用,就可以运行在多种不同的服务器上;(Tomcat,JBoss等服务器就是通过sun制定的Servlet接口来找到要执行的servlet类,从而启动web应用)
Java程序和数据库也是 JDBC接口来进行了解耦合;
Http协议的作用:
注意:
返回状态码500,就说明代码出现了问题;
项目目录
主启动类
package cn.huangyan.httpserver.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import cn.huangyan.httpserver.util.Logger;
/*
* httpserver程序主入口
* @author:huangyan
* @version:1.0
* */
public class BootStrap {
public static void main(String[] args) {
start();
}
// 主程序入口
public static void start() {
ServerSocket serverSocket = null;
BufferedReader br = null;
Socket clientSocket = null;
try {
Logger.log("httpserver start");
// 获取当前时间
long startTime = System.currentTimeMillis();
// 解析服务器中包含的所有web.xml配置文件
String[] webAppNames = {"oa"};
WebParser.parser(webAppNames);
// 获取系统端口号
int port = ServerParser.getPort();
Logger.log("httpserver-port:"+port);
serverSocket = new ServerSocket(port);
// 获取结束时间
long endTime = System.currentTimeMillis();
Logger.log("httpserver started:" + (endTime - startTime) + " ms");
// 通过while循环,让服务器一直处理监听状态
while(true) {
// 开始监听
clientSocket = serverSocket.accept();
// 每一次请求,都开启一个新的线程进行请求处理
new Thread(new HandlerRequest(clientSocket)).start();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
a)主线程负责接收每个客户端socket,并为每个客户端socket创建一个子线程负责处理
b)解析服务器中包含的所有web.xml配置文件
c)扫描配置文件server.xml,获取系统端口号
conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<server>
<service>
<connector port="8080"></connector>
</service>
</server>
package cn.huangyan.httpserver.core;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/*
* 解析服务器中的web.xml配置文件
* */
public class WebParser {
public static Map<String, Map<String,String>> servletMaps = new HashMap<String, Map<String,String>>();
/*
* 解析服务器中所有web应用的web.xml
* */
public static void parser(String[] webAppNames) throws DocumentException{
for(String webAppName : webAppNames) {
Map<String,String> servletMap = parser(webAppName);
servletMaps.put(webAppName, servletMap);
}
}
/*
* 解析单个应用的web.xml配置文件
* */
private static Map<String,String> parser(String webAppName) throws DocumentException{
// 获取web.xml的路径
String webPath = webAppName + "/WEB-INF/web.xml"; // sun公司规定的路径,没有为什么; 实现web服务器和app解耦
// 创建xml解析器
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(webPath));
// 获取servlet节点元素
List<Element> servletNodes = document.selectNodes("/web-app/servlet");
// 创建一个servletInfoMap集合:将servlet-name和servlet-class当做key和value存入此Map中
Map<String,String> servletInfoMap = new HashMap<String, String>();
// 开始遍历servletNodes
for(Element servletNode : servletNodes) {
// 获取servlet-name节点元素
Element servletNameEle = (Element) servletNode.selectSingleNode("servlet-name");
// 获取servlet-name节点元素对象的值
String servletName = servletNameEle.getStringValue();
// 获取servlet-class节点元素
Element servletClassEle = (Element) servletNode.selectSingleNode("servlet-class");
// 获取servlet-class节点元素对象的值
String servletClassName = servletClassEle.getStringValue();
// 将servletName和servletClassName作为key/value,放入servletInfoMap集合中
servletInfoMap.put(servletName, servletClassName);
}
// 获取servlet节点元素
List<Element> servletMappingNodes = document.selectNodes("/web-app/servlet-mapping");
// 创建一个servletInfoMap集合:将servlet-name和url,当做key和value存入此Map中
Map<String,String> servletMappingInfoMap = new HashMap<String, String>();
// 开始遍历servletMappingNodes
for(Element servletMappingNode : servletMappingNodes) {
Element servletNameEle = (Element) servletMappingNode.selectSingleNode("servlet-name");
String servletName = servletNameEle.getStringValue();
Element urlPatternEle = (Element) servletMappingNode.selectSingleNode("url-pattern");
String urlPattern = urlPatternEle.getStringValue();
// 这里要替换为servletMappingInfoMap,不要再写成servletInfoMap
servletMappingInfoMap.put(servletName, urlPattern);
}
// 获取servletInfoMap的keySet()
Set<String> servletNames = servletInfoMap.keySet();
// 创建一个servletMap:
// 将servletMappingInfoMap的value与servletInfoMap的value,分别作为key与value存入此servletMap
Map<String,String> servletMap = new HashMap<String, String>();
for(String servletName : servletNames) {
String urlPattern = servletMappingInfoMap.get(servletName);
String servletClassName = servletInfoMap.get(servletName);
servletMap.put(urlPattern, servletClassName);
}
return servletMap;
}
}
考虑使用web.xml配置文件的原因:(解耦合)
Sun公司制定了规范;
Sun公司规定了webapp开发人员必须把web.xml放在规定的位置,必须使用规定的标签来描述url和类名之间的映射关系
Sun公司也规定了web服务器开发人员,就去这里读取web.xml,并读取web.xml中的规定的标签;
从而,实现了webapp开发人员和web服务器开发人员的解耦合
a)使用SAXReader,并使用三个Map,读取web.xml,最终将一个web.xml中的所有urlPattern <--> servletClassName保存进入ServletMap中
解析server.xml配置文件的类
package cn.huangyan.httpserver.core;
import java.io.File;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/*
* 解析server.xml配置文件
* */
public class ServerParser {
/*
* 获取服务器的端口号
* @return int port
* */
public static int getPort() {
// 设置服务器默认启动端口
int port = 8080;
try {
// 创建解析器
SAXReader saxReader = new SAXReader();
// 通过解析器的read方法,将配置文件读取到内存中,生成一个Document[org.dom4j]对象树
//Document document = saxReader.read("D:\\ecli_space\\workspace\\myday06\\src\\main\\resources\\conf\\server.xml");
//Document document = saxReader.read("src/main/resources/conf/server.xml");
/*
* File用在web项目中,路径最前面不以/开头时,则是以当前web项目为根目录
* */
Document document = saxReader.read(new File("src/main/resources/conf/server.xml"));
// 获取connector节点的路径:server -> service -> connector
// 获取connector节点的xpath路径:/server/service/connector
// 获取connector节点的xpath路径:server//connector
// 获取connector节点的xpath路径://connector
Element connectorEle = (Element) document.selectSingleNode("//connector");
// 获取port属性的值
port = Integer.parseInt(connectorEle.attributeValue("port"));
} catch (DocumentException e) {
e.printStackTrace();
}
return port;
}
}
a)涉及到File类在javaweb项目中,读取文件时路径书写的用法
客户端请求处理类
package cn.huangyan.httpserver.core;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import org.huangyan.oa.servlet.LoginServlet;
import cn.huangyan.httpserver.util.Logger;
/*
* 处理客户端请求
* @version 1.0
* @since 1.0
* */
public class HandlerRequest implements Runnable {
public Socket clientSocket;
public HandlerRequest(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
// 处理客户端请求
BufferedReader br = null;
Logger.log("httpserver thread: "+ Thread.currentThread().getName());;
PrintWriter out = null;
// 接收客户端消息
try {
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 获取响应流对象
out = new PrintWriter(clientSocket.getOutputStream());
/*
// 打印出全部,请求协议
* String temp = null; while((temp = br.readLine()) != null) {
* System.out.println(temp); }
*/
String requestLine = br.readLine(); // GET /oa/index.html HTTP/1.1
String requestURI = requestLine.split(" ")[1];
System.out.println("reqeustURI="+requestURI);
// 判断用户请求是否为静态页面:以.html或者.htm后缀名的文件叫做HTML静态页面
if(requestURI.endsWith(".html") || requestURI.endsWith(".htm")) {
//处理静态页面的方法
responseStaticPage(requestURI,out);
}else {
// 动态资源:java程序,业务处理类
// requestURI:/oa/login?username=jack&password=123
String servletPath = requestURI;
if(servletPath.contains("?")) {
servletPath = servletPath.split("\\?")[0]; // servletPath.split("[?]")[0]
}
System.out.println("servletPath="+servletPath);
/*
* // 这里请求路径和LoginServlet在服务器程序中耦合了
* if("/oa/login".equals(servletPath)) {
* LoginServlet loginServlet = new LoginServlet();
* loginServlet.service();
* }
*/
// 获取应用的名称webAppName
// webAppName: oa,在URI中:/oa/login
String webAppName = servletPath.split("[/]")[1];
System.out.println("webAppName="+webAppName); // oa
// 获取servletMaps集合中的value值
Map<String,String> servletMap = WebParser.servletMaps.get(webAppName);
// 从uri:/oa/login 中获取到:/login
String urlPattern = servletPath.substring(1+webAppName.length());
String servletClassName = servletMap.get(urlPattern);
try {
if(servletClassName != null) {
// 如果找到了动态资源
// 封装请求对象
ServletRequest request = new RequestObject(requestURI);
// 封装响应对象
ResponseObject response = new ResponseObject();
response.setWriter(out);
// 拼接响应信息
out.print("HTTP/1.1 200 OK\n");
out.print("Content-Type:text/html;charset=utf-8\n\n");
/*
* 创建Servlet对象之前,先从Servlet缓存池中查找
* 1. 有,直接拿来用
* 2. 没有,创建Servlet对象,并放入缓存池中
* */
Servlet servlet = ServletCache.get(urlPattern);
if(servlet == null) {
Class clazz = Class.forName(servletClassName);
Object obj = clazz.newInstance();
servlet = (Servlet)obj;
// 将创建好的Servlet放入缓存池中
ServletCache.put(urlPattern, servlet);
}
/*
* 服务器将out输出流对象,传递给webapp开发人员使用的service方法
* 从而webapp开发人员便可以拿着此out输出流对象,往页面写一些数据
*
* 由于当前线程持有的是此out输出流对象
* 我们为了保证同处于当前线程的service()业务方法,也持有同样的out输出流对象,
* 则必须把此out输出流对象传递给service方法,而不能自己去service()业务方法中去new一个新的out对象
*
* servlet.service(out);
* */
Logger.log("Servlet对象是:"+servlet);
// 这个时候,服务器开发人员不知道如何调用servlet业务处理类里的业务方法
// 这个时候,sun公司的servlet规范又出来了
servlet.service(request,response);
}else {
// 404找不到动态资源
StringBuilder html = new StringBuilder();
html.append("HTTP/1.1 404 NotFound\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
html.append("<html>\r\n" + "<head>\r\n" + "<meta charset=\"UTF-8\">\r\n" +
"<title>404-错误</title>\r\n" + "</head>\r\n" +
"<body>\r\n" + "<center><font size=\"35xp\" color=\"red\">404-Not-Found</font></center>\r\n" +
"</body>\r\n" + "</html>");
out.print(html);
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
// 强制刷新(否则,浏览器无法显示)
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/* 处理静态页面
* requestURI
* */
public void responseStaticPage(String requestURI, PrintWriter out) {
// requestURI: /oa/index.html
// 静态页面路径:oa/index.html
String htmlPath = requestURI.substring(1);
BufferedReader br = null;
try {
// 读取页面
br = new BufferedReader(new FileReader(htmlPath));
String temp = null;
StringBuilder html = new StringBuilder();
// 拼接响应信息
html.append("HTTP/1.1 200 OK\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
while((temp = br.readLine()) != null) {
html.append(temp);
}
// 输出HTML
out.print(html);
} catch (FileNotFoundException e) {
// 404找不到静态资源
StringBuilder html = new StringBuilder();
html.append("HTTP/1.1 404 NotFound\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
html.append("<html>\r\n" + "<head>\r\n" + "<meta charset=\"UTF-8\">\r\n" +
"<title>404-错误</title>\r\n" + "</head>\r\n" +
"<body>\r\n" + "<center><font size=\"35xp\" color=\"red\">404-Not-Found</font></center>\r\n" +
"</body>\r\n" + "</html>");
out.print(html);
}catch(IOException e) {
e.printStackTrace();
}
}
}
a)客户端请求处理类又细分为两个部分:处理静态资源,处理请求的动态资源
b)如果处理的请求是请求动态资源,则涉及到在服务器代码中封装请求对象,封装响应对象,servlet缓存池
c)引出sun公司定义javax.servlet.Servlet接口的目的
Servlet缓存池
package cn.huangyan.httpserver.core;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
/*
* Servlet缓存池
* */
public class ServletCache {
private static Map<String,Servlet> servletMap = new HashMap<String,Servlet>();
public static void put(String urlPattern , Servlet servlet) {
servletMap.put(urlPattern, servlet);
}
public static Servlet get(String urlPattern) {
return servletMap.get(urlPattern);
}
}
javax.servlet.Servlet接口
package javax.servlet;
/*
* 由sun公司指定的servlet接口规范,
* 该接口由web服务器开发人员调用,由webapp开发人员来实现;
* */
public interface Servlet {
// 业务处理方法
void service(ServletRequest request,ServletResponse response);
}
/*
* import cn.huangyan.httpserver.core.ResponseObject;
* // 这个又出现一个问题,此ResponseObject是web服务器开发人员开发程序是自定义的
*
*
* 由sun公司指定的servlet接口规范,
public interface Servlet {
void service(ResponseObject response);
}
---------- 这就出现了耦合的问题:
在sun公司开发的接口中出现了比如Tomcat公司自定义的ResponseObject类
---------- 这时,就需要把sun公司和Tomcat公司再通过接口进行解耦合
定义ServletResponse接口
*/
a)在sun公司的Servlet接口中出现了Tomcat公司自定义的Response类,这就又出现了耦合的问题
b)sun公司为了消除这种耦合,就又定义了ServletRequest接口和ServletResponse接口
请求对象接口
package javax.servlet;
/*
* 负责封装请求参数的对象
* */
public interface ServletRequest {
// 获取单选框标参数的值
public String getParametervalue(String key);
// 获取多选框标参数的值
public String[] getParametervalues(String key);
}
响应对象接口
package javax.servlet;
import java.io.PrintWriter;
/*
* sun公司定义的:
* 封装响应参数的接口规范
* */
public interface ServletResponse {
void setWriter(PrintWriter out);
PrintWriter getWriter();
}
工具类
日期工具类
package cn.huangyan.httpserver.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/* 日期工具类
* @author huangyan
* @version 1.0
* #since 1.0
* */
public class DateUtil {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
private DateUtil() {}
/*
* 获取系统当前时间
* @return String [yyyy-MM-dd HH:mm:ss SSS]
* */
public static String getCurrentTime() {
return dateFormat.format(new Date());
}
}
日志工具类
package cn.huangyan.httpserver.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 日志记录器
* @author:huangyan
* @version:1.0
* */
public class Logger {
// 工具类的方法往往是静态的,直接通过类名来调用,不需要创建对象;
// 工具类的构造方法往往是私有的,但不是必须的;
private Logger() {
}
public static void log(String msg) {
/*
* SimpleDateFormat dataFormat = new
* SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); Date nowTime = new Date();
* String nowTimeStr = dataFormat.format(nowTime);
*/
System.out.println("[INFO] "+DateUtil.getCurrentTime()+" "+msg);
}
}
业务处理类
登录的业务处理类
package org.huangyan.oa.servlet;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import cn.huangyan.httpserver.core.ResponseObject;
/*
* 处理登录业务的java程序
* 该java程序由webapp开发人员编写;由web服务器来调用
* */
public class LoginServlet implements Servlet{
@Override
public void service(ServletRequest request,ServletResponse response) {
System.out.println("login-service:正在执行身份验证...");
// 获取当前线程的输出流对象(也就是当前客户端socket对象对应的输出流对象)
PrintWriter out = response.getWriter();
out.append("<html>\r\n" + "<head>\r\n" + "<meta charset=\"UTF-8\">\r\n" +
"<title>404-错误</title>\r\n" + "</head>\r\n" +
"<body>\r\n" + "<center><font size=\"35xp\" color=\"blue\">正在执行身份验证...</font></center>\r\n" +
"</body>\r\n" + "</html>");
}
/*
* @Override public void service(ResponseObject response) {
* System.out.println("login-service:正在执行身份验证...");
*
* // 获取当前线程的输出流对象(也就是当前客户端socket对象对应的输出流对象) PrintWriter out =
* response.getWriter();
*
* out.append("<html>\r\n" + "<head>\r\n" + "<meta charset=\"UTF-8\">\r\n" +
* "<title>404-错误</title>\r\n" + "</head>\r\n" + "<body>\r\n" +
* "<center><font size=\"35xp\" color=\"blue\">正在执行身份验证...</font></center>\r\n"
* + "</body>\r\n" + "</html>"); }
*/
}
用户保存的业务处理类
package org.huangyan.oa.servlet;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/*
* 处理登录业务的java程序
* 该java程序由webapp开发人员编写;由web服务器来调用
* */
public class UserSaveServlet implements Servlet{
@Override
public void service(ServletRequest request,ServletResponse response ) {
System.out.println("UserSaveServlet:正在执行用户保存");
String username = null;
try {
// 对传递过来的“%e6%96%b0%e5%bb%ba”,这种UTF-8编码的串,用UTF-8进行解码
username = URLDecoder.decode(request.getParametervalue("username"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String gender = request.getParametervalue("gender");
String[] likes = request.getParametervalues("like");
System.out.println("username="+username);
PrintWriter out = response.getWriter();
out.print("<html>\r\n" + "<head>\r\n" + "<meta charset=\"UTF-8\">\r\n" +
"<title>用户信息</title>\r\n" + "</head>\r\n" + "<body>\r\n"
+"用户名:"+username+ "<br>"
+"性别:"+gender+ "<br>"
+"爱好:"+likes[0]+" "+likes[1]+
"</body>\r\n" + "</html>");
}
// public void service(ResponseObject response) {
// System.out.println("UserSaveServlet:正在执行用户保存");
// }
}
web应用:oa
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>oa办公系统</title>
</head>
<body>
<center><font size="35xp" color="blue">oa办公系统首页</font></center>
</body>
</html>
userSave.html
<!DOCTYPE html>
<html>
<head>
<title>用户信息-保存用户信息</title>
<meta content="text/html;charset=utf-8">
</head>
<body>
<center>
<form name="userForm" action="/oa/user/save" method="get">
用户名:
<input type="text" name="username"/><br><br>
性 别:
<input type="radio" name="gender" value="1"/>男
<input type="radio" name="gender" value="0"/>女
<br><br>
性 别:
<input type="checkbox" name="like" value="music"/>音乐
<input type="checkbox" name="like" value="sport"/>运动
<input type="checkbox" name="like" value="food"/>美食
<input type="checkbox" name="like" value="sleep"/>睡觉
<input type="checkbox" name="like" value="travel"/>旅行
<br><br>
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</form>
</center>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>org.huangyan.oa.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UserSaveServlet</servlet-name>
<servlet-class>org.huangyan.oa.servlet.UserSaveServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserSaveServlet</servlet-name>
<url-pattern>/user/save</url-pattern>
</servlet-mapping>
</web-app>
web应用:bank
actOpen.html
<html>
<head>
<title>银行帐户-开户</title>
<meta content="text/html;charset=utf-8"/>
</head>
<body>
<form name="actOpenForm" action="/bank/act/open" method="get">
银行帐户:
<input type="text" name="actno"/>
<br><br>
开户金额:
<input type="text" name="balance"/>
<br><br>
<input type="submit" value="确认开户"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
actTransfer.html
<html>
<head>
<title>银行帐户-转帐</title>
<meta content="text/html;charset=utf-8"/>
</head>
<body>
<form name="actTransferForm" action="/bank/act/transfer" method="get">
转出帐号:
<input type="text" name="actFrom"/>
<br><br>
转出金额:
<input type="text" name="balance"/>
<br><br>
转入帐号:
<input type="text" name="actTo"/>
<br><br>
<input type="submit" value="确认转帐"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>actOpenServlet</servlet-name>
<servlet-class>org.bjpowernode.bank.servlet.ActOpenServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>actOpenServlet</servlet-name>
<url-pattern>/act/open</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>actTransferServlet</servlet-name>
<servlet-class>org.bjpowernode.bank.servlet.ActTransferServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>actTransferServlet</servlet-name>
<url-pattern>/act/transfer</url-pattern>
</servlet-mapping>
</web-app>
开户的业务处理类
package org.bjpowernode.bank.servlet;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ActOpenServlet implements Servlet {
@Override
public void service(ServletRequest request, ServletResponse response) {
//-----------从页面获取参数值------------
String actno = request.getParameterValue("actno");
double balance = Double.parseDouble(request.getParameterValue("balance"));
//---------------连接数据库-------------
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3366/bjpowernode", "root", "111");
//3.定义SQL语句框架
String sql = "insert into t_act(actno,balance) values(?,?)";
//4.进行SQL语句预编译
ps = conn.prepareStatement(sql);
//5.进行赋值
ps.setString(1, actno);
ps.setDouble(2, balance);
//6.执行SQL语句
count = ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//获取响应流对象
PrintWriter out = response.getWriter();
if(count == 1){
out.print("<html>");
out.print("<head>");
out.print("<title>银行帐户-开户结果</title>");
out.print("<meta content='text/html;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("<center><font size='35px' color='green'>恭喜您,开户成功!</font></center>");
out.print("</body>");
out.print("</html>");
}else{
out.print("<html>");
out.print("<head>");
out.print("<title>银行帐户-开户结果</title>");
out.print("<meta content='text/html;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("<center><font size='35px' color='red'>对不起,开户失败!</font></center>");
out.print("</body>");
out.print("</html>");
}
}
}
转账的业务处理类
package org.bjpowernode.bank.servlet;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ActTransferServlet implements Servlet {
@Override
public void service(ServletRequest request, ServletResponse response) {
//------------获取页面请求的参数------------
String actFrom = request.getParameterValue("actFrom");
double balance = Double.parseDouble(request.getParameterValue("balance"));
String actTo = request.getParameterValue("actTo");
//-----------连接数据库---------------
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接
String url = "jdbc:mysql://127.0.0.1:3366/bjpowernode";
String user = "root";
String password = "111";
conn = DriverManager.getConnection(url, user, password);
//开启事务,关闭自动提交
conn.setAutoCommit(false);
//3.定义SQL语句框架
String sql_from = "update t_act set balance = balance - ? where actno = ?";
//4.进行SQL语句的预编译
ps = conn.prepareStatement(sql_from);
//5.进行赋值
ps.setDouble(1, balance);
ps.setString(2, actFrom);
//6.执行SQL语句
count = ps.executeUpdate();
String sql_to = "update t_act set balance = balance + ? where actno = ?";
ps = conn.prepareStatement(sql_to);
ps.setDouble(1, balance);
ps.setString(2, actTo);
count = count + ps.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
try {
// 出现异常,则进行事务回滚
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
//关闭资源
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//获取响应流对象
PrintWriter out = response.getWriter();
if(count == 2){
out.print("<html>");
out.print("<head>");
out.print("<title>银行帐户-转帐结果</title>");
out.print("<meta content='text/html;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("<center><font size='35px' color='green'>转帐成功!</font></center>");
out.print("</body>");
out.print("</html>");
}else{
out.print("<html>");
out.print("<head>");
out.print("<title>银行帐户-转帐结果</title>");
out.print("<meta content='text/html;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("<center><font size='35px' color='red'>转帐失败!</font></center>");
out.print("</body>");
out.print("</html>");
}
}
}