个人复习
在老师的带领下做了个简单的Servlet,因为代码过多,只贴出来第一第二和最后一个任务的代码
练习3:简单WebServer的实现
1. 需求及实现方法
第一个任务:
写服务器端,多线程的服务器端
1.包:cn.tedu.core
2.类名:WebServer
3.声明成员变量:
server:ServerSocket
4.方法:
无参的构造方法:WebServer
功能:初始化server,端口号为8080
start方法:
功能:启动服务器
接收客户端请求:accept()
定义线程对象,并启动线程start()
5.定义内部类:ClientHandler
线程类定义成员变量:socket:Socket
定义带参的构造方法初始化:socket
重写run方法:功能:控制台输出处理客户端请求
6.定义main方法:启动服务器
7.测试:打开浏览器客户端:http://localhost:8080/
第二个任务:读客户端发给服务器的报头信息
1.读客户端的请求
在run方法处理客户端请求
1)获取InputStream对象
2)使用read方法读取数据,判断如果!=-1,输出
int d = -1;
while((d= in.read())!=-1){
System.out.print((char)d);
}
3)观察打印结果:学习http协议请求头信息格式
报头的每一行都是以1310
整个请求报头信息完成后,还有一个1310
空行
请求头信息
GET /myweb/images/logo.png HTTP/1.11310
Accept: text/html, application/xhtml+xml, image/jxr, */*1310
Accept-Language: zh-CN1310
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.162991310
Accept-Encoding: gzip, deflate1310
Host: localhost:80801310
Connection: Keep-Alive1310
1310
//这一行必须空
测试:http://localhost:8080/myweb/index.html
2.解析请求行:
GET /myweb/images/logo.png HTTP/1.11310
核心代码参考:
while循环跳出 最后两个字符是13,10
StringBuilder
int d = -1;
char c1 = 0,c2=0;
while((d= in.read())!=-1){
c2 = (char)d;
if(c1==13&&c2==10){
break;
}
builder.append(c2);
c1 = c2;
}
System.out.println(builder.toString().trim());
第三任务:封装请求行中的三部分内容到HttpRequest类中
1.解析请求行
2.定义HttpRequest类
1)定义HttpRequest类在cn.tedu.http包中
2)定义变量:method,url,protocol;
3)定义带参的构造方法HttpRequest(InputStream in)
4)定义三个变量的get方法
5)定义方法:parseRquestLine(InputStream in):void
方法的功能:解析请求行,给三个变量赋值
在构造方法中调用
3.重构WebServer的run方法
创建HttpRequest对象,调用get方法打印请求的方法,url,protocl
4.测试:打开浏览器客户端:http://localhost:8080/myweb/index.html
第四个任务:读文件,响应文件到客户端
1.在项目中添加目录webapps,并在里面添加一个子目录myweb,
然后在其中存放我们定义的页面index.html
2.响应包括两部分,响应头和响应文件内容
3.学习掌握响应头信息
HTTP/1.1 200 OK1310
Content-Type:text/html1310
Content-Length:201310
1310
4.响应画面到客户端
5.测试:打开浏览器客户端:http://localhost:8080/myweb/index.html
第五个任务:封装HttpResponse类
1.定义HttpResponse类:
1)定义HTTPResponse类在cn.tedu.http包中
2)定义变量:
OutputStream out;
File entity;
定义setEntity()和getEntity()方法。
3)定义构造方法:HttpResponse(OutputStream out)
功能:初始化out成员变量
4)定义方法: println(String line) :void
功能:
向客户端发送一行字符串,该字符串会通过ISO8859-1转换为一组字节并写出.写出后会自动连续写出CRLF
参考代码:
public void println(String line){
out.write(line.getBytes(“ISO8859-1”));
out.write(13);
out.write(10);
}
5)定义方法sendStatusLine():void
功能:发送状态行信息
String line = “HTTP/1.1 200 OK”;
在sendStatusLine()放中调用println(String line)方法。
参考代码:
public void sendStatusLine(){
String line = “HTTP/1.1 200 OK”;
println(line);
}
6)定义方法:getMimeTypeByEntity():String
功能:根据实体文件的名字获取对应的介质类型,Content-Type使用的值(常用的几种):根据文件扩展名返回文件的介质类型
核心代码参考:
String name = entity.getName().substring(
entity.getName().lastIndexOf(".")+1
);
if("html".equals(name)){
return "text/html";
}else if("jpg".equals(name)){
return "image/jpg";
}else if("png".equals(name)){
return "image/png";
}
else if("gif".equals(name)){
return "image/gif";
}
return "";
测试:
8)定义方法:sendHeaders();
功能:响应头信息
核心代码参考:
println("Content-Type:"+getMimeTypeByEntity());
println("Content-Length:"+entity.length());
println("");//单独发送CRLF表示头发送完毕
9)定义方法: sendContent()
功能:发送响应正文信息
核心代码参考:
fis = new FileInputStream(entity);
int len = -1;
byte[] data = new byte[1024*10];
while((len = fis.read(data))!=-1){
out.write(data,0,len);
}
10)定义方法:flush():void
功能:调用sendStatusLine();sendHeaders();sendContent()
2.重构WebServer:
1)创建HTTPResponse对象
2)把File对象通过set方法传递到reponse
3)调用Flush方法
测试:http://localhost:8080/myweb/index.html
第六个任务:
1.在cn.tedu.core中添加一个类HttpContext
该类用于定义相关Http协议的内容.
比如头信息中Content-Type的值与文件后缀的关系等.
1)在cn.tedu.core包中定义HttpContext类
2)定义两个常量int CR = 13; int LF = 10;
3)定义介质的类型静态变量 Map<String,String> mimeTypeMapping;
4)定义方法private static void initMimeTypeMapping()
功能:初始化介质的类型
mimeTypeMapping = new HashMap<String,String>();
mimeTypeMapping.put(“html”, “text/html”);
mimeTypeMapping.put(“jpg”, “image/jpg”);
mimeTypeMapping.put(“gif”, “image/gif”);
mimeTypeMapping.put(“png”, “image/png”);
5)定义public static String getContentTypeByMime(String mime)方法
功能:根据给定的介质类型获取对应的Content-Type的值
return mimeTypeMapping.get(mime);
6)定义初始化的方法public static void init()
功能:完成HTTPContext初始化的功能
//1 初始化介质类型映射
initMimeTypeMapping();
7)定义静态块
功能:HttpContext加载的时候开始初始化
static{
//HttpContext加载的时候开始初始化
init();
}
2.在HttpResponse中进行代码重构
1)添加一个Map属性,用于保存响应在中的所有响应头信息.
private Map<String,String> headers = new HashMap<String,String>();
2)添加常用头的设置方法,共外界设置响应头:
public void setContentType(String contentType){
//把内容类型添加到头信息中
//this.headers.put("Content-Type", contentType);
}
public void setContentLength(int length){
//把响应文件的长度添加到头信息中
this.headers.put("Content-Length", length+"");
}
3)重新实现sendHeaders方法
private void sendHeaders(){
Set<String> set = headers.keySet();
for(String name:set){
String line = name+":"+headers.get(name);
println(line);//发送每一个头信息
}
println("");//单独发送CRLF表示头发送完毕
}
3.重构WebServer的run方法
String contentType = HttpContext.getContentTypeByMime(name);
//设置响应头Content-Type
response.setContentType(contentType);
response.setContentLength((int)file.length());
//设置响应正文
response.setEntity(file);
//响应客户端
response.flush();
测试:http://localhost:8080/myweb/index.html
第七个任务:
完成HttpRequest中对消息头的解析工作
1.HttpRequest中使用Map创建一个属性headers,用于保存所有客户端发送过来的消息头信息
private Map<String,String> headers = new HashMap<String,String>();
2.添加方法parseHeaders,用于解析所有的消息头.
public void paresHeader(InputStream in){
参考读请求的状态行代码
}
3.添加getHeader方法返回头信息
public Map<String, String> getHeaders() {
return headers;
}
测试:在服务器中测试,检查请求头信息是否正确
private String readLine(InputStream in) throws IOException{
//返回行字符串
}
调整代码:重复的代码定义方法,分别在parseRquestLine(in);
paresHeader(in);方法中调用
第八个任务:完成注册的功能
1.重构HttpRequest类
1)添加成员变量
//请求信息
private String requestLine;
//请求所附带的所有参数
private Map<String,String> params = new HashMap<String,String>();
2)定义paresUri():
功能完成:判读是否有?,如果有解析出来方法map集合中
3)在parseRquestLine方法中调用
private void parseRquestLine(InputStream in){
4)定义getParameter方法,和getRequestLine
public String getParameter(String name){
return params.get(name);
}
public String getRequestLine() {
return requestLine;
}
2.重构run方法
如果myweb/reg
处理注册功能,响应页面到客户端
if("/myweb/reg".equals(request.getRequestLine())){
//获取客户端数据
//写数据到数据文件
System.out.println("注册完毕!");
//响应页面到客户端
}
测试:
封装forward方法
第九个任务:读取web.xml中的介质
在项目目录中添加conf目录,并在里面
添加web.xml文件(该文件直接使用tomcat
根目录中conf目录中的这个文件)
web.xml文件中主要记录了HTTP协议中
头信息Content-Type对应的介质类型.
修改HttpContext对于介质类型映射的
初始化工作,将web.xml文件中的所有
介质类型解析出来并存入到Map中替代原
先写死的内容.使得我们的服务端可以
支持所有的介质类型.
对web.xml文件
从配置文件中读取介质类型,设置到mimeTypeMapping中
第十个任务:完成登录的功能,
1.登录的画面
2.提交请求到服务器:
1)获取表单数据
2)读数据文件,解析每一行的用户名和密码,与出入的参数做
做比较
3)如果登录成功,显示成功的画面login_ok.html
4)失败,显示失败的画面login_error.html
第十一个任务:
1.HttpServlet:抽象类 包名:cn.tedu.servlet
1)定义service(request,response)定义为抽象方法
2)定义forward方法
public abstract class HttpServlet {
public abstract void service(HttpRequest request,HttpResponse response);
}
public void forward(String path,HttpRequest request,HttpResponse response){
try {
File file = new File("webapps"+path);
String name = file.getName().substring(
file.getName().lastIndexOf(".")+1);
String contentType
= HttpContext.getContentTypeByMime(name);
//设置响应头Content-Type
response.setContentType(contentType);
response.setContentLength((int)file.length());
//设置响应正文
response.setEntity(file);
//响应客户端
response.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.LoginServlet extends HttpServlet
重写service方法,完成登录功能
3.RegServlet extends HttpServlet
重写service方法,完成注册功能
4.重构run
/*
* 先判断用户请求的是否为业务功能
*/
//是否请求注册功能
if("/myweb/reg".equals(request.getRequestLine())){
System.out.println("开始注册!");
RegServlet servlet = new RegServlet();
servlet.service(request, response);
}else if("/myweb/login".equals(request.getRequestLine())){
System.out.println("处理登录!");
LoginServlet servlet = new LoginServlet();
servlet.service(request, response);
}else{
/*
* 查看请求的该页面是否存在
*/
File file = new File("webapps"+request.getRequestLine());
if(file.exists()){
System.out.println("该文件存在!");
/*
* 响应客户端
*/
forward(request.getRequestLine(), request, response);
}else{
System.out.println("该文件不存在!");
}
}
第十二个任务:使用反射
创建一个Map,key为请求路径,value为处理该请求
的业务类某个Servlet的名字
ClientHandler当开始处理请求时使用请求路径作为
key去提取对应的Servlet的名字,然后基于反射机制
加载并实例化该Servlet,然后调用它的service方法
处理该业务.
这样一来,无论以后加什么新的业务,ClientHandler
都不用再进行修改.
改动的内容:
1:添加类ServletContext
该类负责存储服务端主要的配置信息
2:在ServerContext中添加一个Map,用来保存
请求与对应的Servlet之间的映射关系
并添加初始化该Map的方法
3:修改ClientHandler的run方法.基于Map并使用
反射方式加载Servlet并执行service处理业务
1.添加ServletContext类 包名:cn.tedu.core;
定义map 变量:public static Map<String,String> servletMapping;
定义 initServletMapping
/**
* 初始化Servlet的映射
*/
private static void initServletMapping(){
servletMapping = new HashMap<String,String>();
servletMapping.put("/myweb/login", "cn.tedu.servlets.LoginServlet");
servletMapping.put("/myweb/reg", "cn.tedu.servlets.RegServlet");
}
定义静态的init方法:
调用initServletMapping
定义静态块:
调用init方法
2.重构server的run方法
核心代码参考:
if(ServletContext.servletMapping.containsKey(
request.getRequestLine())){
String className = ServletContext.servletMapping.get(request.getRequestLine());
Class clazz = Class.forName(className);
HttpServlet servlet = (HttpServlet)clazz.newInstance();
servlet.service(request, response);
}
第十三个任务:定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<mappings>
<mapping
uri="/myweb/reg"
classname="com.tedu.servlets.RegServlet"
/>
<mapping
uri="/myweb/login"
classname="com.tedu.servlets.LoginServlet"
/>
</mappings>
解析配置文件:重构ServletContext类的initServletMapping()
private static void initServletMapping(){
servletMapping = new HashMap<String,String>();
封装配置文件的key,value
}
第十四个任务:解析post请求
在HTTPRequest类中添加解析post请求的方法
在构造方法中调用
private void parseContent(InputStream in){
//获取消息头中的Content-Type
String contentType
= this.headers.get("Content-Type");
if(contentType!=null && "application/x-www-form-urlencoded".equals(contentType)){
int contentLength = Integer.parseInt(
this.headers.get("Content-Length"));
try {
byte[] buf = new byte[contentLength];
in.read(buf);
String line = new String(buf);
System.out.println("form表单内容:"+line);
line = URLDecoder.decode(line, "UTF-8");
System.out.println("解码后的form表单内容:"+line);
解析过程同get请求
} catch (Exception e) {
e.printStackTrace();
}
}
}
把解析数据的代码封装成方法
parseParams(String line):void
String[] paramArr = line.split("&");
for(String paramStr : paramArr){
String[] para = paramStr.split("=");
if(para.length==2){
this.params.put(para[0], para[1]);
}else if(para.length==1){
this.params.put(para[0], "");
}
}
第十五个任务:根据请求方式调用doGet,doPost方法
1.重构HttpServer类
public void service(HttpRequest request,
HttpResponse response){
if(request.getMethod().equals(“GET”)){
this.doGet(request, response);
}else if(request.getMethod().equals(“POST”)){
this.doPost(request, response);
}else{
}
}
2.在类中定义doGet,doPost方法
public void doGet(HttpRequest request,
HttpResponse response){
}
public void doPost(HttpRequest request,
HttpResponse response){
}
2.代码实现
第一个任务实现
public class WebServer {
private ServerSocket serverSocket;
private WebServer(){
try {
serverSocket=new ServerSocket(8080);
System.out.println("服务器初始化成功...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start(){
while(true){
try {
System.out.println("等待客户端请求...");
Socket socket = serverSocket.accept();
System.out.println("接受一个客户端请求...");
//启动线程服务客户端
new Thread(new ClientHandler(socket)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
System.out.println("处理客户端请求");
}
}
public static void main(String[] args) {
new WebServer().start();
}
}
第二个任务实现
public class WebServer {
private ServerSocket serverSocket;
private WebServer(){
try {
serverSocket=new ServerSocket(8080);
System.out.println("服务器初始化成功...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start(){
while(true){
try {
System.out.println("等待客户端请求...");
Socket socket = serverSocket.accept();
System.out.println("接受一个客户端请求...");
//启动线程服务客户端
new Thread(new ClientHandler(socket)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
StringBuilder builder=new StringBuilder();
InputStream in=socket.getInputStream();
int d = -1;
char c1 = 0,c2=0;
while((d= in.read())!=-1){
c2 = (char)d;
if(c1==13&&c2==10){
break;
}
builder.append(c2);
c1 = c2;
}
//获取到请求的状态行
String line=builder.toString().trim();
System.out.println(line);
String data[] =line.split(" ");
//请求方式get,post
System.out.println(data[0]);
//请求的url
System.out.println(data[1]);
//请求的协议
System.out.println(data[2]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new WebServer().start();
}
}
最后一个任务实现
public class HttpContext {
public static final int CR=13;
public static final int LF=10;
private static Map<String,String> map;
private static void initMimeTypeMapping() throws Exception{
//map=new HashMap<String,String>();
map=new HashMap<String,String>();
SAXReader reader=new SAXReader();
Document document=reader.read("conf/web.xml");
Element root=document.getRootElement();
List<Element> list=root.elements("mime-mapping");
for(Element e:list){
String key=e.elementText("extension");
String value=e.elementText("mime-type");
map.put(key, value);
}
}
public static String getContentTypeByMime(String name){
return map.get(name);
}
public static void init() throws Exception{
initMimeTypeMapping();
}
static{
try {
init();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class HttpRequest {
//存表单数据
private Map<String,String> params=new HashMap<>();
private String requestLine;
private Map<String,String> headers=new HashMap<String,String>();
private String method;
private String url;
private String protocol;
public HttpRequest(InputStream in){
parseRequestLine(in);
parseHeader(in);
parseContent(in);
}
public void parseContent(InputStream in){
String contentType=headers.get("Content-Type");
if(contentType!=null&&contentType.equals("application/x-www-form-urlencoded")){
int len=Integer.parseInt(headers.get("Content-Length"));
try {
byte[] buffer=new byte[len];
in.read(buffer);
String paramsValues=new String(buffer);
parseParams(paramsValues);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void parseParams(String line){
String[] params1=line.split("&");
for(String str:params1){
String[] param=str.split("=");
if(param.length==2){
params.put(param[0], param[1]);
}else if(param.length==1){
params.put(param[0], "");
}
}
}
public void parseUrl(){
//1.判断是否有?
int index=this.url.indexOf("?");
if(index==-1){
//2.如果没有那么requestLine=url
requestLine=url;
}else{
//3.如果有:requestLine=url?之前的值
//把?后边的数据解析出来,设置到params集合中
requestLine=url.substring(0, index);
String datas=url.substring(index+1);
parseParams(datas);
}
}
private String readLine(InputStream in) throws IOException{
StringBuilder builder=new StringBuilder();
int d = -1;
char c1 = 0,c2=0;
while((d= in.read())!=-1){
c2 = (char)d;
if(c1==13&&c2==10){
break;
}
builder.append(c2);
c1 = c2;
}
//获取到请求的状态行
String line=builder.toString().trim();
return line;
}
public String getMethod() {
return method;
}
public String getUrl() {
return url;
}
public String getProtocol() {
return protocol;
}
//解析请求的状态行
public void parseRequestLine(InputStream in){
try {
String line=readLine(in);
System.out.println(line);
String data[] =line.split(" ");
if(data.length==3){
//请求方式get,post
//System.out.println(data[0]);
method=data[0];
//请求的url
//System.out.println(data[1]);
url=data[1];
parseUrl();
//请求的协议
//System.out.println(data[2]);
protocol=data[2];
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void parseHeader(InputStream in){
while(true){
try{
String line=readLine(in);
//读到空行
if("".equals(line)){
break;
}
int index=line.indexOf(":");
//消息头key
String key=line.substring(0,index);
//消息头url
String value=line.substring(index+1);
headers.put(key.trim(),value.trim());
}catch(Exception e){
e.getMessage();
}
}
}
public Map<String,String> getHeaders(){
return headers;
}
public String getParameter(String name){
return params.get(name);
}
public String getRequestLine(){
return requestLine;
}
}
public class HttpResponse {
private OutputStream out;
private File entity;
private Map<String,String> headers = new HashMap<String,String>();
public File getEntity() {
return entity;
}
public void setEntity(File entity) {
this.entity = entity;
}
public HttpResponse(OutputStream out) {
this.out = out;
}
public void println(String line) throws IOException{
out.write(line.getBytes("ISO8859-1"));
out.write(HttpContext.CR);
out.write(HttpContext.LF);
}
//响应状态行
public void sendStatusLine() throws IOException{
String line="HTTP/1.1 200 OK";
println(line);
}
public void sendRedirect(String url) throws IOException{
File file=new File("webapps"+url);
if(file.exists()){
//设置响应正文
this.setEntity(file);
//获取文件后缀 file.getName()获取到完整文件名
String name = file.getName().substring(
file.getName().lastIndexOf(".")+1);
String contentType = HttpContext.getContentTypeByMime(name);
//设置响应头Content-Type
this.setContentType(contentType);
this.setContentLength((int)file.length());
//响应客户端
flush();
}else{
System.out.println("文件不存在");}
}
//响应头信息
public void sendHeaders() throws IOException{
Set<String> set = headers.keySet();
for(String name:set){
String line = name+":"+headers.get(name);
println(line);//发送每一个头信息
}
println("");//单独发送CRLF表示头发送完毕
}
public void sendContent() throws IOException{
//响应文档内容
//定义数组
FileInputStream fileInput=new FileInputStream(entity);
byte[] buffer=new byte[(int) entity.length()];
//把数据读到数组中
fileInput.read(buffer);
//把数组中的数据写到输出流
out.write(buffer);
}
public void flush() throws IOException{
this.sendStatusLine();
this.sendHeaders();
this.sendContent();
}
//设置文档类型
public void setContentType(String contentType){
this.headers.put("Content-Type", contentType);
}
//设置文档长度
public void setContentLength(int length){
this.headers.put("Content-length", length+"");
}
public OutputStream getOut(){
return out;
}
}
public abstract class HttpServlet{
public void service(HttpRequest request,HttpResponse response){
if(request.getMethod().equals("GET")){
this.doGet(request,response);
}else if(request.getMethod().equals("POST")){
this.doPost(request,response);
}
}
public void doGet(HttpRequest request,HttpResponse response){
}
public void doPost(HttpRequest request,HttpResponse response){
}
}
public class LoginServlet extends HttpServlet{
@Override
public void doGet(HttpRequest request, HttpResponse response){
String username=request.getParameter("name");
String pw=request.getParameter("pw");
//把数据写到数据文件
try {
BufferedReader bf = new BufferedReader(new FileReader("user.txt"));
int flag=0;//表示用户名密码不正确
String str="";
while((str=bf.readLine())!=null){
String data[]=str.split("&");
if(data[0].equals(username)&&data[1].equals(pw)){
flag=1;
break;
}
}
if(flag==1){
response.sendRedirect("/myweb/loginOK.html");
}else{
response.sendRedirect("/myweb/loginERROR.html");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RegisterServlet extends HttpServlet{
@Override
public void doGet(HttpRequest request, HttpResponse response){
String username=request.getParameter("name");
String pw=request.getParameter("pw");
//把数据写到数据文件
PrintWriter printwriter;
try {
printwriter = new PrintWriter(new FileWriter("user.txt",true));
printwriter.println(username+"&"+pw);
printwriter.flush();
printwriter.close();
//admin&123123
//响应一个视图
response.sendRedirect("/myweb/registerOK.html");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void doPost(HttpRequest request, HttpResponse response){
doGet(request, response);
}
}
public class ServletContext {
public static Map<String,String> servletMapping=new HashMap<>();
public static void initServletMapping() throws Exception{
//读文件
SAXReader reader=new SAXReader();
Document document=reader.read("conf/ServletMapping.xml");
Element root=document.getRootElement();
List<Element> list=root.elements();
for(Element e:list){
String uri=e.attributeValue("uri");
String classname=e.attributeValue("classname");
servletMapping.put(uri,classname);
}
}
public static void init() throws Exception{
initServletMapping();
}
static{
try {
init();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ShowUserServlet extends HttpServlet {
public void doGet(HttpRequest request,HttpResponse response){
OutputStream out=response.getOut();
BufferedReader bf;
try {
bf = new BufferedReader(new FileReader("user.txt"));
int flag=0;//表示用户名密码不正确
String str="";
response.sendStatusLine();
response.sendHeaders();
out.write("<html>".getBytes());
out.write("<body>".getBytes());
while((str=bf.readLine())!=null){
String data[]=str.split("&");
out.write(data[0].getBytes());
out.write(" ".getBytes());
out.write(data[1].getBytes());
out.write("<br>".getBytes());
}
out.write("</body>".getBytes());
out.write("</html>".getBytes());
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void doPost(HttpRequest request,HttpResponse response){
doGet(request, response);
}
}
public class UpdateServlet extends HttpServlet {
public void doGet(HttpRequest request,HttpResponse response){
//1.获取表单数据
String username=request.getParameter("name");
String pw=request.getParameter("pw");
//把数据写到数据文件
try{
BufferedReader bf = new BufferedReader(new FileReader("user.txt"));
String str="";
List<String> data=new ArrayList<>();
while((str=bf.readLine())!=null){
data.add(str);
}
for(int i=0;i<data.size();i++){
String[] str1=data.get(i).split("&");
if(str1[0].equals(username)){
data.set(i, str1[0]+"&"+pw);
System.out.println(data.toString());
break;
}
}
bf.close();
//写数据到数据文件
PrintWriter printwriter=new PrintWriter("user.txt");
for(String s:data){
printwriter.println(s);
printwriter.flush();
}
printwriter.close();
//响应页面
response.sendRedirect("/myweb/index.html");
}catch(Exception e){
}
}
public void doPost(HttpRequest request,HttpResponse response){
doGet(request, response);
}
}
public class WebServer {
private ServerSocket serverSocket;
private WebServer(){
try {
serverSocket=new ServerSocket(8080);
System.out.println("服务器初始化成功...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start(){
while(true){
try {
System.out.println("等待客户端请求...");
Socket socket = serverSocket.accept();
System.out.println("接受一个客户端请求...");
//启动线程服务客户端
new Thread(new ClientHandler(socket)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
OutputStream out=socket.getOutputStream();
HttpRequest request=new HttpRequest(in);
HttpResponse response=new HttpResponse(out);
if(ServletContext.servletMapping.containsKey(request.getRequestLine())){
String className=ServletContext.servletMapping.get(request.getRequestLine());
Class clazz=Class.forName(className);
HttpServlet servlet=(HttpServlet)clazz.newInstance();
servlet.service(request,response);
}else{
response.sendRedirect(request.getUrl());
}
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new WebServer().start();
}
}
index.html
<body>
欢迎来到我的网站!<br>
<a href="register.html">注册</a><br>
<a href="login.html">登录</a><br>
<a href="showUser">显示用户信息</a><br>
<a href="update.html">修改</a><br>
<a href="delete.html">删除</a><br>
</body>
login.html
<body>
<form action="/myweb/login" method="get">
姓名:<input type="text" name="name"/><br>
密码:<input type="password" name="pw"/><br>
<input type="submit" value="登录"/>
</form>
</body>
ServletMapping.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- conf/ServletMapping.xml -->
<mappings>
<mapping
uri="/myweb/register"
classname="test16.RegisterServlet"
/>
<mapping
uri="/myweb/login"
classname="test16.LoginServlet"
/>
<mapping
uri="/myweb/showUser"
classname="test16.ShowUserServlet"
/>
<mapping
uri="/myweb/update"
classname="test16.UpdateServlet"
/>
<mapping
uri="/myweb/delete"
classname="test16.DeleteServlet"
/>
</mappings>