通过这片文章,想表达的是代码演变的过程,由繁到简
最原始的方法,通过网络编程、I/O流和多线程来实现:
package com.itheima;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/*
* 自定义web服务器
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8080); // 监听指定端口
System.out.println("server is running...");
while (true){
Socket sock = ss.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
//开启线程处理请求
Thread t = new Handler(sock);
t.start();
}
}
}
class Handler extends Thread {
Socket sock;
public Handler(Socket sock) {
this.sock = sock;
}
public void run() {
try (InputStream input = this.sock.getInputStream(); OutputStream output = this.sock.getOutputStream()) {
handle(input, output);
} catch (Exception e) {
try {
this.sock.close();
} catch (IOException ioe) {
}
System.out.println("client disconnected.");
}
}
private void handle(InputStream input, OutputStream output) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
// 读取HTTP请求:
boolean requestOk = false;
String first = reader.readLine();
if (first.startsWith("GET / HTTP/1.")) {
requestOk = true;
}
for (;;) {
String header = reader.readLine();
if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
break;
}
System.out.println(header);
}
System.out.println(requestOk ? "Response OK" : "Response Error");
if (!requestOk) {// 发送错误响应:
writer.write("HTTP/1.0 404 Not Found\r\n");
writer.write("Content-Length: 0\r\n");
writer.write("\r\n");
writer.flush();
} else { // 发送成功响应:
//读取html文件,转换为字符串
InputStream is = Server.class.getClassLoader().getResourceAsStream("html/a.html");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder data = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null){
data.append(line);
}
br.close();
int length = data.toString().getBytes(StandardCharsets.UTF_8).length;
writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Connection: keep-alive\r\n");
writer.write("Content-Type: text/html\r\n");
writer.write("Content-Length: " + length + "\r\n");
writer.write("\r\n"); // 空行标识Header和Body的分隔
writer.write(data.toString());
writer.flush();
}
}
}
后来Servlet对这些代码进行了封装,这个时候每一个类来处理一个请求。通过继承HttpServlet实现doGet和doPost方法,来实现业务处理
@WebServlet(name = "ServletConfigTest", urlPatterns = "/ServletConfigTest", initParams = {
@WebInitParam(name = "name", value = "GRR") })
public class ServletConfigTest extends HttpServlet {
private static final long serialVersionUID = 1L;
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
// 处理业务请求
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = this.config.getInitParameter("name");
response.getWriter().print(name);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
后来SpringBoot直接封装。通过启动类的扫描,将当前包以及子包的所有带@Component,@Controller,@RestController,@Service,@Repository等注解都扫描设置为控制器,然后将类中的每个方法,访问路径做为key,方法名的全限定名作为value,生成一个map集合,当有请求的时候Spring通过访问路径,找到对应的方法进行处理。我想哈大概如下:
访问路径 | 方法的全限定名称(这样就可以通过发射来操作方法) |
---|---|
/crm/user/login | com.yfs1024.controller.UserController#login |
/crm/user/logout | com.yfs1024.controller.UserController#logout |
/admin/user/getAllGoods | com.yfs1024.controller.admin.UserAdminController#getAllGoods |
后来每一个方法来处理一个请求:
/**
* 分页条件查询轮播图
*
* @param carousel
* @param page
* @param rows
* @return
*/
@RequestMapping("/list")
public Map<String, Object> list(Carousel carousel, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "rows", required = false) Integer rows) {
Map<String, Object> resultMap = new HashMap<>(16);
QueryWrapper<Carousel> carouselQueryWrapper = new QueryWrapper<>();
if (carousel.getTitle() != null) {
carouselQueryWrapper.like("title", carousel.getTitle());
}
carouselQueryWrapper.orderByAsc("sortNum");
Page<Carousel> carouselPage = new Page<>(page, rows);
List<Carousel> carouselList = carouselService.list(carouselQueryWrapper, carouselPage);
Integer total = carouselService.getCount(carouselQueryWrapper);
resultMap.put("rows", carouselList);
resultMap.put("total", total);
return resultMap;
}