1.封裝請(qǐng)求數(shù)據(jù)
1.將方法的httpservletrequest和httpservletresponse參數(shù)封裝到參數(shù)數(shù)組進(jìn)行反射調(diào)用
1.修改SunDispatcherServlet.java的executeDispatch方法
//請(qǐng)求分發(fā)
private void executeDispatch(HttpServletRequest request, HttpServletResponse response) {
//獲取映射對(duì)象
SunHandler sunHandler = getSunHandler(request);
//映射對(duì)象不等于空則反射調(diào)用controller的方法
if (sunHandler != null) {
try {
/**
* 1.這里的的方法調(diào)用方式只支持有兩個(gè)參數(shù)的方法
* 2.將實(shí)參放到參數(shù)數(shù)組,然后給這個(gè)invoke方法設(shè)置可變參數(shù)
*/
//1.獲取目標(biāo)方法的形參列表
Class<?>[] parameterTypes = sunHandler.getMethod().getParameterTypes();
//2.創(chuàng)建實(shí)參列表
Object[] objects = new Object[parameterTypes.length];
//3.遍歷形參列表,將實(shí)參的類型跟形參匹配并填充到實(shí)參列表中
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 {
//當(dāng)映射對(duì)象是空的時(shí)候,返回404
try {
response.getWriter().write("<h1>404 not found!</h1>");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.debug測(cè)試
2.封裝http請(qǐng)求參數(shù)
1.需求分析
2.自定義注解RequestsParam
package com.Sun.sunspringmvc.annotation;
import java.lang.annotation.*;
/**
* @author 孫顯圣
* @version 1.0
*/
@Target(ElementType.PARAMETER) //作用于方法中的參數(shù)
@Retention(RetentionPolicy.RUNTIME) //作用范圍
@Documented
public @interface RequestsParam {
String value() default "";
}
3.修改MonsterService接口,添加方法
4.修改MonsterServiceImpl.java添加方法
//根據(jù)姓名返回妖怪對(duì)象數(shù)組
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));
//根據(jù)姓名查找
//存放結(jié)果
ArrayList<Monster> monsters1 = new ArrayList<Monster>();
for (Monster monster : monsters) {
if (monster.getName().equals(name)) {
monsters1.add(monster);
}
}
return monsters1;
}
5.修改SunDispatcherServlet.java編寫方法根據(jù)請(qǐng)求參數(shù)的名字判斷對(duì)應(yīng)于形參列表的哪個(gè)位置
//根據(jù)請(qǐng)求參數(shù)的名字判斷對(duì)應(yīng)于形參列表的哪個(gè)位置,如果沒有對(duì)應(yīng)的則返回-1
public int getIndexRequestParameterIndex(Method method, String name) {
//遍歷方法的參數(shù)列表
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
//獲取參數(shù)對(duì)象,查看是否有注解RequestParam
Parameter parameter = parameters[i];
if (parameter.isAnnotationPresent(RequestsParam.class)) { //如果有這個(gè)注解
//得到這個(gè)注解
RequestsParam annotation = parameter.getAnnotation(RequestsParam.class);
//如果這個(gè)注解的值和請(qǐng)求的參數(shù)相同,則返回這個(gè)位置
if (annotation.value().equals(name)) {
return i;
}
}
}
//遍歷之后如果沒有找到對(duì)應(yīng)位置返回-1
return -1;
}
6.修改SunDispatcherServlet.java的executeDispatch方法
7.單元測(cè)試
8.通過參數(shù)名匹配
1.修改SunDispatcherServlet.java的executeDispatch方法
2.添加方法
//獲取目標(biāo)方法所有形參名并以列表的形式返回
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.單元測(cè)試
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(":")) {
//根據(jù)冒號(hào)分割
String[] split = ((String) result).split(":");
String type = split[0];
String name = split[1];
if (type.equals("forward")) {
// /login_ok.jsp
try {
//請(qǐng)求轉(zhuǎn)發(fā)
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 {
//沒有冒號(hào)比如login.jsp, 默認(rèn)請(qǐng)求轉(zhuǎn)發(fā)
try {
request.getRequestDispatcher("/" + result).forward(request, response);
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.單元測(cè)試
4.自定義ResponseBody注解
1.需求分析
2.編寫注解ResponseBody.java
package com.Sun.sunspringmvc.annotation;
import java.lang.annotation.*;
/**
* 用于標(biāo)識(shí)一個(gè)要返回json數(shù)據(jù)的方法
*
* @author 孫顯圣
* @version 1.0
*/
@Target(ElementType.METHOD) //作用目標(biāo)是方法
@Retention(RetentionPolicy.RUNTIME) //作用范圍
@Documented
public @interface ResponseBody {
}
3.編寫Controller,MonsterController.java
//編寫一個(gè)方法,添加ResponseBody注解,返回json數(shù)據(jù)
@ResponseBody
@RequestMapping(value = "monster/list/json")
public List<Monster> listMonsterByJson(HttpServletRequest request, HttpServletResponse response) {
List<Monster> monsters = monsterService.listMonsters();
return monsters;
}
4.引入Json格式轉(zhuǎn)換工具jackjson
<!--引入jackson 使用它的工具可以進(jìn)行json類型轉(zhuǎn)換-->
<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) { //如果結(jié)果類型是ArrayList則表明可能要求返回的是Json形式
//得到這個(gè)目標(biāo)方法對(duì)象
Method method = sunHandler.getMethod();
//判斷是否含有ResponseBody注解
if (method.isAnnotationPresent(ResponseBody.class)) { //如果有,則以json形式返回?cái)?shù)據(jù)
//把返回的結(jié)果轉(zhuǎn)換成json格式的數(shù)據(jù)
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(result);
//返回給瀏覽器
//注意設(shè)置字符編碼
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(json);
//刷新和關(guān)閉
writer.flush();
writer.close();
}
}
6.單元測(cè)試
文章來源:http://www.zghlxwxcb.cn/news/detail-860928.html
5.SpringMVC框架總結(jié)
文章來源地址http://www.zghlxwxcb.cn/news/detail-860928.html
到了這里,關(guān)于實(shí)現(xiàn)SpringMVC底層機(jī)制(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!