1.封装请求数据
1.将方法的httpservletrequest和httpservletresponse参数封装到参数数组进行反射调用
1.修改SunDispatcherServlet.java的executeDispatch方法
//请求分发
private void executeDispatch(HttpServletRequest request, HttpServletResponse response) {
//获取映射对象
SunHandler sunHandler = getSunHandler(request);
//映射对象不等于空则反射调用controller的方法
if (sunHandler != null) {
try {
/**
* 1.这里的的方法调用方式只支持有两个参数的方法
* 2.将实参放到参数数组,然后给这个invoke方法设置可变参数
*/
//1.获取目标方法的形参列表
Class<?>[] parameterTypes = sunHandler.getMethod().getParameterTypes();
//2.创建实参列表
Object[] objects = new Object[parameterTypes.length];
//3.遍历形参列表,将实参的类型跟形参匹配并填充到实参列表中
for (int i = 0; i < parameterTypes.length; i++) {
//封装HttpServletRequest request, HttpServletResponse response
if ("HttpServletRequest".equals(parameterTypes[i].getSimpleName())) {
objects[i] = request;
}
if ("HttpServletResponse".equals(parameterTypes[i].getSimpleName())) {
objects[i] = response;
}
}
sunHandler.getMethod().invoke(sunHandler.getController(),objects);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
} else {
//当映射对象是空的时候,返回404
try {
response.getWriter().write("<h1>404 not found!</h1>");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.debug测试
2.封装http请求参数
1.需求分析
2.自定义注解RequestsParam
package com.Sun.sunspringmvc.annotation;
import java.lang.annotation.*;
/**
* @author 孙显圣
* @version 1.0
*/
@Target(ElementType.PARAMETER) //作用于方法中的参数
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface RequestsParam {
String value() default "";
}
3.修改MonsterService接口,添加方法
4.修改MonsterServiceImpl.java添加方法
//根据姓名返回妖怪对象数组
public List<Monster> findMonstersByName(String name) {
ArrayList<Monster> monsters = new ArrayList<Monster>();
monsters.add(new Monster(1, "牛魔王", "芭蕉扇", 500));
monsters.add(new Monster(2, "蜘蛛精", "吐口水", 200));
monsters.add(new Monster(3, "蜘蛛精", "吐口水", 200));
monsters.add(new Monster(4, "蜘蛛精", "吐口水", 200));
monsters.add(new Monster(5, "蜘蛛精", "吐口水", 200));
//根据姓名查找
//存放结果
ArrayList<Monster> monsters1 = new ArrayList<Monster>();
for (Monster monster : monsters) {
if (monster.getName().equals(name)) {
monsters1.add(monster);
}
}
return monsters1;
}
5.修改SunDispatcherServlet.java编写方法根据请求参数的名字判断对应于形参列表的哪个位置
//根据请求参数的名字判断对应于形参列表的哪个位置,如果没有对应的则返回-1
public int getIndexRequestParameterIndex(Method method, String name) {
//遍历方法的参数列表
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
//获取参数对象,查看是否有注解RequestParam
Parameter parameter = parameters[i];
if (parameter.isAnnotationPresent(RequestsParam.class)) { //如果有这个注解
//得到这个注解
RequestsParam annotation = parameter.getAnnotation(RequestsParam.class);
//如果这个注解的值和请求的参数相同,则返回这个位置
if (annotation.value().equals(name)) {
return i;
}
}
}
//遍历之后如果没有找到对应位置返回-1
return -1;
}
6.修改SunDispatcherServlet.java的executeDispatch方法
7.单元测试
8.通过参数名匹配
1.修改SunDispatcherServlet.java的executeDispatch方法
2.添加方法
//获取目标方法所有形参名并以列表的形式返回
public List<String> getParameterNames(Method method) {
List<String> parNames = new ArrayList<String>();
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
String name = parameter.getName();
parNames.add(name);
}
return parNames;
}
3.引入插件pom.xml否则getName得到的形参列表是下面的[arg0, arg1, arg2]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<encoding>utf-8</encoding>
</configuration>
</plugin>
4.单元测试
2.完成视图解析
1.需求分析
2.框架搭建
1.编写Service
1.MonsterService.java
2.MonsterServiceImpl.java添加方法
//处理登录的方法
@Override
public boolean login(String name) {
if ("sun".equals(name)) {
return true;
}
return false;
}
2.编写MonsterController.java添加方法
@RequestMapping("monster/login")
public String login(String mName) {
System.out.println("接收到的名字=" + mName);
boolean login = monsterService.login(mName);
if (login) {
//返回给视图解析器
return "forward:/login_ok.jsp";
} else {
return "forward:/login_error.jsp";
}
}
3.编写login.jsp
<%--
Date: 2024/2/28
Time: 13:54
User: 孙显圣
Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="get" action="monster/login">
姓名:<input name="mName" type="text"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
4.login_ok.jsp
<%--
Date: 2024/2/28
Time: 13:56
User: 孙显圣
Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录成功</h1>
欢迎你:${?}
</body>
</html>
5.login_error.jsp
<%--
Date: 2024/2/28
Time: 13:56
User: 孙显圣
Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录失败</h1>
欢迎你:${?}
</body>
</html>
6.修改SunDispatcherServlet.java解决中文乱码问题
3.完成基本视图解析器
1.修改SunDispatcherServlet.java
//以下是视图解析器
//1.判断是否是字符串
if (result instanceof String) {
//判断是否包含:
if (((String) result).contains(":")) {
//根据冒号分割
String[] split = ((String) result).split(":");
String type = split[0];
String name = split[1];
if (type.equals("forward")) {
// /login_ok.jsp
try {
//请求转发
request.getRequestDispatcher(name).forward(request, response);
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else if (type.equals("redirect")) {
//重定向
String fill = "/sun_springmvc";
try {
response.sendRedirect(fill + name);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} else {
//没有冒号比如login.jsp, 默认请求转发
try {
request.getRequestDispatcher("/" + result).forward(request, response);
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.单元测试
4.自定义ResponseBody注解
1.需求分析
2.编写注解ResponseBody.java
package com.Sun.sunspringmvc.annotation;
import java.lang.annotation.*;
/**
* 用于标识一个要返回json数据的方法
*
* @author 孙显圣
* @version 1.0
*/
@Target(ElementType.METHOD) //作用目标是方法
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface ResponseBody {
}
3.编写Controller,MonsterController.java
//编写一个方法,添加ResponseBody注解,返回json数据
@ResponseBody
@RequestMapping(value = "monster/list/json")
public List<Monster> listMonsterByJson(HttpServletRequest request, HttpServletResponse response) {
List<Monster> monsters = monsterService.listMonsters();
return monsters;
}
4.引入Json格式转换工具jackjson
<!--引入jackson 使用它的工具可以进行json类型转换-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
5.修改SunDispatcherServlet.java,在executeDispatch方法添加逻辑
else if (result instanceof ArrayList) { //如果结果类型是ArrayList则表明可能要求返回的是Json形式
//得到这个目标方法对象
Method method = sunHandler.getMethod();
//判断是否含有ResponseBody注解
if (method.isAnnotationPresent(ResponseBody.class)) { //如果有,则以json形式返回数据
//把返回的结果转换成json格式的数据
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(result);
//返回给浏览器
//注意设置字符编码
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(json);
//刷新和关闭
writer.flush();
writer.close();
}
}
6.单元测试
文章来源:https://www.toymoban.com/news/detail-860928.html
5.SpringMVC框架总结
文章来源地址https://www.toymoban.com/news/detail-860928.html
到了这里,关于实现SpringMVC底层机制(三)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!