目录
项目构建
1、环境搭建
Maven项目,添加web模块
打war包并引入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
引入web
打开项目结构
web文件内容
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
</web-app>
2、项目结构
代码实现
1、 自定义注解
@Autowired
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MvcAutowired {
String value() default "";
}
@Controller
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MvcController {
String value() default "";
}
@RequestMapping
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MvcRequestMapping {
String value() default "";
}
@RequestParam
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MvcRequestParam {
String value() default "";
}
@Service
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MvcService {
String value() default "";
}
2、控制层
WriteController
@MvcController
@MvcRequestMapping("/write")
public class WriteController {
@MvcAutowired("WriteServiceImpl") //map.get("key)
private WriteService writeService;
@MvcRequestMapping("/query")
public void query(HttpServletRequest request, HttpServletResponse response,
@MvcRequestParam("name") String name,
@MvcRequestParam("age") String age) {
try {
PrintWriter pw=response.getWriter();
String result = writeService.query(name, age);
pw.write(result);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
3、服务层
WriteService
public interface WriteService {
//查询方法
String query(String name,String age);
}
4、实现层
@MvcService("WriteServiceImpl") //map.put(WriteServiceImpl,new WriteServiceImpl)
public class WriteServiceImpl implements WriteService {
@Override
public String query(String name, String age) {
return "name==="+name+"; age==="+age;
}
}
5、前端控制器
定义一个名为DispatcherServlet 的Spring MVC框架的前端控制器,负责接收HTTP请求,根据请求信息调用相应的处理方法,并返回相应的HTTP响应
public class DispatcherServlet extends HttpServlet {
List<String> classNames = new ArrayList<String>();
Map<String, Object> beans = new HashMap<String, Object>();
Map<String, Object> harldermap = new HashMap<String, Object>();
private static final long serialVersionUID = 1L;
public void init(ServletConfig config) {
//把所有的bean扫描 ----扫描所有的class文件
scanPackage("com.ll");
doInstance(); //根据全类名创建bean
doIoc(); //根据bean 进行依赖注入
buildUrlMapping(); //构建url映射
}
//com.enjoy
public void scanPackage(String basePackage) {
URL url = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));
String fileStr = url.getFile();
File file = new File(fileStr);
String[] filesStr = file.list();
for (String path : filesStr) {
File filePath = new File(fileStr + path);
if (filePath.isDirectory()) {
scanPackage(basePackage + "." + path);
} else {
//加入LIST
classNames.add(basePackage + "." + filePath.getName());
}
}
}
//根据扫描到的List全类名 进行实例化
public void doInstance() {
if (classNames.size() <= 0) {
System.out.println("没有扫描到任何类");
return;
}
//list的所有class
for (String className : classNames) {
String cn = className.replace(".class", "");
try {
Class<?> aClass = Class.forName(cn);
if (aClass.isAnnotationPresent(MvcController.class)) {
//是controller
Object instance = aClass.newInstance(); //创建控制类
MvcRequestMapping requestMapping = aClass.getAnnotation(MvcRequestMapping.class);
String rmvalue = requestMapping.value(); // /write
beans.put(rmvalue, instance);
} else if (aClass.isAnnotationPresent(MvcService.class)) {
//是service
Object instance = aClass.newInstance();
MvcService service = aClass.getAnnotation(MvcService.class);
String serviceName = service.value();
beans.put(serviceName, instance);
} else {
continue;
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
//把service注入到controller
public void doIoc() {
if (beans.entrySet().size() <= 0) {
System.out.println("没有一个实例化类");
}
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Object instance = entry.getValue();
Class<?> clazz = instance.getClass();
if (clazz.isAnnotationPresent(MvcController.class)) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(MvcAutowired.class)) {
MvcAutowired autowired = field.getAnnotation(MvcAutowired.class);
String key = autowired.value(); // 获取service的key
field.setAccessible(true);
try {
field.set(instance, beans.get(key));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} else {
continue;
}
}
}
}
}
private void buildUrlMapping() {
if (beans.entrySet().size() <= 0) {
System.out.println("没有一个实例化类");
return;
}
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Object instance = entry.getValue();
Class<?> clazz = instance.getClass();
if (clazz.isAnnotationPresent(MvcController.class)) {
MvcRequestMapping requestMapping = clazz.getAnnotation(MvcRequestMapping.class);
String classPath = requestMapping.value(); // /write
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MvcRequestMapping.class)) {
MvcRequestMapping methodMapping = method.getAnnotation(MvcRequestMapping.class);
String methodPath = methodMapping.value();
harldermap.put(classPath + methodPath, method); // 修改这里
} else {
continue;
}
}
}else{
continue;
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求路径
String url = req.getRequestURI();
String context = req.getContextPath(); //write-mvc
String path = url.replace(context, ""); //write/query
Method method = (Method) harldermap.get(path);
if (method == null) {
throw new RuntimeException("No handler method found for the path: " + path);
}
//根据key - /write 到 map去拿
WriteController instance= (WriteController) beans.get("/"+path.split("/")[1]);
Object arg[] = hand(req, resp, method);
try {
method.invoke(instance, arg);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static Object[] hand(HttpServletRequest request, HttpServletResponse response, Method method){
//拿到当前执行的方法有哪些参数
Class<?>[] paramClazzs = method.getParameterTypes();
//根据参数的个数 创建数组
Object[] args = new Object[paramClazzs.length];
int args_i=0;
int index=0;
for (Class<?> paramClazz : paramClazzs) {
if(ServletRequest.class.isAssignableFrom(paramClazz)){
args[args_i++] = request;
}
if(ServletResponse.class.isAssignableFrom(paramClazz)){
args[args_i++] = response;
}
Annotation[] paramAns = method.getParameterAnnotations()[index];
if (paramAns.length > 0) {
for (Annotation paramAn : paramAns) {
if(MvcRequestParam.class.isAssignableFrom(paramAn.getClass())){
MvcRequestParam requestParam = (MvcRequestParam) paramAn;
args[args_i++] = request.getParameter(requestParam.value());
}
}
}
index++;
}
return args;
}
6、web.xml
定义了一个名为DispatcherServlet的Servlet,并在服务器启动时加载(load-on-startup值为0)。映射该Servlet到所有以/开头的URL路径上。
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>com.ll.springmvc.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
效果
1、浏览器访问
http://localhost:8080/spring_mvc_war/
