Servlet开发简化

Servlet开发简化

使用原生的Servlet进行开发时会存在大量的重复代码,特别是doGet和doPost方法出现在每个Servlet中,使我们烦不胜烦,分发处理时需要重复的编写大量的if-else语句,参数接收时要不断地编写验证,参数过多时使用手工接收也略显不便。使用反射机制可以对这一切的弊端进行调整。

  1. 新建一个String工具类
package com.gub.util;

public class GUBStringUtil {
    /**
     * 将传入字符串首字母变成大写
     * @param data 传入字符串
     * @return
     */
    public static String initcap(String data){
        if(data==null||"".equals(data)){
            return data;
        }
        if(data.length()==1){
            return data.toUpperCase();
        }else{
            return data.substring(0,1).toUpperCase()+data.substring(1);
        }
    }
}
  1. 新建一个自动接收工具类帮我们自动接收对象。
package com.gub.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;

public class FillParam {
    private Object currentObj;//表示当前对象
    private String paramName;//需要设置内容的属性名称
    private String value;//属性值
    private String[] arrayValue;//属性数组
    private Field field;//表示当前属性

    /**
     * 构造接受需要设置当前程序执行的类对象,属性名称及属性值,并为其赋值
     * @param currentObj 需要设置属性的对象
     * @param paramName 属性名称
     * @param value 属性值
     */
    public FillParam(Object currentObj,String paramName,String value){
        this.currentObj = currentObj;
        this.paramName = paramName;
        this.value = value;
        try{
            this.paramInit();
            this.setValue();
        }catch(Exception e){e.printStackTrace();}
    }

    //当属性为数组类型时调用此构造
    public FillParam(Object currentObj,String paramName,String[] arrayValue){
        this.currentObj = currentObj;
        this.paramName = paramName;
        this.arrayValue = arrayValue;
        try{
            this.paramInit();
            this.setValue();
        }catch(Exception e){e.printStackTrace();}
    }


    public FillParam(Object currentObj,String paramName){
        this.currentObj = currentObj;
        this.paramName = paramName;
        try{
            this.paramInit();
        }catch(Exception e){e.printStackTrace();}
    }

    /**
     * 初始化各参数,取得传入对象的传入属性
     */
    private void paramInit() throws Exception{
        String[] result = this.paramName.split("\\.");//将属性名字按点拆分
        if(result.length==2){//表示只有一层关系
            //取得要设置属性的对象
            this.currentObj = this.currentObj.getClass().getMethod("get"
                    +GUBStringUtil.initcap(result[0])).invoke(this.currentObj);
            this.field = this.currentObj.getClass().getDeclaredField(result[1]);
        }else{//表示有多层关系
            for(int x=0;x<result.length;x++){
                //取得属性
                this.field = this.currentObj.getClass().getDeclaredField(result[x]);
                if(x<result.length-1){
                    //取得对象
                    this.currentObj = this.currentObj.getClass().getMethod("get"
                            +GUBStringUtil.initcap(result[x])).invoke(this.currentObj);
                }
            }
        }
    }

    private void setValue() throws Exception{
        String typeName = this.field.getType().getSimpleName();
        //取得set方法
        Method setMethod = this.currentObj.getClass().
                getMethod("set"+GUBStringUtil.initcap(this.field.getName()),
                        this.field.getType());
        if(typeName.contains("[]")){//如果是为数组属性设置值
            if("string[]".equalsIgnoreCase(typeName)){
                setMethod.invoke(this.currentObj,(Object)this.arrayValue);
            }else if("int[]".equalsIgnoreCase(typeName)){
                int[] temp = new int[this.arrayValue.length];
                for(int x=0;x<temp.length;x++){
                    temp[x] = Integer.parseInt(this.arrayValue[x]);
                }
                setMethod.invoke(this.currentObj,(Object)temp);
            }else if("Integer[]".equalsIgnoreCase(typeName)){
                Integer[] temp = new Integer[this.arrayValue.length];
                for(int x=0;x<temp.length;x++){
                    temp[x] = Integer.parseInt(this.arrayValue[x]);
                }
                setMethod.invoke(this.currentObj,(Object)temp);
            }else if("double[]".equals(typeName)){
                double[] temp = new double[this.arrayValue.length];
                for(int x=0;x<temp.length;x++){
                    temp[x] = Double.parseDouble(this.arrayValue[x]);
                }
                setMethod.invoke(this.currentObj,(Object)temp);
            }else if("Double[]".equals(typeName)){
                Double[] temp = new Double[this.arrayValue.length];
                for(int x=0;x<temp.length;x++){
                    temp[x] = Double.parseDouble(this.arrayValue[x]);
                }
                setMethod.invoke(this.currentObj,(Object)temp);
            }
        }else{//如果是基本数据类型
            if("string".equalsIgnoreCase(typeName)){
                setMethod.invoke(this.currentObj,this.value);
            }else if("int".equalsIgnoreCase(typeName)||"integer".equalsIgnoreCase(typeName)){
                setMethod.invoke(this.currentObj,Integer.parseInt(this.value));
            }else if("double".equalsIgnoreCase(typeName)){
                setMethod.invoke(this.currentObj,Double.parseDouble(this.value));
            }else if("date".equalsIgnoreCase(typeName)){
                setMethod.invoke(this.currentObj,new SimpleDateFormat("yyyy-MM-dd").parse(this.value));
            }
        }
    }

    /**
     * 取得属性类型
     * @return 属性类型
     */
    public String getFieldType(){
        return this.field.getType().getSimpleName();
    }

}
  1. 新建一个基本类型数据验证工具类。
package com.gub.util;

public class ValidateUtil {
    /**
     * 验证数据是否非空
     * @param data 要验证的数据
     * @return 若数据非空,返回true,否则返回false
     */
    public static boolean validateEmpty(String data){
        return data!=null&&data.length()>0;
    }

    /**
     * 验证数据是否满足正则要求
     * @param data 要验证的数据
     * @param regex 正则表达式
     * @return 若数据满足正则返回true,否则返回false
     */
    public static boolean validateRegex(String data,String regex){
        if(validateEmpty(data)){
            return data.matches(regex);
        }
        return false;
    }

    /**
     * 验证数据是否为整数
     * @param data 要验证的数据
     * @return 若数据为整数返回true,否则返回false
     */
    public static boolean validateInt(String data){
        return validateRegex(data,"\\d+");
    }

    /**
     * 验证数据是否为数字
     * @param data 要验证的数据
     * @return 若数据为数字返回true,否则返回false
     */
    public static boolean validateNum(String data){
        return validateRegex(data,"\\d+(\\.\\d+)?");
    }

    /**
     * 验证数据是否为日期
     * @param data 要验证的数据
     * @return 若数据为日期返回true,否则返回false
     */
    public static boolean validateDate(String data){
        //判断是否满足日期格式
        if(validateRegex(data,"\\d{4}-\\d{1,2}-\\d{1,2}")){
            return true;
        }else{
            //判断是否满足日期时间格式
            return validateRegex(data,"\\d{4}-\\d{1,2}-\\d{1,2} \\d{2}:\\d{2}:\\d{2}");
        }
    }
}
  1. 新建一个数据自动验证类,验证应在数据转型之前进行。
package com.gub.util;

import com.jspsmart.upload.SmartUpload;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

public class ValidateHandle {
    private HttpServletRequest request;
    private String rule;
    private ResourceBundle messagesResource ;
    private SmartUpload smart;
    //保存错误信息
    private Map<String,String> errors = new HashMap<String,String>();

    public ValidateHandle(HttpServletRequest request,
                          String rule, ResourceBundle messagesResource,
                          SmartUpload smart) {
        this.request = request;
        this.rule = rule;
        this.messagesResource = messagesResource;
        this.smart = smart;
    }

    public boolean validate(){
        if(!ValidateUtil.validateEmpty(this.rule)){//没有验证规则,验证直接通过
            return true;
        }
        //判断表单是否已封装
        boolean isMultipart = this.request.getContentType().contains("multipart/form-data");
        String[] result = this.rule.split("\\|");
        for(int x=0;x<result.length;x++){
            String[] temp = result[x].split(":");
            if(!temp[1].contains("[]")){//不是数组对象
                String value = null;//取得传入数据
                if(!isMultipart){//表单未封装
                    value = this.request.getParameter(temp[0]);
                }else{//表单已封装
                    value = this.smart.getRequest().getParameter(temp[0]);
                }
                if("string".equalsIgnoreCase(temp[1])){
                    if(!ValidateUtil.validateEmpty(value)){//空验证未通过
                        this.errors.put(temp[0],this.messagesResource.getString("validate.empty"));
                    }
                }else if("int".equalsIgnoreCase(temp[1])||"integer".equalsIgnoreCase(temp[1])){
                    if(!ValidateUtil.validateEmpty(value)){//空验证未通过
                        this.errors.put(temp[0],this.messagesResource.getString("validate.empty"));
                    }else{
                        if(!ValidateUtil.validateInt(value)){//整数验证未通过
                            this.errors.put(temp[0],this.messagesResource.getString("validate.integer"));
                        }
                    }
                }else if("double".equalsIgnoreCase(temp[1])){
                    if(!ValidateUtil.validateEmpty(value)){//空验证未通过
                        this.errors.put(temp[0],this.messagesResource.getString("validate.empty"));
                    }else{
                        if(!ValidateUtil.validateNum(value)){//数字验证未通过
                            this.errors.put(temp[0],this.messagesResource.getString("validate.number"));
                        }
                    }
                }else if("date".equalsIgnoreCase(temp[1])){
                    if(!ValidateUtil.validateEmpty(value)){//数字验证未通过
                        this.errors.put(temp[0],this.messagesResource.getString("validate.empty"));
                    }else{
                        if(!ValidateUtil.validateDate(value)){//日期验证未通过
                            this.errors.put(temp[0],this.messagesResource.getString("validate.date"));
                        }
                    }
                }
            }else{//表示数组对象
                String[] arrayValue = null;//取得传入数据
                if(!isMultipart){//表单未封装
                    arrayValue = this.request.getParameterValues(temp[0]);
                }else{//表单已封装
                    arrayValue = this.smart.getRequest().getParameterValues(temp[0]);
                }
                if(arrayValue==null){//此时数据不存在
                    this.errors.put(temp[0],this.messagesResource.getString("validate.empty"));
                }else{
                    if("int[]".equalsIgnoreCase(temp[1])||"integer[]".equalsIgnoreCase(temp[1])){
                        for(int y=0;y<arrayValue.length;y++){
                            if(!ValidateUtil.validateInt(arrayValue[y])){
                                this.errors.put(temp[0]+"-"+y,this.messagesResource.getString("validate.integer"));
                            }
                        }
                    }else if("double[]".equalsIgnoreCase(temp[1])){
                        for(int y=0;y<arrayValue.length;y++){
                            if(!ValidateUtil.validateNum(arrayValue[y])){
                                this.errors.put(temp[0]+"-"+y,this.messagesResource.getString("validate.number"));
                            }
                        }
                    }else if("date[]".equalsIgnoreCase(temp[1])){
                        for(int y=0;y<arrayValue.length;y++){
                            if(!ValidateUtil.validateDate(arrayValue[y])){
                                this.errors.put(temp[0]+"-"+y,this.messagesResource.getString("validate.date"));
                            }
                        }
                    }
                }
            }
        }
       return this.errors.size()==0;
    }

    /**
     * 取得所有的错误信息
     * @return 所有的错误信息集合
     */
    public Map<String,String> getErrors(){
        return this.errors;
    }
}
  1. 新建类SmartUtil,对SmartUpload进行封装,以简化使用
package com.gub.util;

import com.jspsmart.upload.SmartUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;

public class SmartUtil {
    private SmartUpload smart;
    private HttpServletRequest request;

    public SmartUtil(SmartUpload smart, HttpServletRequest request) {
        this.smart = smart;
        this.request = request;
    }

    public boolean isUpload(){
        return this.count()>0;
    }

    public int count(){
        return this.smart.getFiles().getCount();
    }

    public SmartUpload getSmart(){
        return this.smart;
    }

    public String createSingleName(){
        String photoName = null;
        if(this.isUpload()){
            if(this.smart.getFiles().getFile(0).getSize()>0){
                photoName = UUID.randomUUID()+"."+this.smart.getFiles().getFile(0).getFileExt();
            }
        }
        return photoName;
    }

    public Map<Integer,String> createMultiNames(){
        Map<Integer,String> names = new HashMap<Integer,String>();
        if(this.isUpload()){
            for(int x=0;x<this.count();x++){
                String photoName = UUID.randomUUID()+"."+this.smart.getFiles().getFile(x).getFileExt();
                names.put(x,photoName);
            }
        }
        return names;
    }

    public void save(Integer index,String path) throws Exception{
        String savePath = this.request.getServletContext().getRealPath(path);
        if(this.smart.getFiles().getFile(index).getSize()>0){
            File file = new File(savePath);
            if(!file.getParentFile().exists()){
                file.mkdirs();
            }
            this.smart.getFiles().getFile(index).saveAs(savePath);
        }
    }

    public void save(String path)throws Exception{
        this.save(0,path);
    }

    public void save(Map<Integer,String> paths)throws Exception{
        Iterator<Map.Entry<Integer,String>> iter = paths.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry<Integer,String> me = iter.next();
            this.save(me.getKey(),me.getValue());
        }
    }

    public void delete(String path){
        String deletePath = this.request.getServletContext().getRealPath(path);
        File file = new File(deletePath);
        if(file.exists()){
            file.delete();
        }
    }

    public void delete(List<String> paths){
        Iterator<String> iter = paths.iterator();
        while(iter.hasNext()){
            this.delete(iter.next());
        }
    }
}
  1. 新建Annotation用以判断是否需要自动进行数据的接收
package com.gub.util.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface AutoAssign {

}
  1. 新建DispatcherServlet类,所有的servlet应该继承DispatcherServlet。
package com.gub.util.servlet;

import com.gub.util.FillParam;
import com.gub.util.ValidateHandle;
import com.jspsmart.upload.SmartUpload;

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.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.ResourceBundle;

public class DispatcherServlet extends HttpServlet {
    private static final String MESSAGES = "Messages";

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    private ResourceBundle messagesResource ;
    private SmartUpload smart;

    private boolean autoAssignFlag = false;//自动赋值功能默认关闭

    @Override
    public void init() throws ServletException {
        this.messagesResource = ResourceBundle.getBundle(MESSAGES);
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.request = request;
        this.response = response;
        try{
            //判断表单是否已封装
            if(this.request.getContentType().contains("multipart/form-data")){
                this.smart = new SmartUpload();
                this.smart.initialize(super.getServletConfig(),this.request,this.response);
                this.smart.upload();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        Annotation[] ans = this.getClass().getAnnotations();//取得所有的Annotation
        for(int x=0;x<ans.length;x++){//循环列出所有的Annotation
            //取得Annotation的名字
            String annotationName = ans[x].annotationType().getSimpleName();
            if("AutoAssign".equals(annotationName)){//表示开启自动赋值功能
                this.autoAssignFlag = true;//开启自动赋值功能
            }
        }
        if (this.autoAssignFlag){//如果开启了自动赋值
            if(this.validate()){//数据验证通过
                this.paramHandle();//赋值
                execute();//执行方法
            }else{
                //跳转到错误显示
                request.getRequestDispatcher(this.getMsg("error.page")).forward(request,response);
            }
        }else{//如果没开启了自动赋值则直接执行方法
            execute();//执行方法
        }
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    /**
     * 根据索引取得保存在Messages.properties里的数据
     * @param key 保存索引
     * @return 保存在Messages.properties里的数据
     */
    protected String getMsg(String key){
        return this.messagesResource.getString(key);
    }

    /**
     * 自动执行方法
     */
    private void execute(){
        String path = "error.page";//跳转路径的索引名
        //取得要执行的方法名称
        String methodName = this.request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/")+1);
        try{
            Method method = this.getClass().getMethod(methodName);//取得要执行的方法
            String typeName = method.getGenericReturnType().getTypeName();// 获取返回值类型
            if("java.lang.String".equals(typeName)){//此时方法的返回值为String
                path = (String)method.invoke(this);//执行方法并取得跳转路径
                //跳转到指定路径
                request.getRequestDispatcher(this.getMsg(path)).forward(request,response);
            }else if("void".equals(typeName)){//此时方法的返回值为void
                method.invoke(this);//只执行方法
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 赋值前进行验证操作
     * @return 验证通过返回true,否则返回false
     */
    private boolean validate(){
        try{
            //取得要验证的方法名称
            String validateMethod = this.request.getRequestURI().substring(this.request.getRequestURI().lastIndexOf("/")+1);
            //取得验证规则属性名称
            String validateFieldName = validateMethod + "ValidateRule";
            //取得验证规则属性
            Field validateField = this.getClass().getDeclaredField(validateFieldName);
            validateField.setAccessible(true);//解除禁止
            String rule = (String)validateField.get(this);//取得验证规则
            ValidateHandle vh = new ValidateHandle(this.request,
                    rule,this.messagesResource,this.smart);
            boolean flag = vh.validate();
            this.request.setAttribute("errors",vh.getErrors());
            return flag;
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 自动赋值
     */
    public void paramHandle(){
        try{
            Enumeration<String> enu = null;
            //判断表单是否已封装
            boolean isMultipart = this.request.getContentType().contains("multipart/form-data");
            if(!isMultipart){//表单未封装
                enu = this.request.getParameterNames();//枚举取得所有参数的名字
            }else{
                enu = this.smart.getRequest().getParameterNames();
            }
            while(enu.hasMoreElements()){//循环输出
                String paramName = enu.nextElement();//取得参数的名字
                if(paramName.contains(".")){//名字中包含.可以赋值
                    //取得参数类型
                    String type = new FillParam(this,paramName).getFieldType();
                    if(!isMultipart){
                        //判断类型是否为数组类型
                        if(!type.contains("[]")){//不是数组类型
                            String value = this.request.getParameter(paramName);//取得参数值
                            new FillParam(this,paramName,value);//为对象赋值
                        }else{//数组类型
                            String[] arrayValue = this.request.getParameterValues(paramName);//取得所有的参数值
                            new FillParam(this,paramName,arrayValue);//为对象赋值
                        }
                    }else{//表单已被封装
                        //判断类型是否为数组类型
                        if(!type.contains("[]")){//不是数组类型
                            String value = this.smart.getRequest().getParameter(paramName);//取得参数值
                            new FillParam(this,paramName,value);//为对象赋值
                        }else{//数组类型
                            String[] arrayValue = this.smart.getRequest().getParameterValues(paramName);//取得所有的参数值
                            new FillParam(this,paramName,arrayValue);//为对象赋值
                        }
                    }
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public SmartUpload getSmart(){
        return this.smart;
    }

    public HttpServletRequest getRequest(){
        return this.request;
    }

    public HttpServletResponse getResponse(){
        return this.response;
    }
}
  1. 此时我们的工具类就都写好了,开始进行测试:新建VO类和一个用于控制的Servlet,并建立表单页面。
package com.gub.vo;

import java.util.Date;

public class Member {
    private Integer id;
    private String name;
    private Double salary;
    private Date credate;

    public Member() {
    }
    //Setter,Getter略
    //toString()略
}
package com.gub.servlet;

import com.gub.util.SmartUtil;
import com.gub.util.annotation.AutoAssign;

import com.gub.util.servlet.AbstractServlet;
import com.gub.vo.Member;

import javax.servlet.annotation.WebServlet;

@AutoAssign
@WebServlet(name="MemberServlet",urlPatterns="/MemberServlet/*")
public class MemberServlet extends DispatcherServlet{
    //定义验证规则
    private String insertValidateRule = "member.id:Integer|member.name:String|" +
            "member.salary:Double|member.credate:Date|ai:int[]";
    private Member member = new Member();
    public Member getMember() {
        return member;
    }
    public void setMember(Member member) {
        this.member = member;
    }

    public String insert(){
        System.out.println("====insert====");
        System.out.println(this.member);
        SmartUtil su = new  SmartUtil(super.getSmart(),super.request);
        try {
            su.delete("/upload/02dca8ae-a8a3-41a5-9824-a203ba9a50c1.png");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "index.page";
    }

    public void update(){
        System.out.println("====update====");
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page pageEncoding="UTF-8" %>
<%
  String basePath = request.getScheme()+"://"+request.getServerName()+":"+
          request.getServerPort()+request.getContextPath();
%>
<html>
  <head>
    <title>Index</title>
  </head>
  <body>
    <form action="<%=basePath%>/MemberServlet/insert" method="post" enctype="multipart/form-data" >
      <label>ID:</label>
      <input type="text" id="member.id" name="member.id" /><br>
      <label>用户名:</label>
      <input type="text" id="member.name" name="member.name" /><br>
      <label>工资:</label>
      <input type="text" id="member.salary" name="member.salary" /><br>
      <label>日期:</label>
      <input type="text" id="member.credate" name="member.credate" /><br>
      <label>兴趣爱好:</label>
      <input type="checkbox"  name="ai" value="0" />踢足球
      <input type="checkbox"  name="ai" value="1" />羽毛球
      <input type="checkbox"  name="ai" value="2" />乒乓球
      <input type="checkbox"  name="ai" value="hehe" />篮球
      <br>
      <label>图片</label>
      <input type="file" name="photo" /><br>
      <input type="submit" value="提交" />
    </form>
  </body>
</html>

运行项目后发现:数据验证和接收正常,文件也能正常的上传。




此时我们会发现,Servlet节约大大量的代码,逻辑更加的清晰了。项目下载

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值