day37(V23(删除任务),V24(HandlerMapping类),线程池,V26(线程池),myboot(Spring))

day37(V23(删除任务),V24(HandlerMapping类),线程池,V26(线程池),myboot(Spring))

1.V23(删除任务)

1.UserController(删除任务)

package com.webserver.controller;

import com.webserver.annotation.Controller;
import com.webserver.annotation.RequestMapping;
import com.webserver.core.DispatcherServlet;
import com.webserver.entity.User;
import com.webserver.http.HttpServletRequest;
import com.webserver.http.HttpServletResponse;

import java.io.*;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;


/*处理与用户相关的操作
* */
@Controller
public class UserController {
   private static File userDir;
   private static File root;
   private static File staticDir;

   static {
       try {
           root = new File(DispatcherServlet.class.getClassLoader().getResource(".").toURI());
           staticDir = new File(root, "static");
      } catch (URISyntaxException e) {
           e.printStackTrace();
      }

       userDir = new File("./users");
       if (!userDir.exists()) {
           userDir.mkdirs();
      }
  }

   /*注册页面*/
   @RequestMapping("/myweb/reg")
   public void reg(HttpServletRequest request, HttpServletResponse response) {
       //1.获取用户注册页面上输入的注册信息,获取form表单上提交的内容
         /*
           getParameter传入的值必须和页面表单上对应输入框的名字一致
           即:<input name="username" type="text">
                           ^^^^^^^
                           以它一致
        */
       String username = request.getParameter("username");
       String password = request.getParameter("password");
       String nickname = request.getParameter("nickname");
       String ageStr = request.getParameter("age");
       /*必要的验证,要求:
       * 四项不能为null,且一项必须为数字(正则表达式)
       * 否则直接给用户一个注册失败的页面:reg_input_error.html
       * 该页面显示一行字:输入信息有误,注册失败
       *
       * 实现思路:
       * 添加一个分支判断,如果符合上述情况,直接创建一个File对象表示
           错误提示页面,然后将其设置到响应对象的正文上即可。否则才执行下面
           原有的注册操作。
       * */

       if (username == null || password == null || nickname == null || ageStr == null || !ageStr.matches("[0-9]+")) {
           File file = new File(staticDir, "/myweb/reg_input_error.html");
           response.setContentFile(file);
           return;
      }
       int age = Integer.parseInt(ageStr);
       System.out.println(username + "," + password + "," + nickname + "," + ageStr);
       //2.将用户信息保存
       File userFile = new File(userDir, username + ".obj");
         /*
           判断是否为重复用户,若重复用户,则直接响应页面:have_user.html
           该页面剧中显示一行字:该用户已存在,请重新注册
        */
       if (userFile.exists()) {
           File file = new File(staticDir, "/myweb/have_user.html");
           response.setContentFile(file);
           return;
      }
       try (
               FileOutputStream fos = new FileOutputStream(userFile);
               ObjectOutputStream oos = new ObjectOutputStream(fos);
      ) {
           User user = new User(username, password, nickname, age);
           oos.writeObject(user);//保存到硬盘上
           /*注册成功了*/
           File file = new File(staticDir, "/myweb/reg_success.html");
           response.setContentFile(file);
      } catch (FileNotFoundException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      }

       //3 给用户响应一个注册结果页面(注册成功或注册失败)

  }

   /*处理登陆业务*/
   @RequestMapping("/myweb/login")
   public void login(HttpServletRequest request, HttpServletResponse response) {
       String username = request.getParameter("username");
       String password = request.getParameter("password");
       /*如果没有输入信息*/
       if (username == null || password == null) {
           File file = new File(staticDir, "/myweb/login_info_error.html");
           response.setContentFile(file);
           return;
      }
       /*将登录信息与保存的信息对应*/
       File userFile = new File(userDir, username + ".obj");
//                 判断用户是否存在
       if (userFile.exists()) {
           try {
//               反序列化
               FileInputStream fis = new FileInputStream(userFile);
               ObjectInputStream ois = new ObjectInputStream(fis);
               User user = (User) ois.readObject();
//               判断密码
               if (password.equals(user.getPassword())) {
                   File file = new File(staticDir, "/myweb/login_success.html");
                   response.setContentFile(file);
                   return;
              }
          } catch (FileNotFoundException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          } catch (ClassNotFoundException e) {
               e.printStackTrace();
          }

      }

       File file = new File(staticDir, "/myweb/login_fail.html");
       response.setContentFile(file);

  }

   /*处理动态用户列表*/
   @RequestMapping("/myweb/showAllUser")
   public void showAllUser(HttpServletRequest request, HttpServletResponse response) {

       //1.先将user里的所有用户提取出来存入list集合列表
       List<User> userList = new ArrayList<>();
           /*
           首先获取users中所有名字以.obj结尾的子项 提示:userDir.listFiles()
           然后遍历每一个子项并用文件流连接对象输入流进行反序列化
           最后将反序列化的User对象存入userList集合

        */

       File[] files = userDir.listFiles(l -> l.getName().endsWith(".obj"));

       for (File userFile : files) {
           try (
                   FileInputStream fis = new FileInputStream(userFile);
                   ObjectInputStream ois = new ObjectInputStream(fis);
          ) {

               userList.add((User) ois.readObject());

          } catch (Exception e) {
               e.printStackTrace();
          }
      }
       System.out.println(userList);

       //2.使程序生成一个页面,将list里的信息全部拼接到列表中


       PrintWriter pw = response.getWrite();
       pw.println("<!DOCTYPE html>");
       pw.println("<html lang=\"en\">");
       pw.println("<head>");
       pw.println(" <meta charset=\"UTF-8\">");
       pw.println("<title>用户列表</title>");
       pw.println("</head>");
       pw.println("<body>");
       pw.println("<center>");
       pw.println("<h1>用户列表</h1>");
       pw.println("<table border=\"1\">");
       pw.println("<tr>");
       pw.println("<td>用户名</td>");
       pw.println("<td>密码</td>");
       pw.println("<td>昵称</td>");
       pw.println("<td>年龄</td>");
       pw.println("<td>操作</td>");
       pw.println("</tr>");
       for (User user : userList) {
           pw.println("<tr>");
           pw.println("<td>" + user.getUsername() + "</td>");
           pw.println("<td>" + user.getPassword() + "</td>");
           pw.println("<td>" + user.getNickname() + "</td>");
           pw.println("<td>" + user.getAge() + "</td>");
           pw.println("<td><a href='/myweb/deleteUser?username=" + user.getUsername() + "'>删除</a></td>");
           pw.println("</tr>");
      }
       pw.println("</table>");
       pw.println("</center>");
       pw.println("</body>");
       pw.println("</html>");

       System.out.println("页面生成完毕!");


       //3.设置响应头Content-Type用于告知动态数据是什么
       response.setContentType("text/html");

  }

   /*处理删除用户任务*/
   @RequestMapping("/myweb/deleteUser")
   public void deleteUser(HttpServletRequest request, HttpServletResponse response) {
       String userName=request.getParameter("username");
       File userFile=new File(userDir,userName+".obj");
       userFile.delete();
       File file=new File(staticDir,"/myweb/deleteUser.html");
       response.setContentFile(file);
  }

}

2.deleteUser.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>成功</title>
</head>
<body>
<center>
   <h1>
      删除成功
   </h1>
</center>
</body>
</html>

2.V24(重构代码:DispatcherServlet:每次处理请求仅扫描一次,HandlerMapping类)

1.主要内容

1.重构代码

  • 上一个版本那种DispatcherServlet每次处理请求时都要扫描controller包,这样性能 低下.因此改为仅扫描一次.

2.实现:

  • 1:在com.webserver.core包下新建类HandlerMapping

  • 2:定义静态属性Map requestMapping key:请求路径 value:MethodMapping(内部类),记录处理该请求的方法对象和该方法所属对象

  • 3:在静态块中初始化,完成原DispatcherServlet扫描controller包的工作并初始化 requestMapping

  • 4:提供静态方法:getRequestMapping可根据请求路径获取处理该请求的方法

  • 5:在DispatcherServlet中处理业务时只需要根据请求获取对应的处理方法利用反射 机制调用即可

2.HandlerMapping(该类维护所有请求与对应的业务处理类的关系)

package com.webserver.core;

import com.webserver.annotation.Controller;
import com.webserver.annotation.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;

import java.util.HashMap;
import java.util.Map;

//该类维护所有请求与对应的业务处理类的关系
public class HandlerMapping {
   private static Map<String, MethodMapping> mapping = new HashMap<>();

   static {
       initMapping();
  }

   private static void initMapping() {
       try {
           File dir = new File(
                   HandlerMapping.class.getClassLoader().getResource("./com/webserver/controller").toURI()
          );
           // String packName = "com.webserver.controller";
           File[] subs = dir.listFiles(f -> f.getName().endsWith("class"));
           for (File sub : subs) {
               String fileName = sub.getName();
               String className = fileName.substring(0, fileName.indexOf("."));
//               加载类对象
               Class cls = Class.forName("com.webserver.controller." + className);
//               判断该类是否被Controller标注了
               if (cls.isAnnotationPresent(Controller.class)) {
//                   实例化该Controller
                   Object obj = cls.newInstance();
//                   获取Controller里的方法
                   Method[] methods = cls.getMethods();
                   for (Method method : methods) {
//                       判断该方法是否被RequestMapping标注了
                       if (method.isAnnotationPresent(RequestMapping.class)) {

//                       获取注解
                           RequestMapping rm = method.getAnnotation(RequestMapping.class);
//                       获取该注解的参数
                           String value = rm.value();
                           MethodMapping methodMapping = new MethodMapping(obj, method);
                           mapping.put(value, methodMapping);
                      }


                  }
              }
          }
      } catch (Exception e) {
           e.printStackTrace();
      }
  }

   /**
    * 根据给定的请求路径给出请求的Controller及对应的业务方法
    */
   public static MethodMapping getMethod(String path) {
       return mapping.get(path);
  }

   public static void main(String[] args) {
       System.out.println(mapping);
       MethodMapping mm = mapping.get("/myweb/reg");
       System.out.println(mm);
  }

   //   每个实例用于记录方法以及该方法的所属的Controller对象
   public static class MethodMapping {
       private Object controller;
       private Method method;

       public MethodMapping(Object controller, Method method) {
           this.controller = controller;
           this.method = method;
      }

       public Object getController() {
           return controller;
      }


       public Method getMethod() {
           return method;
      }


  }
}

3.DispatcherServlet

package com.webserver.core;

import com.webserver.annotation.Controller;
import com.webserver.annotation.RequestMapping;
import com.webserver.controller.ArticleController;
import com.webserver.controller.ToolsController;
import com.webserver.controller.UserController;
import com.webserver.http.HttpServletRequest;
import com.webserver.http.HttpServletResponse;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
* 用于处理请求
*/
public class DispatcherServlet {
   private static File root;
   private static File staticDir;

   static {
       try {
           root = new File(DispatcherServlet.class.getClassLoader().getResource(".").toURI());
           staticDir = new File(root, "static");
      } catch (URISyntaxException e) {
           e.printStackTrace();
      }
  }

   public void service(HttpServletRequest request, HttpServletResponse response) {
       /*获取路径*/
       String path = request.getRequestURI();

//       首先判断是否为请求一个业务
       try {
           HandlerMapping.MethodMapping mm = HandlerMapping.getMethod(path);
           if (mm != null) {
               Object obj = mm.getController();
               Method method = mm.getMethod();
               method.invoke(obj, request, response);
               return;
          }
      } catch (Exception e) {
           e.printStackTrace();
      }
       File file = new File(staticDir, path);
       System.out.println("资源是否存在:" + file.exists());

       if (file.isFile()) {//当file表示的文件真实存在且是一个文件时返回true
           response.setContentFile(file);


      } else {//要么file表示的是一个目录,要么不存在
           response.setStatusCode(404);
           response.setStatusReason("NotFound");
           file = new File(staticDir, "root/404.html");
           response.setContentFile(file);

      }

       //测试添加一个额外的响应头
       response.addHeader("Server", "WebServer");

  }
}

 

3.V25(重定向:sendRedirect())

1.主要内容

1.实现重定向

  • 当浏览器提交一个请求时,比如注册,那么请求会带着表单信息请求注册功能。而注册功能处理 完毕后直接设置一个页面给浏览器,这个过程是内部跳转。 即:浏览器上的地址栏中地址显示的是提交表单的请求,而实际看到的是注册结果的提示页面。 这有一个问题,如果此时浏览器刷新,会重复上一次的请求,即:再次提交表单请求注册业务。

  • 为了解决这个问题,我们可以使用重定向。 重定向是当我们处理完请求后,不直接响应一个页面,而是给浏览器回复一个路径,让其再次根据 该路径发起请求。这样一来,无论用户如何刷新,请求的都是该路径。避免表达的重复提交。

2.实现:

  • 在HttpServletResponse中定义一个方法:sendRedirect()

  • 该方法中设置状态代码为302,并在响应头中包含Location指定需要浏览器重新发起请求的路径 将原来Controller中内部跳转页面的操作全部改为重定向。

2.HttpServletResponse(sendRedirect()方法)

package com.webserver.http;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* 响应对象
* 该类的每一个实例用于表示HTTP协议要求的响应
* 每个响应由三部分组成:
* 状态行,响应头,响应正文
*/
public class HttpServletResponse {
   private Socket socket;
   //状态行相关信息
   private int statusCode = 200;
   private String statusReason = "OK";

   //响应头相关信息
   private Map<String, String> headers = new HashMap<>();

   //响应正文相关信息
   private File contentFile;

   private ByteArrayOutputStream baos;
   private byte[] contentData;//作为响应正文数据的节点数组

   public HttpServletResponse(Socket socket) {
       this.socket = socket;
  }

   /**
    * 将当前响应对象内容按照标准的HTTP响应格式发送给客户端
    */
   public void response() throws IOException {
//       发送前的准备工作
       sendBefore();
       //3.1发送状态行
       sendStatusLine();
       //3.2发送响应头
       sendHeaders();
       //3.3发送响应正文
       sendContent();
  }

   //发送前最后的准备工作
   private void sendBefore() {
//       先判断baos是否为null,不为null说明存在动态数据
       if (baos != null) {
//       得到其内部字节数组(动态数据)
           contentData = baos.toByteArray();
      }
//       如果动态数据不为null,添加响应头Content-Length
       if (contentData != null) {
           addHeader("Content-Length", contentData.length + "");
      }
  }

   /**
    * 发送状态行
    */
   private void sendStatusLine() throws IOException {
       println("HTTP/1.1" + " " + statusCode + " " + statusReason);
  }

   /**
    * 发送响应头
    */
   private void sendHeaders() throws IOException {
       /*
           headers这个Map中的内容:
           key             value
           Content-Type     text/html
           Content-Length   224
           Server           WebServer
           ...             ...
        */
       //遍历headers将所有的响应头发送给客户端
       Set<Map.Entry<String, String>> entrySet = headers.entrySet();
       for (Map.Entry<String, String> e : entrySet) {
           String key = e.getKey();
           String value = e.getValue();
           println(key + ": " + value);
      }

       println("");//单独发送回车换行表示响应头发送完毕了
  }

   /**
    * 发送响应正文
    */
   private void sendContent() throws IOException {
       if (contentData != null) {//有动态数据
           OutputStream out = socket.getOutputStream();
           out.write(contentData);
      } else if (contentFile != null) {

           OutputStream out = socket.getOutputStream();
           try (FileInputStream fis = new FileInputStream(contentFile);) {

               int len;
               byte[] data = new byte[1024 * 10];
               while ((len = fis.read(data)) != -1) {
                   out.write(data, 0, len);
              }
          }

      }
  }


   /**
    * 将一行字符串按照ISO8859-1编码发送给客户端,最后会自动添加回车和换行符
    *
    * @param line
    */
   private void println(String line) throws IOException {
       OutputStream out = socket.getOutputStream();
       byte[] data = line.getBytes(StandardCharsets.ISO_8859_1);
       out.write(data);
       out.write(13);//单独发送了回车符
       out.write(10);//单独发送换行符
  }

   public int getStatusCode() {
       return statusCode;
  }

   public void setStatusCode(int statusCode) {
       this.statusCode = statusCode;
  }

   public String getStatusReason() {
       return statusReason;
  }

   public void setStatusReason(String statusReason) {
       this.statusReason = statusReason;
  }

   public File getContentFile() {
       return contentFile;
  }

   public void setContentFile(File contentFile) {
       this.contentFile = contentFile;
       String contentType = null;

       try {
           contentType = Files.probeContentType(contentFile.toPath());
      } catch (IOException e) {
           e.printStackTrace();
      }
       /*当我们无法根据正文判断类型时,则不发送Content-Type
       在HTTP协议中响应包含正文,但不包含Content-Type时,让浏览器自行判断响应正文内容
       * */
       if (contentType != null) {

           addHeader("Content-Type", contentType);
      }
       addHeader("Content-Length", contentFile.length() + "");
  }

   /**
    * 添加一个要发送的响应头
    *
    * @param name
    * @param value
    */
   public void addHeader(String name, String value) {
       //将响应头的名字和值以key-value形式存入headers这个Map中
       headers.put(name, value);
  }

   public OutputStream getOutputStream() {
       if (baos == null) {
           baos = new ByteArrayOutputStream();

      }
       return baos;
  }

   /**
    * 通过该方法获取的缓冲输出流写出的文本会作为正文内容发送给浏览器
    */
   public PrintWriter getWrite() {
       return new PrintWriter(
               new BufferedWriter(
                       new OutputStreamWriter(
                               getOutputStream(),
                               StandardCharsets.UTF_8
                      )
              ), true
      );
  }

   /**
    *设置响应头Content-Type的值
    */
   public void setContentType(String mine) {
       addHeader("Content-Type", mine);
  }

   /**
    * 使浏览器重新定位到指定位置
    */
   public void sendRedirect(String location) {
       /*重定向的规则:
       响应中的状态码为302
       响应头中应该包含Location
       没有响应正文
       * */
   this.statusCode=302;
   this.statusReason="Moved Temporarily";
   addHeader("Location",location);
  }
}

3.ArticleController、UserController(修改)

File file = new File(staticDir, "/myweb/article_fail.html"); response.setContentFile(file);

修改为

response.sendRedirect("/myweb/article_fail.html");

4.线程池(ExecutorService 变量= Executors.newFixedThreadPool(线程数);)

1.定义:

是线程的管理机制

ExecutorService treadPool= Executors.newFixedThreadPool(2);

2.两个作用

1.复用线程 2.控制线程数量

3.JUC

java.util.concurrent

concurrent并发

java的开发包,里面都是与多线程相关的API,线程池就在里面

4.关闭线程池:(shutdown()、shutdownNow())

5.代码

package thread;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*线程池
是线程的管理机制,两个作用
1.复用线程
2.控制线程数量

* */
public class TreadPoolDemo {
   public static void main(String[] args) {
       /*JUC java.util.concurrent
       concurrent并发
       java的开发包,里面都是与多线程相关的API,线程池就在里面
       * */
//       创建一个固定大小的线程池,容量为2
       ExecutorService treadPool= Executors.newFixedThreadPool(2);
       for (int i = 0; i < 5; i++) {
           Runnable r=new Runnable() {
               @Override
               public void run() {
                   Thread t=Thread.currentThread();
                   System.out.println(t.getName()+"正在执行任务");
                   try {
                       Thread.sleep(5000);
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println(t.getName()+"任务执行完毕!!!!!!!!");
              }
          };
           treadPool.execute(r);
           System.out.println("交给线程一个任务");
  }
         /*
           关闭线程池的两个操作:
           shutdown()
           该方法调用后,线程不再接收新任务,如果此时还调用execute()则会抛出异常
           并且线程池会继续将已经存在的任务全部执行完毕后才会关闭。

           shutdownNow()
           强制中断所有线程,来停止线程池
        */
       treadPool.shutdown();
       System.out.println("结束线程》》》》》》");
  }}

5.V26(线程池)

1.主要内容

在WebServerApplication应用线程池

2.WebServerApplication(线程池)

package com.webserver.core;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* WebServer主类
* WebServer是一个Web容器,实现了Tomcat中的基础功能,通过这个项目的学习了解Tomcat的
* 底层工作逻辑。
* Web容器是一个Web服务端程序,主要负责两方面的工作:
* 1:管理部署在容器中的所有网络应用
* 2:与客户端(通常就是浏览器)进行TCP通讯,并基于HTTP协议进行应用交互,使得客户端可以
*   通过网络远程调用容器下不同网络应用中的内容。
*
* 网络应用(webapp):包含的内容大致有:网页,处理业务的代码,其他资源等。就是俗称的"网站"
*
*/
public class WebServerApplication {
   private ServerSocket serverSocket;
   private ExecutorService threadPool;

   public WebServerApplication(){
       try {
           System.out.println("正在启动服务端...");
           serverSocket = new ServerSocket(8088);
           threadPool= Executors.newFixedThreadPool(50);
           System.out.println("服务端启动完毕!");
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

   public void start(){
       try {
           while(true) {
               System.out.println("等待客户端连接...");
               Socket socket = serverSocket.accept();
               System.out.println("一个客户端连接了!");
               //启动一个线程处理该客户端交互
               ClientHandler handler = new ClientHandler(socket);
               threadPool.execute(handler);
          }
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

   public static void main(String[] args) {
       WebServerApplication application = new WebServerApplication();
       application.start();
  }
}

6.myboot(Spring)

1.在MybootApplication同级目录上创建controller文件与entity文件

2.导入文件

3.引入类

4.ArticleController

package com.myboot.controller;



import com.myboot.entity.Article;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;


@Controller
public class ArticleController {
   private static File articleDir;


   static {

       articleDir = new File("./articles");
       if (!articleDir.exists()) {
           articleDir.mkdirs();
      }
  }

   /*保存文章*/
   @RequestMapping("/myweb/writeArticle")
   public void writeArticle(HttpServletRequest request, HttpServletResponse response) {
//   1.获取用户输入的信息,即获取form表单上提交的内容
       String title = request.getParameter("title");
       String author = request.getParameter("author");
       String content = request.getParameter("content");

       if (title == null || author == null || content == null) {
//           File file = new File(staticDir, "/myweb/article_fail.html");
//           response.setContentFile(file);
           try {
               response.sendRedirect("/myweb/article_fail.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }
       System.out.println(title + "," + author + "," + content);

//       2.保存内容
       File articleFile = new File(articleDir, title + ".obj");
       if (articleFile.exists()) {//文件存在则说明是重复文章
//           File file = new File(staticDir, "/myweb/article_fail.html");
//           response.setContentFile(file);
           try {
               response.sendRedirect("/myweb/article_fail.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }
       try (FileOutputStream fos = new FileOutputStream(articleFile);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
      ) {
           Article article = new Article(title, author, content);
           oos.writeObject(article);
           /*保存成功*/
//           File file = new File(staticDir, "/myweb/article_success.html");
//           response.setContentFile(file);
           response.sendRedirect("/myweb/article_success.html");
      } catch (FileNotFoundException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

   /*读取文章*/
   @RequestMapping("/myweb/showAllArticle")
   public void showAllArticle(HttpServletRequest request, HttpServletResponse response) {
//       1.先将article里所有文章提取出来
       List<Article> articleList = new ArrayList<>();
       File[] files = articleDir.listFiles(a -> a.getName().endsWith(".obj"));
       for (File articleFile : files) {
           try (
                   FileInputStream fis = new FileInputStream(articleFile);
                   ObjectInputStream ois = new ObjectInputStream(fis);
          ) {
               articleList.add((Article) ois.readObject());

          } catch (FileNotFoundException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          } catch (ClassNotFoundException e) {
               e.printStackTrace();
          }

      }
       System.out.println(articleList);
//       2.使主程序生成一个页面,将list里的信息都拼接到列表中
       PrintWriter pw = null;
       try {
           pw = response.getWriter();
      } catch (IOException e) {
           e.printStackTrace();
      }
       pw.println("<!DOCTYPE html>");
       pw.println("<html lang=\"en\">");
       pw.println("<head>");
       pw.println("<meta charset=\"UTF-8\">");
       pw.println("<title>文章列表</title>");
       pw.println("</head>");
       pw.println("<body>");
       pw.println("<center>");
       pw.println("<h1>文章列表</h1>");
       pw.println("<table border=\"1\">");
       pw.println("<tr>");
       pw.println("<td>标题名</td>");
       pw.println("<td>作者</td>");

       pw.println("</tr>");
       for (Article article : articleList) {
           pw.println("<tr>");
           pw.println("<td>" + article.getTitle() + "</td>");
           pw.println("<td>" + article.getAuthor() + "</td>");

           pw.println("</tr>");
      }
       pw.println("</table>");
       pw.println("</center>");
       pw.println("</body>");
       pw.println("</html>");

       System.out.println("页面生成完毕!");
//       3.设置响应头Content-Type用于告知动态数据是什么
       response.setContentType("text/html");
  }
}

5.UserController

1.初始

package com.myboot.controller;


import com.myboot.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;


/*处理与用户相关的操作
* */
@Controller
public class UserController {
   private static File userDir;


   static {


       userDir = new File("./users");
       if (!userDir.exists()) {
           userDir.mkdirs();
      }
  }

   /*注册页面*/
   @RequestMapping("/myweb/reg")
   public void reg(HttpServletRequest request, HttpServletResponse response) {
       //1.获取用户注册页面上输入的注册信息,获取form表单上提交的内容
         /*
           getParameter传入的值必须和页面表单上对应输入框的名字一致
           即:<input name="username" type="text">
                           ^^^^^^^
                           以它一致
        */
       String username = request.getParameter("username");
       String password = request.getParameter("password");
       String nickname = request.getParameter("nickname");
       String ageStr = request.getParameter("age");
       /*必要的验证,要求:
       * 四项不能为null,且一项必须为数字(正则表达式)
       * 否则直接给用户一个注册失败的页面:reg_input_error.html
       * 该页面显示一行字:输入信息有误,注册失败
       *
       * 实现思路:
       * 添加一个分支判断,如果符合上述情况,直接创建一个File对象表示
           错误提示页面,然后将其设置到响应对象的正文上即可。否则才执行下面
           原有的注册操作。
       * */

       if (username == null || password == null || nickname == null || ageStr == null || !ageStr.matches("[0-9]+")) {
//           File file = new File(staticDir, "/myweb/reg_input_error.html");
//           response.setContentFile(file);
           try {
               response.sendRedirect("/myweb/reg_input_error.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }
       int age = Integer.parseInt(ageStr);
       System.out.println(username + "," + password + "," + nickname + "," + ageStr);
       //2.将用户信息保存
       File userFile = new File(userDir, username + ".obj");
         /*
           判断是否为重复用户,若重复用户,则直接响应页面:have_user.html
           该页面剧中显示一行字:该用户已存在,请重新注册
        */
       if (userFile.exists()) {
//           File file = new File(staticDir, "/myweb/have_user.html");
//           response.setContentFile(file);
           try {
               response.sendRedirect("/myweb/have_user.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }
       try (
               FileOutputStream fos = new FileOutputStream(userFile);
               ObjectOutputStream oos = new ObjectOutputStream(fos);
      ) {
           User user = new User(username, password, nickname, age);
           oos.writeObject(user);//保存到硬盘上
           /*注册成功了*/
//           File file = new File(staticDir, "/myweb/reg_success.html");
//           response.setContentFile(file);
           response.sendRedirect("/myweb/reg_success.html");
      } catch (FileNotFoundException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      }

       //3 给用户响应一个注册结果页面(注册成功或注册失败)

  }

   /*处理登陆业务*/
   @RequestMapping("/myweb/login")
   public void login(HttpServletRequest request, HttpServletResponse response) {
       String username = request.getParameter("username");
       String password = request.getParameter("password");
       /*如果没有输入信息*/
       if (username == null || password == null) {
//           File file = new File(staticDir, "/myweb/login_info_error.html");
//           response.setContentFile(file);
           try {
               response.sendRedirect("/myweb/login_info_error.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }
       /*将登录信息与保存的信息对应*/
       File userFile = new File(userDir, username + ".obj");
//                 判断用户是否存在
       if (userFile.exists()) {
           try {
//               反序列化
               FileInputStream fis = new FileInputStream(userFile);
               ObjectInputStream ois = new ObjectInputStream(fis);
               User user = (User) ois.readObject();
//               判断密码
               if (password.equals(user.getPassword())) {
//                   File file = new File(staticDir, "/myweb/login_success.html");
//                   response.setContentFile(file);
                   response.sendRedirect("/myweb/login_success.html");
                   return;
              }
          } catch (FileNotFoundException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          } catch (ClassNotFoundException e) {
               e.printStackTrace();
          }

      }

//       File file = new File(staticDir, "/myweb/login_fail.html");
//       response.setContentFile(file);
       try {
           response.sendRedirect("/myweb/login_fail.html");
      } catch (IOException e) {
           e.printStackTrace();
      }

  }

   /*处理动态用户列表*/
   @RequestMapping("/myweb/showAllUser")
   public void showAllUser(HttpServletRequest request, HttpServletResponse response) {

       //1.先将user里的所有用户提取出来存入list集合列表
       List<User> userList = new ArrayList<>();
           /*
           首先获取users中所有名字以.obj结尾的子项 提示:userDir.listFiles()
           然后遍历每一个子项并用文件流连接对象输入流进行反序列化
           最后将反序列化的User对象存入userList集合

        */

       File[] files = userDir.listFiles(l -> l.getName().endsWith(".obj"));

       for (File userFile : files) {
           try (
                   FileInputStream fis = new FileInputStream(userFile);
                   ObjectInputStream ois = new ObjectInputStream(fis);
          ) {

               userList.add((User) ois.readObject());

          } catch (Exception e) {
               e.printStackTrace();
          }
      }
       System.out.println(userList);

       //2.使程序生成一个页面,将list里的信息全部拼接到列表中
       //3.设置响应头Content-Type用于告知动态数据是什么
       response.setContentType("text/html;charset=UTF-8");

       PrintWriter pw = null;
       try {
           pw = response.getWriter();
      } catch (IOException e) {
           e.printStackTrace();
      }
       pw.println("<!DOCTYPE html>");
       pw.println("<html lang=\"en\">");
       pw.println("<head>");
       pw.println(" <meta charset=\"UTF-8\">");
       pw.println("<title>用户列表</title>");
       pw.println("</head>");
       pw.println("<body>");
       pw.println("<center>");
       pw.println("<h1>用户列表</h1>");
       pw.println("<table border=\"1\">");
       pw.println("<tr>");
       pw.println("<td>用户名</td>");
       pw.println("<td>密码</td>");
       pw.println("<td>昵称</td>");
       pw.println("<td>年龄</td>");
       pw.println("<td>操作</td>");
       pw.println("</tr>");
       for (User user : userList) {
           pw.println("<tr>");
           pw.println("<td>" + user.getUsername() + "</td>");
           pw.println("<td>" + user.getPassword() + "</td>");
           pw.println("<td>" + user.getNickname() + "</td>");
           pw.println("<td>" + user.getAge() + "</td>");
           pw.println("<td><a href='/myweb/deleteUser?username=" + user.getUsername() + "'>删除</a></td>");
           pw.println("</tr>");
      }
       pw.println("</table>");
       pw.println("</center>");
       pw.println("</body>");
       pw.println("</html>");

       System.out.println("页面生成完毕!");




  }

   /*处理删除用户任务*/
   @RequestMapping("/myweb/deleteUser")
   public void deleteUser(HttpServletRequest request, HttpServletResponse response) {
       String userName = request.getParameter("username");
       File userFile = new File(userDir, userName + ".obj");
       userFile.delete();
//       File file=new File(staticDir,"/myweb/deleteUser.html");
//       response.setContentFile(file);
       try {
           response.sendRedirect("/myweb/showAllUser");
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

}

2.改进

package com.myboot.controller;


import com.myboot.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

import java.util.ArrayList;
import java.util.List;


/**
* 处理与用户相关的业务操作
*/

@Controller
public class UserController {
   private static File userDir;

   static {
       userDir = new File("./users");
       if (!userDir.exists()) {
           userDir.mkdirs();
      }
  }

   @RequestMapping("/myweb/reg")
//   public void reg(HttpServletRequest request, HttpServletResponse response) {
//   public void reg(String username,String password,String nickname,int age,HttpServletResponse response) {
   public void reg(User user,HttpServletResponse response) {
       //1 获取用户注册页面上输入的注册信息,获取form表单提交的内容
       /*
           getParameter传入的值必须和页面表单上对应输入框的名字一致
           即:<input name="username" type="text">
                           ^^^^^^^
                           以它一致
        */
//       String username = request.getParameter("username");
//       String password = request.getParameter("password");
//       String nickname = request.getParameter("nickname");
//       String ageStr = request.getParameter("age");

       /*
           必要的验证,要求:
           四项信息不能为null,并且年龄必须是一个数字(正则表达式)
           否则直接给用户一个注册失败的页面:reg_input_error.html
           该页面剧中显示一行字:输入信息有误,注册失败。
           实现思路:
           添加一个分支判断,如果符合了上述的情况,直接创建一个File对象表示
           错误提示页面,然后将其设置到响应对象的正文上即可。否则才执行下面
           原有的注册操作。
        */
//       if (username == null || password == null || nickname == null || ageStr == null ||
//               !ageStr.matches("[0-9]+")) {
//           try {
//               response.sendRedirect("/myweb/reg_input_error.html");
//           } catch (IOException e) {
//               e.printStackTrace();
//           }
//           return;
//       }
//       int age = Integer.parseInt(ageStr);
//       System.out.println(username + "," + password + "," + nickname + "," + age);
       System.out.println(user);

       //2 将用户信息保存
//       File userFile = new File(userDir, username + ".obj");
       File userFile = new File(userDir, user.getUsername() + ".obj");
       /*
           判断是否为重复用户,若重复用户,则直接响应页面:have_user.html
           该页面剧中显示一行字:该用户已存在,请重新注册
        */
       if (userFile.exists()) {//文件存在则说明是重复用户
           try {
               response.sendRedirect("/myweb/have_user.html");
          } catch (IOException e) {
               e.printStackTrace();
          }

           return;
      }


       try (
               FileOutputStream fos = new FileOutputStream(userFile);
               ObjectOutputStream oos = new ObjectOutputStream(fos);
      ) {
//           User user = new User(username, password, nickname, age);
           oos.writeObject(user);

           //注册成功了

           response.sendRedirect("/myweb/reg_success.html");

      } catch (FileNotFoundException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      }


       //3 给用户响应一个注册结果页面(注册成功或注册失败)


  }

   /**
    * 处理登录
    *
    * @param request
    * @param response
    */
   @RequestMapping("/myweb/login")
   public void login(HttpServletRequest request, HttpServletResponse response) {
       String username = request.getParameter("username");
       String password = request.getParameter("password");

       if (username == null || password == null) {

           try {
               response.sendRedirect("/myweb/login_input_error.html");
          } catch (IOException e) {
               e.printStackTrace();
          }
           return;
      }

       File userFile = new File(userDir, username + ".obj");
       if (userFile.exists()) {//文件存在,说明该用户存在
           try (
                   FileInputStream fis = new FileInputStream(userFile);
                   ObjectInputStream ois = new ObjectInputStream(fis);
          ) {
               //从文件中反序列化注册用户信息
               User user = (User) ois.readObject();
               //密码正确
               if (user.getPassword().equals(password)) {
                   response.sendRedirect("/myweb/login_success.html");
                   return;
              }
          } catch (Exception e) {
               e.printStackTrace();
          }
      }
       try {
           response.sendRedirect("/myweb/login_fail.html");
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

   /**
    * 用于显示用户列表的动态页面
    *
    * @param request
    * @param response
    */
   @RequestMapping("/myweb/showAllUser")
   public void showAllUser(HttpServletRequest request, HttpServletResponse response) {
       //1 先用users目录里将所有的用户读取出来存入一个List集合备用
       List<User> userList = new ArrayList<>();
       /*
           首先获取users中所有名字以.obj结尾的子项 提示:userDir.listFiles()
           然后遍历每一个子项并用文件流连接对象输入流进行反序列化
           最后将反序列化的User对象存入userList集合
        */
       File[] subs = userDir.listFiles(f -> f.getName().endsWith(".obj"));
       for (File userFile : subs) {
           try (
                   FileInputStream fis = new FileInputStream(userFile);
                   ObjectInputStream ois = new ObjectInputStream(fis);
          ) {
               userList.add((User) ois.readObject());
          } catch (Exception e) {
               e.printStackTrace();
          }
      }


       //设置响应头Content-Type用于告知动态数据是什么
       response.setContentType("text/html;charset=utf-8");

       //2 使用程序生成一个页面,同时遍历List集合将用户信息拼接到表格中
       PrintWriter pw = null;
       try {
           pw = response.getWriter();
      } catch (IOException e) {
           e.printStackTrace();
      }
       pw.println("<!DOCTYPE html>");
       pw.println("<html lang=\"en\">");
       pw.println("<head>");
       pw.println("<meta charset=\"UTF-8\">");
       pw.println("<title>用户列表</title>");
       pw.println("</head>");
       pw.println("<body>");
       pw.println("<center>");
       pw.println("<h1>用户列表</h1>");
       pw.println("<table border=\"1\">");
       pw.println("<tr>");
       pw.println("<td>用户名</td>");
       pw.println("<td>密码</td>");
       pw.println("<td>昵称</td>");
       pw.println("<td>年龄</td>");
       pw.println("<td>操作</td>");
       pw.println("</tr>");
       for (User user : userList) {
           pw.println("<tr>");
           pw.println("<td>" + user.getUsername() + "</td>");
           pw.println("<td>" + user.getPassword() + "</td>");
           pw.println("<td>" + user.getNickname() + "</td>");
           pw.println("<td>" + user.getAge() + "</td>");
           pw.println("<td><a href='/myweb/deleteUser?username=" + user.getUsername() + "'>删除</a></td>");
           pw.println("</tr>");
      }
       pw.println("</table>");
       pw.println("</center>");
       pw.println("</body>");
       pw.println("</html>");

       System.out.println("页面生成完毕!");

  }

   @RequestMapping("/myweb/deleteUser")
   public void deleteUser(HttpServletRequest request,HttpServletResponse response){
       String username = request.getParameter("username");

       File userFile = new File(userDir, username + ".obj");
       userFile.delete();

       try {
           response.sendRedirect("/myweb/showAllUser");
      } catch (IOException e) {
           e.printStackTrace();
      }

  }
}
 

 

posted @ 2022-04-20 20:41  约拿小叶  阅读(23)  评论(0编辑  收藏  举报