通过反射实例化对象
本节介绍JSP 提交的参数名称带有不同的实例名称,通过反射机制对不同的对象类型进行实例化。
项目结构:
代码
先建立两个简单javaBean 对象:
学生类
package cn.lyx.reflact;
import java.io.Serializable;
/**
* @author ShayneLee
*/
public class Student implements Serializable{
private String name;
private Integer age;
private Double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
}
}
老师类
package cn.lyx.reflact;
/**
* Created by ShayneLee on 2017/11/8
*/
public class Teacher {
private String work;
private Double wages;
public void setWork(String work) {
this.work = work;
}
public String getWork() {
return work;
}
public void setWages(Double wages) {
this.wages = wages;
}
public Double getWages() {
return wages;
}
@Override
public String toString() {
return work + "," +wages;
}
}
然后建一个公共servlet 父类,这个类主要是统一处理反射调用,转发等。
package cn.lyx.servlet;
import cn.lyx.util.BeanOperateTools;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
/**
* 这是Servlet 的父类,统一在此类做请求响应分发,跳转。
* @author ShayneLee
*/
public abstract class DispatcherServlet extends HttpServlet{
private HttpServletRequest request;
private HttpServletResponse response;
// 统一处理request,response
public HttpServletRequest getRequest() {
return request;
}
public HttpServletResponse getResponse() {
return response;
}
@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 {
this.request = req;
this.response = resp;
String url = "/jsp/default.jsp"; // 默认跳转路径
Object obj = this.getBean(req); // 反射调用要操作的对象实例名称
String uri = req.getRequestURI();
String status = uri.substring(uri.lastIndexOf("/")+1);
Class<?> cls = this.getClass();// 这里一定用 this.getClass 而不是DispatcherServlet.class,否则取不到方法
try {
Method method = cls.getMethod(status);
// 反射调用子类状态操作方法 如 insert()
url = method.invoke(this).toString();
} catch (Exception e) {
e.printStackTrace();
}
String paramObj = obj.getClass().getSimpleName().toLowerCase();
req.setAttribute(paramObj, obj);
req.getRequestDispatcher(url).forward(req, resp);
}
/**
* 反射调用取得要操作的对象
* @param request
* @return
*/
public Object getBean(HttpServletRequest request){
String fullParamName = null;
Enumeration<String> enu = request.getParameterNames();
Object resultObj = null;
while (enu.hasMoreElements()) {
fullParamName = enu.nextElement();
// 获取参数参数名称. 号前面的名称, 如获取student.name 的student
if (fullParamName.contains(".")){
String[] temp = fullParamName.split("\\.");
String objName = temp[0];
String firstUp = objName.substring(0,1).toUpperCase()
.concat(objName.substring(1).toLowerCase());
Method met = null;
try {
// 这里一定用 this.getClass 而不是DispatcherServlet.class,否则取不到方法
// 调用子类servlet 的获取对象实例方法 如 getStudent
met = this.getClass().getMethod("get" + firstUp);
resultObj = met.invoke(this);
// 设置属性值 如 设置属性 name 的值
String paramName = temp[1];
String paramValue = request.getParameter(fullParamName);
BeanOperateTools.setValueSimple(resultObj, paramName, paramValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return resultObj;
}
}
两个子类servlet :
package cn.lyx.servlet;
import javax.servlet.annotation.WebServlet;
import cn.lyx.reflact.Student;
@WebServlet(urlPatterns={"/jsp/studentServlet/*"})
public class StudentServlet extends DispatcherServlet{
private static Student student = null;
/**
* 单例模式
* @return
*/
public static Student getStudent() {
if (student == null){
student = new Student();
}
return student;
}
public String insert() {
System.out.println("学生-添加成功");
return "/jsp/insert_do.jsp";
}
}
TeacerServlet:
package cn.lyx.servlet;
import cn.lyx.reflact.Teacher;
import javax.servlet.annotation.WebServlet;
@WebServlet(urlPatterns={"/jsp/teacherServlet/*"})
public class TeacherServlet extends DispatcherServlet{
private static Teacher teacher = null;
/**
* 单例模式
* @return
*/
public static Teacher getTeacher() {
if (teacher == null) {
teacher = new Teacher();
}
return teacher;
}
public String insert() {
System.out.println("老师-添加成功");
return "/jsp/insert_do.jsp";
}
}
一个设置属性工具类
package cn.lyx.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 利用反射进行属性参数设置,
* @author ShayneLee
*
*/
public class BeanOperateTools {
/**
* @author ShayneLee
* @param obj 要实例化的对象
* @param paramValue 传递输入的参数过来
* @throws Exception
*/
public static void setValueSimple(Object obj, String paramName, String paramValue)
throws Exception{
// 取得Class 对象
Class<?> cls = obj.getClass();
Field field = cls.getDeclaredField(paramName); // 为了获得指定参数类型
// 首字母大写
String firstUp = paramName.substring(0,1).toUpperCase()
.concat(paramName.substring(1).toLowerCase());
// 取得set操作方法,满足反射调用
Method method = cls.getMethod("set" + firstUp, field.getType());
// 根据类型进行数据的装换,同时调用setter 设置数据
String fiedlType = field.getType().getSimpleName().toLowerCase();
switch (fiedlType) {
case "string":
method.invoke(obj, paramValue);
break;
case "int":
method.invoke(obj, Integer.parseInt(paramValue));
break;
case "integer":
method.invoke(obj, Integer.parseInt(paramValue));
break;
case "double":
method.invoke(obj, Double.parseDouble(paramValue));
break;
default:
break;
}
}
}
JSP 页面部分
学生添加的页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>首页</title>
</head>
<body>
<%
request.setCharacterEncoding("UTF-8");
%>
<form action="studentServlet/insert" method="post">
学生姓名:<input type="text" name="student.name"><br>
学生年龄:<input type="text" name="student.age"><br>
学生成绩:<input type="text" name="student.score"><br>
<input type="submit" value="输入">
<input type="reset" value="重置">
</form>
</body>
</html>
老师添加jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>首页</title>
</head>
<body>
<%
request.setCharacterEncoding("UTF-8");
%>
<form action="teacherServlet/insert" method="post">
老师职业:<input type="text" name="teacher.work"><br>
老师工资:<input type="text" name="teacher.wages"><br>
<input type="submit" value="输入">
<input type="reset" value="重置">
</form>
</body>
</html>
公共结果jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8"); %>
<html>
<head>
<title>Java Bean 操作</title>
</head>
<body>
<h5>学生姓名 : ${student.name}</h5>
<h5>学生年龄 : ${student.age}</h5>
<h5>学生成绩 : ${student.score}</h5>
<h5>老师职业 : ${teacher.work}</h5>
<h5>老师工资 : ${teacher.wages}</h5>
</body>
</html>
测试
添加学生信息:
结果:
老师信息添加:
结果:
总结
本例主要是测试通过反射实例化不同的对象。做法是通过请求的参数名带上不同的实例名称, servlet 接收到请求的参数信息,通过反射调用对应的实例对象进行属性赋值操作。可见Servlet 通过反射的方式把公共代码部分组合在一起,大大减少了代码冗余部分,遵循高内聚,低耦合,可复用原则 提高了开发效率。