1、DispatcherServlet
package com.csdn.mymvc.core;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DispatcherServlet extends HttpServlet {
private final String BEAN_FACTORY = "beanFactory";
private final String CONTROLLER_BEAN_MAP = "controllerBeanMap";
String uri = "/fruit/index";
String[] arr = uri.split("/");
System.out.println(Arrays.toString(arr));
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String[] staticResourceSuffixes = {".html", ".jsp", ".jpg", ".png", ".gif", ".css", ".js", ".ico"};
String uri = req.getRequestURI();
if (Arrays.stream(staticResourceSuffixes).anyMatch(uri::endsWith)) {
RequestDispatcher defaultDispatcher = req.getServletContext().getNamedDispatcher("default");
defaultDispatcher.forward(req, resp);
String[] arr = uri.split("/");
if (arr == null || arr.length != 3) {
throw new RuntimeException(uri + "非法!");
String requestMapping = "/" + arr[1];
String methodMapping = "/" + arr[2];
ServletContext application = getServletContext();
ControllerDefinition controllerDefinition = ((Map) application.getAttribute(CONTROLLER_BEAN_MAP)).get(requestMapping);
if (controllerDefinition == null) {
throw new RuntimeException(requestMapping + "对应的controller组件不存在!");
String requestMethodStr = req.getMethod().toLowerCase();
Method method = controllerDefinition.getMethodMappingMap().get(requestMethodStr + "_" + methodMapping);
Object controllerBean = controllerDefinition.getControllerBean();
method.setAccessible(true);
method.invoke(controllerBean, req, resp);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
2、ControllerDefinition
package com.csdn.mymvc.core;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.lang.reflect.Method;
import java.util.HashMap;
public class ControllerDefinition {
private String requestMapping;
private Object controllerBean;
private Map methodMappingMap = new HashMap<>();
3、ComponentScan
package com.csdn.mymvc.core;
import com.csdn.mymvc.annotation.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class ComponentScan {
public static Map beanFactory = new HashMap<>();
public static Map controllerBeanMap = new HashMap<>();
static String path = null;
path = ComponentScan.class.getClassLoader().getResource("").getPath();
path = path.substring(1);
File rootDir = new File(path);
beanFactory.values().forEach(System.out::println);
beanFactory.values().forEach(bean -> {
Field[] fields = bean.getClass().getDeclaredFields();
.filter(field -> field.getDeclaredAnnotation(Autowire.class) != null)
String fieldTypeName = field.getType().getName();
Object filedValue = beanFactory.values().stream().filter(instance -> {
return field.getType().isAssignableFrom(instance.getClass());
}).findFirst().orElseThrow(() -> new RuntimeException(fieldTypeName + "装配失败!"));
field.setAccessible(true);
field.set(bean, filedValue);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
beanFactory.values().stream()
.filter(bean -> bean.getClass().getDeclaredAnnotation(RequestMapping.class) != null)
ControllerDefinition controllerDefinition = new ControllerDefinition();
String requestMapping = bean.getClass().getDeclaredAnnotation(RequestMapping.class).value();
Object controllerBean = bean;
controllerDefinition.setRequestMapping(requestMapping);
controllerDefinition.setControllerBean(controllerBean);
Arrays.stream(bean.getClass().getDeclaredMethods()).forEach(method -> {
GetMapping getMappingAnnotation = method.getDeclaredAnnotation(GetMapping.class);
String methodMapping = null;
if (getMappingAnnotation != null) {
methodMapping = getMappingAnnotation.value();
methodMapping = "get_" + methodMapping;
PostMapping postMappingAnnotation = method.getDeclaredAnnotation(PostMapping.class);
if (postMappingAnnotation != null) {
methodMapping = postMappingAnnotation.value();
methodMapping = "post_" + methodMapping;
if (methodMapping != null) {
controllerDefinition.getMethodMappingMap().put(methodMapping, method);
controllerBeanMap.put(requestMapping, controllerDefinition);
System.out.println(beanFactory);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
private static void parseFile(File file) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if (file.isDirectory()) {
File[] childFiles = file.listFiles();
for (File childFile : childFiles) {
String absPath = file.getAbsolutePath();
String fullClassPath = absPath.substring(path.length());
if (fullClassPath.endsWith(".class")) {
String fullClassPathName = fullClassPath.substring(0, fullClassPath.length() - ".class".length());
String fullClassName = fullClassPathName.replaceAll("\\\\", ".");
Class> clazz = Class.forName(fullClassName);
if (clazz.toString().startsWith("class")) {
if (!Modifier.isAbstract(clazz.getModifiers())) {
Optional
optional = Arrays.stream(clazz.getDeclaredAnnotations()).filter(annotation -> { return (annotation instanceof Controller || annotation instanceof Service || annotation instanceof Repository);
if (!optional.isEmpty()) {
Object bean = clazz.getDeclaredConstructor().newInstance();
beanFactory.put(fullClassName, bean);
4、ContextLoaderListener
package com.csdn.mymvc.listener;
import com.csdn.mymvc.core.ComponentScan;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;
public class ContextLoaderListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
Class.forName("com.csdn.mymvc.core.ComponentScan");
ServletContext application = sce.getServletContext();
application.setAttribute("beanFactory", ComponentScan.beanFactory);
application.setAttribute("controllerBeanMap", ComponentScan.controllerBeanMap);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
5、FruitController
package com.csdn.fruit.controller;
import com.csdn.fruit.dto.PageInfo;
import com.csdn.fruit.dto.PageQueryParam;
import com.csdn.fruit.dto.Result;
import com.csdn.fruit.pojo.Fruit;
import com.csdn.fruit.service.FruitService;
import com.csdn.fruit.util.RequestUtil;
import com.csdn.fruit.util.ResponseUtil;
import com.csdn.mymvc.annotation.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@RequestMapping("/fruit")
public class FruitController {
private FruitService fruitService;
protected void index(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pageNoStr = req.getParameter("pageNo");
if (pageNoStr != null && !"".equals(pageNoStr)) {
pageNo = Integer.parseInt(pageNoStr);
String keywordStr = req.getParameter("keyword");
if (keywordStr != null) {
PageQueryParam pageQueryParam = new PageQueryParam(pageNo, 5, keyword);
PageInfo pageInfo = fruitService.getFruitPageInfo(pageQueryParam);
Result result = Result.OK(pageInfo);
ResponseUtil.print(resp, result);
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Fruit fruit = (Fruit) RequestUtil.readObject(req, Fruit.class);
fruitService.addFruit(fruit);
ResponseUtil.print(resp, Result.OK());
protected void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer fid = Integer.parseInt(req.getParameter("fid"));
fruitService.delFruit(fid);
ResponseUtil.print(resp, Result.OK());
protected void edit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer fid = Integer.parseInt(req.getParameter("fid"));
Fruit fruit = fruitService.getFruitById(fid);
ResponseUtil.print(resp, Result.OK(fruit));
public void getFname(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String fname = req.getParameter("fname");
Fruit fruit = fruitService.getFruitByFname(fname);
ResponseUtil.print(resp, fruit == null ? Result.OK() : Result.Fail());
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Fruit fruit = (Fruit) RequestUtil.readObject(req, Fruit.class);
fruitService.updateFruit(fruit);
ResponseUtil.print(resp, Result.OK());
6、有一个小bug,查询的时候需要重置为首页
6.1、index.js
window.onload=function(){
keyword=$("#keyword").value
}else if (str == "pre") {
}else if (str == "next") {
}else if (str == "last") {
if (pageNo > pageCount) {
loadData=function(pageNo=1){
let fruitList = response.data.data.list
pageNo = response.data.data.pageNo
pageCount = response.data.data.pageCount
let fruitArr = fruitList;
let fruitTbl = $("#fruit_tbl")
for (let i = rows.length - 1; i >= 1; i--) {
for (let i = 0; i < fruitArr.length; i++) {
let tr = fruitTbl.insertRow();
let fnameTD = tr.insertCell();
let priceTD = tr.insertCell();
let fcountTD = tr.insertCell();
let operTD = tr.insertCell();
fnameTD.
innerHTML =
'fid +
'">' + fruit.
fname +
'';
priceTD.innerText = fruit.price;
fcountTD.innerText = fruit.fcount;
operTD.
innerHTML =
" + fruit.fid + ")\"/>";delFruit = function (fid) {
if (window.confirm('是否确认删除?')) {
if (response.data.flag) {
window.location.reload();