这篇文章将进行属性的获取与返回的开发。
在Servlet中,属性是通过request中的parameterMap获取的。通过 request.getParameter("name名称") 取得,还不知道获取的类型。
在Struts2中,是用过类的字段获取,或者模型驱动获取自定义的实体类。
在Spring MVC中,我们是通过方法参数的名称去实现的。
在我这次的开发中,我打算使用类似Spring MVC的方式。(由于java 中 的方法的参数的名称是无法获取到的,要从文件中的名称获取或者其它方式,在 编译之前就拿到,这样让新手很难理解)所以,我使用了注解的方式去获取。
https://github.com/yyfyyf1994/MyWebFrame
首先,在html中写一个表单
<form action="/user/add.do" method="post">
用户ID:<input type="text" name="userId">
<br>用户名:<input type="text" name="userName">
<br>备注信息:<input type="text" name="note">
<br><input type="submit" value="提交">
</form>
然后,我们需要一个处理此post请求的Action
@MyAction("/user")
public class UserAction {
private static List<User> users = new ArrayList<User>();
static {
for (long i = 0; i < 8; i++) {
users.add(new User(i, "用户" + i));
}
}
@MyAction("/list")
public Model userList() {
Model model = new Model();
model.addAttribute("users", users);
model.setReturnPath("user/list");
return model;
}
@MyAction("/add")
public Model userAdd(@MyParam("user") User user, @MyParam("note") String note) {
Model model = new Model();
model.addAttribute("message", "增加用户成功!");
users.add(user);
System.out.println("note:"+note);
model.addAttribute("users", users);
model.setReturnPath("user/list");
return model;
}
}
,如果直接在网页中调试开发,比较蛮烦。我们直接模拟一个request的parameterMap,并往里面填好参数。下面是测试实现过程
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class clazz = UserAction.class;
Object object = clazz.newInstance();
Method method = clazz.getMethod("userAdd", User.class, String.class);
Annotation[][] annotations = method.getParameterAnnotations();
Class<?>[] classes = method.getParameterTypes();
Map<String, String[]> reqMap = new HashMap<String, String[]>();
reqMap.put("userId", new String[]{"123"});
reqMap.put("userName", new String[]{"用户1"});
reqMap.put("note", new String[]{"这是备注信息"});
Object[] prarms = new Object[classes.length];
for (int i = 0; i < classes.length; i++) {
//获取方法上参数的注解
MyParam myParam = (MyParam) annotations[i][0];
Class<?> clz = classes[i];
// System.out.println(clz + " " + myParam.value());
Object cob = null;
//如果是基本类型
if (ConvertFactory.isJavaClass(clz)) {
for (String s : reqMap.keySet()) {
//找到对应的参数
if (myParam.value().equals(s)) {
try {
cob = ConvertFactory.convert(clz, reqMap.get(s)[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
//填充数据
prarms[i] = cob;
}
} else if (clz == List.class) {
//如果是集合类
} else {
//如果是自定义实体
Object paramObject = clz.newInstance();
LoadUtil.getMyObject(reqMap, clz, paramObject);
prarms[i] = paramObject;
}
}
method.invoke(object, prarms);
}
LoadUtil.java
package myframe.commons;
import myframe.annotation.MyParam;
import myframe.convert.ConvertFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
/**
* Created by yuyufeng on 2017/5/18.
*/
public class LoadUtil {
/**
* 参数装载
* @param reqMap
* @param method
* @param prarms
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static void loadParams(Map<String, String[]> reqMap, Method method, Object[] prarms) throws InstantiationException, IllegalAccessException {
Class<?>[] classes = method.getParameterTypes();
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < classes.length; i++) {
//获取方法上参数的注解
MyParam myParam = (MyParam) annotations[i][0];
Class<?> clz = classes[i];
// System.out.println(clz + " " + myParam.value());
Object cob = null;
//如果是基本类型
if (ConvertFactory.isJavaClass(clz)) {
for (String s : reqMap.keySet()) {
//找到对应的参数
if (myParam.value().equals(s)) {
try {
cob = ConvertFactory.convert(clz, reqMap.get(s)[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
//填充数据
prarms[i] = cob;
}
} else if (clz == List.class) {
//如果是集合类
} else {
//如果是自定义实体
Object paramObject = clz.newInstance();
getMyObject(reqMap, clz, paramObject);
prarms[i] = paramObject;
}
}
}
//自定义对象装载
public static void getMyObject(Map<String, String[]> reqMap, Class<?> clz, Object paramObject) {
List<Method> methods = GetterSetterUtil.setter(clz);
for (Method method1 : methods) {
Class<?> method1PrarmType = method1.getParameterTypes()[0];
String pName = GetterSetterUtil.getPropertyName(method1);
for (String s : reqMap.keySet()) {
//判断对象里面有getParam方法
if (pName.equals(s)) {
//对象里面的参数也是基本类型。如果自定义对象里面还有自定义对象,则此处需要做递归处理
if (ConvertFactory.isJavaClass(method1PrarmType)) {
try {
method1.invoke(paramObject, ConvertFactory.convert(method1PrarmType, reqMap.get(s)[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
我们在方法里面添加上打印信息,以确定执行过该方法,并且成功传递了参数
@MyAction("/add")
public Model userAdd(@MyParam("user") User user, @MyParam("note") String note) {
Model model = new Model();
model.addAttribute("message", "增加用户成功!");
users.add(user);
System.out.println("note:"+note);
System.out.println("user:"+user);
model.addAttribute("users", users);
model.setReturnPath("user/list");
return model;
}
执行之后,控制台信息:
Connected to the target VM, address: '127.0.0.1:64455', transport: 'socket'
note:这是备注信息
user:User{userId=123, userName='用户1'}
Disconnected from the target VM, address: '127.0.0.1:64455', transport: 'socket'
Process finished with exit code 0
可以看到,我们的方法已经执行了。并且。参数也成功传递了。
然后,我们需要将参数传递给页面,我也构造了一个Model类,去传递(类似Spring MVC),这样就方便很多
package myframe.bean;
import myframe.enums.ReturnTypeEnum;
import java.util.HashMap;
import java.util.Map;
/**
* Created by yuyufeng on 2017/5/17.
*/
public class Model {
private ReturnTypeEnum returnType = ReturnTypeEnum.forward; //响应类型
private String returnPath; //返回路径
private Map<String, Object> map = new HashMap<String, Object>();
public void addAttribute(String var1, Object var2) {
map.put(var1, var2);
}
public Map<String, Object> getModelMap() {
return map;
}
public ReturnTypeEnum getReturnType() {
return returnType;
}
public void setReturnType(ReturnTypeEnum returnType) {
this.returnType = returnType;
}
public String getReturnPath() {
return returnPath;
}
public void setReturnPath(String returnPath) {
this.returnPath = returnPath;
}
}
在Servlet入口类中,这么返回:
//判断返回的类型,然后执行不同的动作
if (returnType == Model.class) {
Model modelResult = (Model) result;
path = modelResult.getReturnPath();
//重定向
if (modelResult.getReturnType() == ReturnTypeEnum.redirect) {
System.out.println("执行重定向完毕,跳转路径" + path);
resp.sendRedirect(path);
}
//设置属性
for (String s : modelResult.getModelMap().keySet()) {
req.setAttribute(s, modelResult.getModelMap().get(s));
}
} else if (returnType == String.class) {
path = (String) result;
}
System.out.println("执行完毕,跳转路径" + "/WEB-INF/jsp/" + path + ".jsp"); ///WEB-INF/jsp/这些暂时写死,到时候可以到配置中获取
req.getRequestDispatcher("/WEB-INF/jsp/" + path + ".jsp").forward(req, resp);
这样我们的参数就可以成功传递到request的attribute里面了
现在在整理一下入口Servlet中的doGet()
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//获取要执行的动作
String uri = req.getRequestURI();
String actionName = uri.substring(0, uri.indexOf(".do"));
System.out.println("访问ActionMethod:" + actionName);
//do
String path = "";
ActionBean actionBean = MyFrameInit.getActionBean(actionName);
Object result;
try {
Class<?> returnType = actionBean.getMethod().getReturnType();
//执行方法的参数填充
Map<String, String[]> reqMap = req.getParameterMap();
Object[] prarms = new Object[actionBean.getMethod().getParameterTypes().length];
//参数装载
LoadUtil.loadParams(reqMap, actionBean.getMethod(), prarms);
result = actionBean.getMethod().invoke(MyFrameInit.getObject(actionBean.getClazz()), prarms);
//判断返回的类型,然后执行不同的动作
if (returnType == Model.class) {
Model modelResult = (Model) result;
path = modelResult.getReturnPath();
//重定向
if (modelResult.getReturnType() == ReturnTypeEnum.redirect) {
System.out.println("执行重定向完毕,跳转路径" + path);
resp.sendRedirect(path);
}
//设置属性
for (String s : modelResult.getModelMap().keySet()) {
req.setAttribute(s, modelResult.getModelMap().get(s));
}
} else if (returnType == String.class) {
path = (String) result;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
System.out.println("执行完毕,跳转路径" + "/WEB-INF/jsp/" + path + ".jsp"); ///WEB-INF/jsp/这些暂时写死,到时候可以到配置中获取
req.getRequestDispatcher("/WEB-INF/jsp/" + path + ".jsp").forward(req, resp);
}
建立的测试Action
package action;
import entity.User;
import myframe.annotation.MyAction;
import myframe.annotation.MyParam;
import myframe.bean.Model;
import myframe.commons.GetterSetterUtil;
import myframe.commons.LoadUtil;
import myframe.convert.ConvertFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by yuyufeng on 2017/5/17.
*/
@MyAction("/user")
public class UserAction {
private static List<User> users = new ArrayList<User>();
static {
for (long i = 0; i < 8; i++) {
users.add(new User(i, "用户" + i));
}
}
@MyAction("/list")
public Model userList() {
Model model = new Model();
model.addAttribute("users", users);
model.setReturnPath("user/list");
return model;
}
@MyAction("/add")
public Model userAdd(@MyParam("user") User user, @MyParam("note") String note) {
Model model = new Model();
model.addAttribute("message", "增加用户成功!");
users.add(user);
System.out.println("note:"+note);
System.out.println("user:"+user);
model.addAttribute("users", users);
model.setReturnPath("user/list");
return model;
}
}
部署启动tomcat
输入http://127.0.0.1:8080/user/list.do
MyFrameInit.init==================初始化完毕
访问ActionMethod:/user/list
执行完毕,跳转路径/WEB-INF/jsp/user/list.jsp
输入信息增加一个用户,点击提交
访问ActionMethod:/user/add
note:备注~
user:User{userId=123, userName='测试用户'}
执行完毕,跳转路径/WEB-INF/jsp/user/list.jsp
这样,MyFrame框架的属性自动获取和传递功能基本已经编写完毕