Java修炼——手写服务器项目
项目工程总览:
1.Dispatcher类(一个请求与响应就是一个Dispatcher)
package com.bjsxt.server;
import java.io.IOException;
import java.net.Socket;
import com.bjsxt.servlet.Servlet;
import com.bjsxt.util.IOCloseUtil;
/**
* 一个请求与响应就是一个Dispatcher
* @author Administrator
*
*/
public class Dispatcher implements Runnable {
private Request req;
private Response rep;
private Socket client;
private int code=200;//状态码
//构造方法初始化属性
public Dispatcher(Socket client) {
//将局部变量的值赋给成员变量
this.client=client;
try {
req=new Request(this.client.getInputStream());
rep=new Response(this.client.getOutputStream());
} catch (IOException e) {
code=500;
return ;
}
}
@Override
public void run() {
//根据不同的url创建指定的Servlet对象
//System.out.println(req.getUrl());
Servlet servlet=WebApp.getServlet(req.getUrl());
if (servlet==null) {
this.code=404;
}else{
//调用相应的Servlet中的service方法
try {
servlet.service(req,rep);
} catch (Exception e) {
this.code=500;
}
}
//将响应结果推送到客户机的浏览器
rep.pushToClient(code);
IOCloseUtil.closeAll(client);
}
}
2.Entity(实体类)
package com.bjsxt.server;
/**
* <servlet>
<servlet-name>login</servlet-name>
<serlvet-class>com.bjsxt.servlet.LoginServlet</serlvet-class>
</servlet>
* @author Administrator
*
*/
public class Entity { /**servlet-name和一个servlet-name所对应的一个实体类*/
private String name;//servlet-name
private String clazz;//servlet-class
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public Entity(String name, String clazz) {
super();
this.name = name;
this.clazz = clazz;
}
public Entity() {
super();
}
}
3.Mapping类(映射关系,多个路径访问共享资源)
package com.bjsxt.server;
import java.util.ArrayList;
import java.util.List;
/**
* <servlet-mapping>
<serlvet-name>login</serlvet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/log</url-pattern>
</servlet-mapping>
* @author Administrator
*
*/
public class Mapping {//映射关系,多个路径访问共享资源
private String name;//servlet-name
private List<String> urlPattern;//url-pattern
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getUrlPattern() {
return urlPattern;
}
public void setUrlPattern(List<String> urlPattern) {
this.urlPattern = urlPattern;
}
public Mapping(){
urlPattern=new ArrayList<String>();
}
public Mapping(String name, List<String> urlPattern) {
super();
this.name = name;
this.urlPattern = urlPattern;
}
}
4.Request类
package com.bjsxt.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Request {/*请求*/
private InputStream is;//输入流
private String requestInfo;//请求字符串,请求方式,请求的路径,参数,协议,协议版本,请求的正文。。。
private String method;//请求的方式
private String url;//请求的url
public String getUrl() {
return url;
}
//输入框的name为key,值为value
/*
* key: username value :bjsxt
* key:pwd value:123
* key:hobby value :read,ball
* */
private Map<String,List<String>> parametermapValues;//参数
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法,初始化属性
public Request() {
parametermapValues=new HashMap<String,List<String>>();
method="";
url="";
requestInfo="";
}
public Request(InputStream is){
this();//调用本类无参的构造方法
this.is=is;
try {
byte [] buf=new byte[20480];
int len=this.is.read(buf);
requestInfo=new String(buf,0,len);
} catch (IOException e) {
return;
}
//调用本类中的分解请求信息的方法
this.parseRequestInfo();
}
//分解请求信息的方法
/**
* 请求方式
* 请求路径
* 请求的参数
*
*/
private void parseRequestInfo(){
String paraString="";//用于存储请求参数
//获取请求参数的第一行
String firstLine=requestInfo.substring(0, requestInfo.indexOf(CRLF)).trim();//从0开始,到第一个换行的位置
//分解出请求方式
int index=firstLine.indexOf("/");
this.method=firstLine.substring(0, index).trim();
//分解url ,get可能包含参数,也可能不包含参数post
String urlString= firstLine.substring(index,firstLine.indexOf("HTTP/")).trim();
//判断请求方式是GET还 是POST
if("get".equalsIgnoreCase(this.method)){ //包含请求参数
if (urlString.contains("?")) {
String [] urlArray=urlString.split("\\?");
this.url=urlArray[0];
paraString=urlArray[1];
}else{
this.url=urlString;
}
}else{//post不包含请求参数
this.url=urlString;
paraString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
}
if (paraString.equals("")) {
return;
}
//请求参数
//System.out.println(paraString);
//调用本类的中的分析请求参数的方法
this.parseParam(paraString);
}
//用于测试
/*public void show(){
System.out.println(this.url);
System.out.println(this.method);
}*/
//username=fdsaf&pwd=fdasf&hobby=ball&hobby=read
/**
* username=bjsxt
* pwd=123
* hobby=ball
* hobby=paint
*
* username=
* @param prarString
*/
private void parseParam(String paramString){
String [] token=paramString.split("&");
for(int i=0;i<token.length;i++){
String keyValues=token[i]; //username=fasaf
//继续分割
String[] keyValue=keyValues.split("="); //username=
if (keyValue.length==1) {
keyValue=Arrays.copyOf(keyValue, 2);
keyValue[1]=null;
}
//转成Map集合
String key=keyValue[0].trim();
String value=keyValue[1]==null?null:decode(keyValue[1].trim(), "utf-8");
//放到参数的集合中存储
if (!parametermapValues.containsKey(key)) {
parametermapValues.put(key, new ArrayList<String>());
}
List<String> values=parametermapValues.get(key);
values.add(value);
}
}
/**
* 编写根据表单元素的name获取多个对应的值
*
*/
public String [] getParamterValues(String name){
List<String> values=parametermapValues.get(name);
if (values==null) {
return null;
}else{
return values.toArray(new String [0]);
}
}
/**
* 根据表单元素的name获取单个值
*
*/
public String getParameter(String name){
//调用根据名称获取多个值的方法
String [] values=getParamterValues(name);
if (values==null) {
return null;
}else{
return values[0];
}
}
//用于测试
public static void main(String[] args) {
Request req=new Request();
//调用分解参数的方法
req.parseParam("username=%E5%8C%97%E4%BA%AC%E5%B0%9A%E5%AD%A6%E5%A0%82&pwd=123&hobby=ball&hobby=paint");
System.out.println(req.parametermapValues);
//调用获取多个值的方法
String [] str=req.getParamterValues("hobby");
for (String string : str) {
System.out.println(string);
}
//调用获取单个值的方法
System.out.println(req.getParameter("pwd"));
}
//处理中文,因为浏览器对中文进行了编码,进行解码
private String decode(String value, String code){
try {
return URLDecoder.decode(value,code);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
5.Response类
package com.bjsxt.server;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import com.bjsxt.util.IOCloseUtil;
public class Response {//响应
private StringBuilder headInfo;//响应头
private StringBuilder content;//响应内容
private int length;//响应内容的长度
//流
private BufferedWriter bw;
//两个常量,换行和空格
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法
public Response() {
headInfo=new StringBuilder();
content=new StringBuilder();
}
//带参构造方法
public Response(OutputStream os){
this();//调用本类的无参构造方法
try {
bw=new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
} catch (UnsupportedEncodingException e) {
headInfo=null;
}
}
//构造正文部分
public Response print(String info){
content.append(info);
try {
length+=info.getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
}
public Response println(String info){
content.append(info).append(CRLF);
try {
length+=(info+CRLF).getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
}
//构造响应头
private void createHeadInfo(int code){
headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch (code) {
case 200:
headInfo.append("OK");
break;
case 500:
headInfo.append("SERVER ERROR");
break;
default:
headInfo.append("NOT FOUND");
break;
}
headInfo.append(CRLF);
headInfo.append("Content-Type:text/html;charset=utf-8").append(CRLF);
headInfo.append("Content-Length:"+length).append(CRLF);
headInfo.append(CRLF);
}
/**
* 推送到客户机的浏览器
* @param code
*/
public void pushToClient(int code){
if (headInfo==null) {
code=500;
}
try {
//调用本类中的构造响应头
this.createHeadInfo(code);
bw.write(headInfo.toString());
bw.write(content.toString());
bw.flush();
this.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void close(){
IOCloseUtil.closeAll(bw);
}
}
6.Server类(服务器,用于启动和停止服务)
package com.bjsxt.server;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import com.bjsxt.servlet.Servlet;
import com.bjsxt.util.IOCloseUtil;
public class Server {//服务器,用于启动和停止服务
private ServerSocket server;
private boolean isShutDown=false;//默认没有出错
public static void main(String[] args) {
Server server=new Server();//创建服务器对象
server.start();
}
public void start(){
this.start(8888);
}
public void start(int port){
try {
server=new ServerSocket(port);
this.receive(); //调用接收请求信息的方法
} catch (IOException e) {
isShutDown=true;
}
}
private void receive() {
try {
while(!isShutDown){
//(1)监听
Socket client=server.accept();
//创建线程类的对象
Dispatcher dis=new Dispatcher(client);
//创建线程的代理类,并启动线程
new Thread(dis).start();
}
} catch (IOException e) {
this.stop();//关闭服务器
}
}
public void stop(){
isShutDown=true;
IOCloseUtil.closeAll(server);
}
}
7.ServletContext类(Entity与Mapping的映射关系)
package com.bjsxt.server;
import java.util.HashMap;
import java.util.Map;
/**
* Servlet上下用,就是一个容器,
* @author Administrator
*
*/
public class ServletContext { //Entity与Mapping的映射关系
private Map<String,String> servlet;//key是servlet-name (Entity中的name),值serlvet-class Entity中的clazz
private Map<String,String> mapping;//key是url-pattern (Mapping中的List集合中的每一个元素),value是serlvet-name,是Mapping中的name
public Map<String, String> getServlet() {
return servlet;
}
public void setServlet(Map<String, String> servlet) {
this.servlet = servlet;
}
public Map<String, String> getMapping() {
return mapping;
}
public void setMapping(Map<String, String> mapping) {
this.mapping = mapping;
}
public ServletContext() {
servlet=new HashMap<String,String>();
mapping=new HashMap<String,String>();
}
}
8.WebApp类
package com.bjsxt.server;
import java.util.List;
import java.util.Map;
import com.bjsxt.servlet.Servlet;
public class WebApp {//App的意思是应用程序
private static ServletContext contxt;
static{
contxt=new ServletContext();
//分别获取对应关系的Map集合
Map<String,String> servlet=contxt.getServlet();
Map<String,String> mapping=contxt.getMapping();
//创建解析XML文件对象
WebDom4j web=new WebDom4j();
web.parse(web.getDocument());//解析xml
//获取解析XML之后的List集合
List<Entity> entityList=web.getEntityList();
List<Mapping> mappingList=web.getMappingList();
//将List集合中的数据存储到Map集合
for (Entity entity : entityList) {
servlet.put(entity.getName(), entity.getClazz());
}
// System.out.println(servlet);
for( Mapping map:mappingList){
//遍历url-pattern的集合
List<String> urlPattern=map.getUrlPattern();
for(String s:urlPattern){
mapping.put(s, map.getName());
}
}
//System.out.println(mapping);
}
/**
* 根据url创建不同的Servlet对象
* @param url
* @return
*/
public static Servlet getServlet(String url){
if (url==null||url.trim().equals("")) {
return null;
}
//调用无参构造方法创建Servlet对象
try {
//如果url正确
//根据url的key获取servlet-name的值 /log=login, /reg=register
String servletName=contxt.getMapping().get(url);
//根据servletName得到对应的servlet-class
String servletClass=contxt.getServlet().get(servletName); //得到的是一个完整个的包名+类的字符串
//使用反射创建 Servlet对象
Class<?> clazz=Class.forName(servletClass);
Servlet servlet = (Servlet) clazz.newInstance();
return servlet;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//测试
public static void main(String[] args) {
System.out.println(getServlet("/log"));
System.out.println(getServlet("/login"));
}
}
9.WebDom4j 类(用于解析xml)
package com.bjsxt.server;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class WebDom4j {//用于解析XML
private List<Entity> entityList;//用于存储是N多Entity,而每一个Entity都是servlet-name与servlet-class
private List<Mapping> mappingList;//用于存储N多Mapping,而每一个Mapping都是一个servlet-name与N多个url-pattern
public List<Entity> getEntityList() {
return entityList;
}
public void setEntityList(List<Entity> entityList) {
this.entityList = entityList;
}
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
}
//构造方法
public WebDom4j() {
entityList=new ArrayList<Entity>();
mappingList=new ArrayList<Mapping>();
}
//获取Document对象的方法
public Document getDocument(){
try {
//(1)创建SAXReader对象
SAXReader reader=new SAXReader();
//(2)调用read方法
return reader.read(new File("src/WEB_INFO/web.xml"));
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void parse(Document doc){
//(1)获取根元素
Element root=doc.getRootElement(); //web-app
//(2)获取servlet子元素
for(Iterator<Element> ite=root.elementIterator("servlet");ite.hasNext();){
Element subElement=ite.next();//得到每一个servlet
//创建一个实体类
Entity ent=new Entity(); //用于存储servlet-name与servlet-class
for(Iterator<Element> subIte=subElement.elementIterator();subIte.hasNext();){
Element ele=subIte.next(); //可能是servlet-name,也可能是servlet-class
if("servlet-name".equals(ele.getName())){
ent.setName(ele.getText()); //给实体类中的name赋值
}else if("serlvet-class".equals(ele.getName())){
ent.setClazz(ele.getText());
}
}
//将Entity添加到集合中
entityList.add(ent);
}
//测试
/**for (Entity entity : entityList) {
System.out.println(entity.getName()+"\t"+entity.getClazz());
}*/
//解析servlet-mapping
for(Iterator<Element> ite=root.elementIterator("servlet-mapping");ite.hasNext();){
Element subEle=ite.next();//得到每一个servlet-mapping
//创建一个Mapping类的对象
Mapping map=new Mapping();
//解析servlet-mapping下的子元素
for(Iterator<Element> subIte=subEle.elementIterator();subIte.hasNext();){
Element ele=subIte.next(); //servlet-name,也有可能是url-pattern
if("serlvet-name".equals(ele.getName())){
map.setName(ele.getText());
}else if("url-pattern".equals(ele.getName())){
//获取集合对象,调用集合对象的添加方法,添加元素素
map.getUrlPattern().add(ele.getText());
}
}
//Mapping添加到集合中
mappingList.add(map);
}
//测试
/*for (Mapping m : mappingList) {
System.out.println(m.getName());
for(String s:m.getUrlPattern()){
System.out.println(s);
}
}*/
}
//用于测试
public static void main(String[] args) {
WebDom4j web=new WebDom4j();
web.parse(web.getDocument());
}
}
10.FaviconServlet类
package com.bjsxt.servlet;
import com.bjsxt.server.Request;
import com.bjsxt.server.Response;
public class FaviconServlet extends Servlet {
@Override
public void doGet(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void doPost(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub
}
}
11.LoginServlet类
package com.bjsxt.servlet;
import com.bjsxt.server.Request;
import com.bjsxt.server.Response;
public class LoginServlet extends Servlet {
@Override
public void doGet(Request req, Response rep) throws Exception {
//获取请求参数
String name=req.getParameter("username");
String pwd=req.getParameter("pwd");
if(this.login(name, pwd)){
//调用响应中的构建内容的方
rep.println(name+"登录成功");
}else{
rep.println(name+"登录失败,对不起,账号或密码不正确");
}
}
private boolean login(String name,String pwd){
if ("bjsxt".equals(name)&&"123".equals(pwd)) {
return true;
}
return false;
}
@Override
public void doPost(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub
}
}
12.Servlet(是所有的请求的Servlet的父类)
package com.bjsxt.servlet;
import com.bjsxt.server.Request;
import com.bjsxt.server.Response;
public abstract class Servlet { //是所有的请求的Servlet的父类
public void service(Request req,Response rep) throws Exception{
this.doGet( req, rep);
this.doPost( req, rep);
}
public abstract void doGet(Request req,Response rep) throws Exception;
public abstract void doPost(Request req,Response rep) throws Exception;
}
13.IOCloseUtil类(用于关闭流的工具类)
package com.bjsxt.util;
import java.io.Closeable;
import java.io.IOException;
public class IOCloseUtil {//用于关闭流
public static void closeAll(Closeable...close){
for (Closeable closeable : close) {
if (closeable!=null) {
try {
closeable.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
14.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<serlvet-class>com.bjsxt.servlet.LoginServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>login</serlvet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/log</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>register</servlet-name>
<serlvet-class>com.bjsxt.servlet.RegisterServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>register</serlvet-name>
<url-pattern>/reg</url-pattern>
<url-pattern>/register</url-pattern>
<url-pattern>/regis</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>favicon</servlet-name>
<serlvet-class>com.bjsxt.servlet.FaviconServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>favicon</serlvet-name>
<url-pattern>/favicon.ico</url-pattern>
</servlet-mapping>
</web-app>
15.Request
package com.bjsxt.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Request {/*请求*/
private InputStream is;//输入流
private String requestInfo;//请求字符串,请求方式,请求的路径,参数,协议,协议版本,请求的正文。。。
private String method;//请求的方式
private String url;//请求的url
public String getUrl() {
return url;
}
//输入框的name为key,值为value
/*
* key: username value :bjsxt
* key:pwd value:123
* key:hobby value :read,ball
* */
private Map<String,List<String>> parametermapValues;//参数
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法,初始化属性
public Request() {
parametermapValues=new HashMap<String,List<String>>();
method="";
url="";
requestInfo="";
}
public Request(InputStream is){
this();//调用本类无参的构造方法
this.is=is;
try {
byte [] buf=new byte[20480];
int len=this.is.read(buf);
requestInfo=new String(buf,0,len);
} catch (IOException e) {
return;
}
//调用本类中的分解请求信息的方法
this.parseRequestInfo();
}
//分解请求信息的方法
/**
* 请求方式
* 请求路径
* 请求的参数
*
*/
private void parseRequestInfo(){
String paraString="";//用于存储请求参数
//获取请求参数的第一行
String firstLine=requestInfo.substring(0, requestInfo.indexOf(CRLF)).trim();//从0开始,到第一个换行的位置
//分解出请求方式
int index=firstLine.indexOf("/");
this.method=firstLine.substring(0, index).trim();
//分解url ,get可能包含参数,也可能不包含参数post
String urlString= firstLine.substring(index,firstLine.indexOf("HTTP/")).trim();
//判断请求方式是GET还 是POST
if("get".equalsIgnoreCase(this.method)){ //包含请求参数
if (urlString.contains("?")) {
String [] urlArray=urlString.split("\\?");
this.url=urlArray[0];
paraString=urlArray[1];
}else{
this.url=urlString;
}
}else{//post不包含请求参数
this.url=urlString;
paraString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
}
if (paraString.equals("")) {
return;
}
//请求参数
//System.out.println(paraString);
//调用本类的中的分析请求参数的方法
this.parseParam(paraString);
}
//用于测试
/*public void show(){
System.out.println(this.url);
System.out.println(this.method);
}*/
//username=fdsaf&pwd=fdasf&hobby=ball&hobby=read
/**
* username=bjsxt
* pwd=123
* hobby=ball
* hobby=paint
*
* username=
* @param prarString
*/
private void parseParam(String paramString){
String [] token=paramString.split("&");
for(int i=0;i<token.length;i++){
String keyValues=token[i]; //username=fasaf
//继续分割
String[] keyValue=keyValues.split("="); //username=
if (keyValue.length==1) {
keyValue=Arrays.copyOf(keyValue, 2);
keyValue[1]=null;
}
//转成Map集合
String key=keyValue[0].trim();
String value=keyValue[1]==null?null:decode(keyValue[1].trim(), "utf-8");
//放到参数的集合中存储
if (!parametermapValues.containsKey(key)) {
parametermapValues.put(key, new ArrayList<String>());
}
List<String> values=parametermapValues.get(key);
values.add(value);
}
}
/**
* 编写根据表单元素的name获取多个对应的值
*
*/
public String [] getParamterValues(String name){
List<String> values=parametermapValues.get(name);
if (values==null) {
return null;
}else{
return values.toArray(new String [0]);
}
}
/**
* 根据表单元素的name获取单个值
*
*/
public String getParameter(String name){
//调用根据名称获取多个值的方法
String [] values=getParamterValues(name);
if (values==null) {
return null;
}else{
return values[0];
}
}
//用于测试
public static void main(String[] args) {
Request req=new Request();
//调用分解参数的方法
req.parseParam("username=%E5%8C%97%E4%BA%AC%E5%B0%9A%E5%AD%A6%E5%A0%82&pwd=123&hobby=ball&hobby=paint");
System.out.println(req.parametermapValues);
//调用获取多个值的方法
String [] str=req.getParamterValues("hobby");
for (String string : str) {
System.out.println(string);
}
//调用获取单个值的方法
System.out.println(req.getParameter("pwd"));
}
//处理中文,因为浏览器对中文进行了编码,进行解码
private String decode(String value, String code){
try {
return URLDecoder.decode(value,code);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Java修炼——手写服务器项目的更多相关文章
- java24 手写服务器最终版本
手写服务器最终版本; <?xml version="1.0" encoding="UTF-8"?> <web-app> <serv ...
- java 从零开始手写 RPC (04) -序列化
序列化 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何实 ...
- java 从零开始手写 RPC (05) reflect 反射实现通用调用之服务端
通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...
- java 从零开始手写 RPC (03) 如何实现客户端调用服务端?
说明 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 写完了客户端和服务端,那么如何实现客户端和服务端的 ...
- java 从零开始手写 RPC (07)-timeout 超时处理
<过时不候> 最漫长的莫过于等待 我们不可能永远等一个人 就像请求 永远等待响应 超时处理 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RP ...
- 通过手写服务器的方式,立体学习Http
前言 Http我们都已经耳熟能详了,而关于Http学习的文章网上有很多,各个知识点的讲解也可说是深入浅出.然而,学习过后,我们对Http还是一知半解.问题出在了哪? Http是一个客户机与服务器之间的 ...
- java - day015 - 手写双向链表, 异常(续), IO(输入输出)
类的内存分配 加载到方法区 对象在堆内存 局部变量在栈内存 判断真实类型,在方法区加载的类 对象.getClass(); 类名.class; 手写双向链表 package day1501_手写双向链表 ...
- 不使用tomcat,仅适用javaSE手写服务器--模拟登陆
1.搭建框架 我们只是简单模拟,框架简单分三个模块 a,服务器端server包 b,servlet,根据不同的请求url,利用反射生产对应的servlet c,IO工具包,用来关闭IO流 d,编写we ...
- Java精进-手写持久层框架
前言 本文适合有一定java基础的同学,通过自定义持久层框架,可以更加清楚常用的mybatis等开源框架的原理. JDBC操作回顾及问题分析 学习java的同学一定避免不了接触过jdbc,让我们来回顾 ...
随机推荐
- PHP判断是否为手机端的方法
PHP判断是否为手机端的方法 private function ismobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset($_SERVER['HT ...
- K8S入门系列之集群yum安装(一)
kubernetes master 节点包含的组件: 1.kube-apiserver :集群核心,集群API接口.集群各个组件通信的中枢:集群安全控制: 2.kube-scheduler: 集群调度 ...
- markdown文档
标题 #加空格# 加粗 *加粗* 斜体 **斜体** 斜体加粗 ***斜体加粗*** 删除线 ~~删除线~~~ 引用 >引用 分割线 --- 超链接[题目](网址) 列表 -加空格 列表内容 ...
- Docker学习-VMware Workstation 本地多台虚拟机互通,主机网络互通,解决name or service not known
NAT网络通用配置 测试连接 主机到虚拟机 虚拟机到虚拟机 ,虚拟机到外网 CentOS,提示name or service not known 设置DNS服务器 vi /etc/resolv.co ...
- C++中对C的扩展学习新增语法——const
Const Const在C语言和C++语言中连接属性不一样,C语言默认是外部连接,如果需要内部连接,需要显示写上static.而在C++中默认是内部连接,如果希望其编程外部变量,需要显示写上exte ...
- nyoj 75-日期计算 (闰年与平年的判断)
75-日期计算 内存限制:64MB 时间限制:3000ms 特判: No 通过数:19 提交数:31 难度:1 题目描述: 如题,输入一个日期,格式如:2010 10 24 ,判断这一天是这一年中的第 ...
- Centos上通过shell脚本备份数据库
#!/bin/bash ds=`` list=`date +%Y`/`date +%m` dname="callme" eval "mkdir -p $list" ...
- 20191031-3 beta week 1/2 Scrum立会报告+燃尽图 01
此作业要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/9911] 一.小组情况 队名:扛把子 组长:孙晓宇 组员:宋晓丽 梁梦瑶 ...
- day 36 html的补充
参考博客:https://www.cnblogs.com/majj/p/9062540.html 内容回顾: 0.浏览器 1.标签 - 行内标签 a span i em strong b.label ...
- 个人收藏--未整理—C# 上传下载文件
Winform下载文件 /// <summary> /// 下载文件 /// </summary> /// <param name="URL"> ...