赞
踩
本课程的难度较高,需要将Servlet原理和IO课程全部学完。
自定义servlet需要实现@WebServlet并且实现name和urlMapping
重启进行访问
http://localhost:8090/myServlet
重启进行访问
http://localhost:8090/index.html
在SearchClassUtil类当中可以设置servlet包的位置
我们本次设计的tomcat能够将用户请求的资源进行返回
资源分类
1.静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源。
静态资源可以直接被浏览器解析。
*例如:html/css/jpg/js..
2.动态资源:每个用户访问相同的资源后,得到的结果可能不一样,称为动态资源。
动态资源被访问后需要先转化为静态资源,再返回给浏览器,浏览器进行解析
*例如:servlet/jsp ...
创建HttpServletRequest接口
public interface HttpServletRequest {
public String getUrl();
public void setUrl(String url);
public String getMethod();
public void setMethod(String method);
}
创建HttpServletResponse接口
public interface HttpServletResponse {
void write(String context) throws IOException;
}
/** * class HttpServlet */ public abstract class HttpServlet { public abstract void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException; public abstract void doPost(HttpServletRequest request,HttpServletResponse response); /** * HttpServlet 实现service方法 */ public void service(HttpServletRequest request,HttpServletResponse response) throws IOException { if("GET".equals(request.getMethod())){ doGet(request,response); }else if("POST".equals(request.getMethod())){ doPost(request,response); } } }
创建工具类,描述返回的信息
/** * 返回信息工具类 */ public class ResponseUtil { public static final String responseHeader200 = "HTTP/1.1 200 \r\n"+ "Content-Type:text/html \r\n"+"\r\n"; public static String getResponseHeader404(){ return "HTTP/1.1 404 \r\n"+ "Content-Type:text/html \r\n"+"\r\n" + "404"; } public static String getResponseHeader200(String context){ return "HTTP/1.1 200 \r\n"+ "Content-Type:text/html \r\n"+"\r\n" + context; } }
@Retention(RetentionPolicy.RUNTIME) //注解的生命周期,运行期间保留
@Target(value = {ElementType.TYPE,ElementType.FIELD}) // 该注解作用在类上边
public @interface WebServlet {
String urlMapping() default ""; //自定义的servlet路径
}
创建ServletConfig存储注解信息
/** * 注解上的信息 */ public class ServletConfig { private String urlMapping; //2.url private String classpath; //3.类的全路径名 public ServletConfig(String urlMapping,String classpath){ this.classpath = classpath; this.urlMapping = urlMapping; } public String getUrlMapping() { return urlMapping; } public void setUrlMapping(String urlMapping) { this.urlMapping = urlMapping; } public String getClasspath() { return classpath; } public void setClasspath(String classpath) { this.classpath = classpath; } }
工具类,获取servlet的全路径名
/** * 扫描指定包,获取该包下所有的类的全路径信息 */ public class SearchClassUtil { public static List<String> classPaths = new ArrayList<String>(); public static List<String> searchClass(){ //需要扫描的包名 String basePack = "com.qcby.webapp"; //将获取到的包名转换为路径 String classPath = SearchClassUtil.class.getResource("/").getPath(); basePack = basePack.replace(".", File.separator); String searchPath = classPath + basePack; doPath(new File(searchPath),classPath); //这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象 return classPaths; } /** * 该方法会得到所有的类,将类的绝对路径写入到classPaths中 * @param file */ private static void doPath(File file,String classpath) { if (file.isDirectory()) {//文件夹 //文件夹我们就递归 File[] files = file.listFiles(); for (File f1 : files) { doPath(f1,classpath); } } else {//标准文件 //标准文件我们就判断是否是class文件 if (file.getName().endsWith(".class")) { String path = file.getPath().replace(classpath.replace("/","\\"). replaceFirst("\\\\",""),"").replace("\\","."). replace(".class",""); //如果是class文件我们就放入我们的集合中。 classPaths.add(path); } } } public static void main(String[] args) { List<String> classes = SearchClassUtil.searchClass(); for (String s: classes ) { System.out.println(s); } } }
创建ServletConfigMapping生成servlet容器
/** * servlet容器 */ public class ServletConfigMapping { //定义一个集合用来存储自定义servlet的配置信息 private static List<ServletConfig> configs = new ArrayList<>(); //定义servlet容器 public static Map<String,Class<HttpServlet>> classMap = new HashMap<>(); //解析注解 ---- 为了实现当mytomcat类启动的时候就将webapp下边所有的类的注解信息获取到我们需要写一个static代码块 static { //1.获取webapp包下有哪些类 List<String> classPaths = SearchClassUtil.searchClass(); //2.获取类的注解信息 for (String classpath: classPaths) { try { //利用反射获取类的注解信息 getMessage(classpath); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } //利用反射获取类的注解信息 public static void getMessage(String classPath) throws ClassNotFoundException { Class clazz = Class.forName(classPath); //注解对象 WebServlet webServlet = (WebServlet) clazz.getDeclaredAnnotation(WebServlet.class); //将解析的信息放入到集合当中 configs.add(new ServletConfig(webServlet.urlMapping(),classPath)); } //初始化类容器 public static void initServlet() throws ClassNotFoundException { for (ServletConfig servletConfig: configs) { // 将servlet对象和 url请求地址放入到 map集合当中去 classMap.put(servletConfig.getUrlMapping(), (Class<HttpServlet>) Class.forName(servletConfig.getClasspath())); } } }
创建Request类接收前端数据并实现HttpServletRequest接口
public class Request implements HttpServletRequest { //请求的地址 private String url; //请求的方式 private String Method; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return Method; } public void setMethod(String method) { Method = method; } }
创建Response类用来实现HttpServletResponse
public class Response implements HttpServletResponse { //输出流 private OutputStream outputStream; public Response(OutputStream outputStream){ this.outputStream = outputStream; } /** * 返回动态资源 * @param context */ public void write(String context) throws IOException { outputStream.write(context.getBytes()); } /** * 返回静态资源 */ public void writeHtml(String path) throws Exception { String resourcesPath = FileUtil.getResoucePath(path); File file = new File(resourcesPath); if(file.exists()){ //静态文件存在 System.out.println("静态文件存在"); FileUtil.writeFile(file,outputStream); }else { System.out.println("静态文件不存在"); write(ResponseUtil.getResponseHeader404()); } } }
工具类获取静态资源
/** * 该类的主要作用是进行读取文件 */ public class FileUtil { public static boolean witeFile(InputStream inputStream, OutputStream outputStream){ boolean success = false ; BufferedInputStream bufferedInputStream ; BufferedOutputStream bufferedOutputStream; try { bufferedInputStream = new BufferedInputStream(inputStream); bufferedOutputStream = new BufferedOutputStream(outputStream); bufferedOutputStream.write(ResponseUtil.responseHeader200.getBytes()); int count = 0; while (count == 0){ count = inputStream.available(); } int fileSize = inputStream.available(); long written = 0; int beteSize = 1024; byte[] bytes = new byte[beteSize]; while (written < fileSize){ if(written + beteSize > fileSize){ beteSize = (int)(fileSize - written); bytes = new byte[beteSize]; } bufferedInputStream.read(bytes); bufferedOutputStream.write(bytes); bufferedOutputStream.flush(); written += beteSize; } success = true; } catch (IOException e) { e.printStackTrace(); } return success; } public static boolean writeFile(File file,OutputStream outputStream) throws Exception{ return witeFile(new FileInputStream(file),outputStream); } public static String getResoucePath(String path){ String resource = FileUtil.class.getResource("/").getPath(); return resource + "\\" + path; } }
获取输入流信息,获取访问方式和访问地址
public class MyTomcat { Request request = new Request(); //启动tomcat主方法 public void startUp() throws IOException, ClassNotFoundException { //1.定义socket对象,监听8080端口 ServerSocket serverSocket = new ServerSocket(8080); while (true){ Socket socket = serverSocket.accept();//等待接收 BIO System.out.println("有用户请求过来了....."); // 给每一个请求都开启一个线程处理信息 new Thread(new Runnable() { @Override public void run() { try { 杜凯(socket); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } //2.创建出入流,读取用户请求信息 public void 杜凯(Socket socket) throws Exception { //创建输入流 InputStream inputStream = socket.getInputStream(); //解析输入流 getInputStream(inputStream); socket.close(); } public void getInputStream(InputStream inputStream) throws IOException { //将bit流转为文字信息 int count = 0; while (count == 0){ count = inputStream.available(); } byte[] bytes = new byte[count]; inputStream.read(bytes); String Context = new String(bytes); System.out.println(Context); //解析数据 if(Context.equals("")){ System.out.println("你输入了一个空请求"); }else { String firstLine = Context.split("\\n")[0]; //根据换行来获取第一行数据 request.setUrl(firstLine.split("\\s")[1]); request.setMethod(firstLine.split("\\s")[0]); } } public static void main(String[] args) throws IOException, ClassNotFoundException { MyTomcat myTomcat = new MyTomcat(); myTomcat.startUp(); } }
加载tomcat启动配置,判断访问内容时否是静态资源
public class MyTomcat { Request request = new Request(); /** * servlet分发器 * @param request * @throws InstantiationException * @throws IllegalAccessException */ public void dispatch(Request request, Response response) throws Exception { //根据请求的信息来获取servlet类 Class<HttpServlet> servletClass = ServletConfigMapping.classMap.get(request.getUrl()); //真实的创建servlet对象 if(servletClass !=null){ HttpServlet servlet = servletClass.newInstance(); servlet.service(request,response); }else { response.write(ResponseUtil.getResponseHeader404()); } } //启动tomcat主方法 public void startUp() throws IOException, ClassNotFoundException { //加载servlet信息 ServletConfigMapping.initServlet(); //1.定义socket对象,监听8080端口 ServerSocket serverSocket = new ServerSocket(8080); while (true){ Socket socket = serverSocket.accept();//等待接收 BIO System.out.println("有用户请求过来了....."); // 给每一个请求都开启一个线程处理信息 new Thread(new Runnable() { @Override public void run() { try { 杜凯(socket); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } //2.创建出入流,读取用户请求信息 public void 杜凯(Socket socket) throws Exception { //创建输入流 InputStream inputStream = socket.getInputStream(); //解析输入流 getInputStream(inputStream); //输出流 Response response = new Response(socket.getOutputStream()); //根据url判断是静态资源还是动态资源 if(request.getUrl().equals("")){ //没有访问数据 response.write(ResponseUtil.getResponseHeader404()); }else if(ServletConfigMapping.classMap.get(request.getUrl()) == null){ //访问静态资源 response.writeHtml(request.getUrl()); }else { //访问动态资源 dispatch(request,response); } socket.close(); } public void getInputStream(InputStream inputStream) throws IOException { //将bit流转为文字信息 int count = 0; while (count == 0){ count = inputStream.available(); } byte[] bytes = new byte[count]; inputStream.read(bytes); String Context = new String(bytes); System.out.println(Context); //解析数据 if(Context.equals("")){ System.out.println("你输入了一个空请求"); }else { String firstLine = Context.split("\\n")[0]; //根据换行来获取第一行数据 request.setUrl(firstLine.split("\\s")[1]); request.setMethod(firstLine.split("\\s")[0]); } } public static void main(String[] args) throws IOException, ClassNotFoundException { MyTomcat myTomcat = new MyTomcat(); myTomcat.startUp(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。