java 反射机制-学习笔记(4)

servlet 自定义反射

如果在jsp 页面直接写 javaBean 标签会显得重复啰嗦,解决这个问题就是要把它单独作为一个组件。先看在servlet 中通过反射接受、设置参数的例子。
继续上次的项目添加一个 StudentServlet 类:

package cn.lyx.servlet;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.lyx.reflact.Student;
@WebServlet(urlPatterns={"/jsp/StudentServlet"})
public class StudentServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        super.doGet(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        Object student = null;
        try {
            // 取得Class 对象
            Class<?> cls = Class.forName("cn.lyx.reflact.Student");
            student = cls.newInstance(); // 实例化对象
            // 取得所有输入的参数名称
            Enumeration<String> enu = req.getParameterNames();
            // 遍历获取输入的参数
            while(enu.hasMoreElements()){
                String paramName = enu.nextElement();
                String paramValue = req.getParameter(paramName);
                // 通过反射获得指定属性
                // 因为输入 的参数名称和对象属性名称一致,可以把属性和输出参数名称一一对应操作。
                // 取得属性的类型是为了取得参数的类型,以确定method 方法,和是否转型
                Field field = cls.getDeclaredField(paramName);  // 获得指定参数
                // 首字母大写,比如 name 的set 方法名是  setName(首字母大写)
                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(student, paramValue);  // 通过反射调用方法
                    break;
                case "int":
                    method.invoke(student, Integer.parseInt(paramValue));
                    break;
                case "integer":
                    method.invoke(student, Integer.parseInt(paramValue));
                    break;
                case "double":
                    method.invoke(student, Double.parseDouble(paramValue));
                    break;
                default:
                    break;
                }

            }

        } catch ( Exception  e) {

            e.printStackTrace();
        }
        req.setAttribute("student", student);
        req.getRequestDispatcher("student_insert_do.jsp").forward(req, resp);
    }
}

可以看到StudentServlet 类中通过反射的方式完成了 Student 的实例化以及设置属性值。

修改 index.jsp ,只是换了请求action 的值,和servlet 中的urlPatterns值对应。 如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>首页</title>
</head>
<body>
    <%
        request.setCharacterEncoding("UTF-8");
    %>
    <form action="StudentServlet" method="post">
        姓名:<input type="text" name="name"><br>
        年龄:<input type="text" name="age"><br>
        成绩:<input type="text" name="score"><br>
        <input type="submit" value="输入">
        <input type="reset"  value="重置">
    </form>
</body>
</html>

student_insert_do.jsp 修改比较大,去掉所有javaBean标签,留下简洁的 ${}取值。 修改如下:

<%@ 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> 
</body>
</html>

如之前一样测试,结果正常。

反射组件封装

上面的反射部分直接写在servlet 中,假如有多个servlet那么需要一个个去重复写,不符合可复用的开发原则。那么就需要单独封装在工具类中。
新建一个工具类 :

package cn.lyx.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;

import javax.servlet.ServletRequest;
/**
 * 利用反射进行所有请求参数设置,
 * @author ShayneLee
 * 
 */
public class BeanOperateTools {
    /**
     * 
     * @param obj 传递过来要操作的对象
     * @param req 传递输入的参数过来
     * @throws Exception
     */
    public static void setValueSimple(Object obj, ServletRequest req)
        throws Exception{
        // 取得Class 对象
        Class<?> cls = obj.getClass();
        // 这里把之前的那个实例化语句删除。因为传递过来的对象已经被实例化过了,这里就不用重复实例化
        // 取得所有输入的参数名称
        Enumeration<String> enu = req.getParameterNames();
        // 遍历获取输入的参数
        while(enu.hasMoreElements()){
            String paramName = enu.nextElement();
            String paramValue = req.getParameter(paramName);
            // 因为输入 的参数名称和对象属性名称一致,可以把属性和输出参数名称一一对应操作。
            // 取得属性的类型是为了取得参数的类型,以确定method 方法,和是否转型
            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;
            }

        }
    }
}

这个工具类直接把 servlet 类中的反射部分复制过来。

修改StudentServlet类如下:

package cn.lyx.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.lyx.reflact.Student;
import cn.lyx.util.BeanOperateTools;

@WebServlet(urlPatterns={"/jsp/StudentServlet"})
public class StudentServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        super.doGet(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        Student student = new Student();
        // 调用反射工具类
        try {
            BeanOperateTools.setValueSimple(student, req);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        req.setAttribute("student", student);
        req.getRequestDispatcher("student_insert_do.jsp").forward(req, resp);
    }
}

看到这样的 servlet 类,是不是感觉世界清静了很多。

如同之前的测试,一切正常。

参考:魔乐科技-李兴华-java 反射机制

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值