servlet的优化

反射api语法

在这里插入图片描述

UserServlet使用反射优化代码

service方法使用反射优化处理不同的请求

//重写了service方法,就不走doGet或doPost方法了
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //目标:实现一个servlet处理多个请求

    //1.获取请求参数标识符action
    String action = request.getParameter("action");

    //2.action的值不同,处理不同的请求
    /*if("register".equals(action)){

            //处理用户注册请求
            register(request,response);
        }else if("checkUserName".equals(action)){

            //处理异步用户名校验请求
            checkUserName(request,response);
        }else if("sendSms".equals(action)){

            //处理发送异步短信请求
            sendSms(request,response);
        }*/
    try {
        //目标:使用反射优化上面处理请求方法的执行
        //1.获取当前Servlet对象的字节码对象
        Class clazz = this.getClass();
        //2.根据方法名字和参数类型,调用字节码对象获取私有的处理请求方法对象
        Method method = clazz.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
        method.setAccessible(true);
        //3.执行方法
        method.invoke(this,request,response);

    } catch (Exception e) {
        e.printStackTrace();

        throw new RuntimeException(e);
    }
}

小结

反射的应用

根据一个字符串可以获取java的类或方法对象进行操作, 动态操作类或方法使用反射

BaseServlet优化:抽取重用

目标

实现BaseServlet

UserServlet问题分析

 //重写了service方法,就不走doGet或doPost方法了
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //目标:实现一个servlet处理多个请求

        //1.获取请求参数标识符action
        String action = request.getParameter("action");

        //2.action的值不同,处理不同的请求
        try {
            //目标:使用反射优化上面处理请求方法的执行
            //1.获取当前Servlet对象的字节码对象
            Class clazz = this.getClass();
            //2.根据方法名字和参数类型,调用字节码对象获取私有的处理请求方法对象
            Method method = clazz.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            method.setAccessible(true);
            //3.执行方法
            method.invoke(this,request,response);

        } catch (Exception e) {
            e.printStackTrace();

            throw new RuntimeException(e);
        }
    }

上面代码问题分析

以后创建其他Servlet也要实现上面的代码,会导致所有servlet处理请求service方法冗余

解决方案

创建一个父类BaseServlet, 将每个子类Servlet中冗余service方法抽取到父类中, 每个子类Servlet自然就会继承serivce方法,子类不需要写,从而没有了冗余代码

BaseServlet抽取重用代码

在这里插入图片描述

package com.itheima.web.servlet;

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 java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author 黑马程序员
 */
//@WebServlet("/BaseServlet")  这里注释,当前父类servlet不用对外提供访问
public class BaseServlet extends HttpServlet {

    //重写了service方法,就不走doGet或doPost方法了
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //目标:实现一个servlet处理多个请求

        //1.获取请求参数标识符action
        String action = request.getParameter("action");

        //2.action的值不同,处理不同的请求
        try {
            //目标:使用反射优化上面处理请求方法的执行
            //1.获取当前Servlet对象的字节码对象
            Class clazz = this.getClass();
            //2.根据方法名字和参数类型,调用字节码对象获取私有的处理请求方法对象
            Method method = clazz.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            method.setAccessible(true);
            //3.执行方法
            method.invoke(this,request,response);

        } catch (Exception e) {
            e.printStackTrace();

            throw new RuntimeException(e);
        }
    }
}

UserServlet代码(注释的代码)

去掉service、继承BaseServlet

在这里插入图片描述

小结

  • BaseServlet优化使用到的技术?

    反射
    继承
    

BaseServlet优化:抽取ajax返回

目标

将任意一个对象转为json,通过response响应到客户端

  1. 方法参数是响应对象和要转换的对象
  2. 将对象转成JSON字符串
  3. 以JSON格式打印

BaseServlet增加代码

//将指定的对象转换为json字符串输出
protected void toJsonString(HttpServletResponse response,Object object)throws Exception{
    response.setContentType("application/json;charset=utf8");
    String jsonData = new ObjectMapper().writeValueAsString(object);
    response.getWriter().print(jsonData);
}

优化后UserServlet的代码

package com.itheima.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.domain.ResultInfo;
import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.RandomStringUtils;

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

/**
 * @author 黑马程序员
 */
@WebServlet("/UserServlet")
public class UserServlet extends BaseServlet {

    //实例业务类
    private UserService userService = new UserService();
    //实例ObjectMapper
    private ObjectMapper objectMapper = new ObjectMapper();



    /*protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        //目标:实现一个servlet处理多个请求

        //1.获取请求参数标识符action
        String action = request.getParameter("action");

        //2.action的值不同,处理不同的请求
        if("register".equals(action)){

            //处理用户注册请求
            register(request,response);
        }else if("checkUserName".equals(action)){

            //处理异步用户名校验请求
            checkUserName(request,response);
        }else if("sendSms".equals(action)){

            //处理发送异步短信请求
            sendSms(request,response);
        }
    }*/

    //目标:处理异步发送短信请求
    private void sendSms(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.获取手机号
        String telephone = request.getParameter("telephone");

        //2.生成随机验证码6个数字
        String checkCode = RandomStringUtils.randomNumeric(6);

        //3.调用业务发送手机验证码,传递(手机号+验证码);
        ResultInfo resultInfo = userService.sendSms(telephone, checkCode);

        //4.判断发送短信状态
        if(resultInfo.getSuccess()==true) {
            //5.如果短信发送成功,将验证码存储到session中
            request.getSession().setAttribute("SERVER_CODE",checkCode);
        }
        //6.将ResultInfo转换为json返回
        toJsonString(response,resultInfo);
    }

    //目标:处理异步用户名校验请求
    private void checkUserName(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.获取用户名
        String username = request.getParameter("username");

        //2.调用业务校验用户名并获取结果
        ResultInfo resultInfo = userService.checkUserName(username);

        //3.将返回结果ResultInfo对象转换为json字符串返回
        toJsonString(response,resultInfo);
    }

    //处理用户注册的请求
    private void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //目标2:处理用户注册的同步请求
            //增加操作:校验验证码,校验通过后才可以用户注册
            //a.获取用户输入的验证码
            String userCheckCode = request.getParameter("smsCode");
            //b.获取session中生成的验证码
            String sessionCheckCode = (String) request.getSession().getAttribute("SERVER_CODE");
            //c.比较2个验证码,如果值不一样封装返回验证码错误
            if(!userCheckCode.equalsIgnoreCase(sessionCheckCode)){
                request.setAttribute("errorMsg","验证码错误");
                request.getRequestDispatcher("/register.jsp").forward(request,response);
                return;
            }


            //目标1:处理用户注册请求
            //1.获取注册数据封装到User对象中
            //实例User
            User user = new User();
            //获取表单所有数据
            Map<String, String[]> map = request.getParameterMap();
            //使用BeanUtils封装数据
            BeanUtils.populate(user,map);

            //2.调用业务层进行用户注册获取注册结果
            ResultInfo resultInfo = userService.register(user);

            //3.判断注册结果
            if(resultInfo.getSuccess()==true) {
                //3.1 注册成功,跳转到register_ok.jsp页面
                response.sendRedirect(request.getContextPath()+"/register_ok.jsp");
            }else {
                //3.2 注册失败,将错误消息存储到请求域中,跳转register.jsp页面显示错误消息
                request.setAttribute("errorMsg",resultInfo.getMessage());
                request.getRequestDispatcher("/register.jsp").forward(request,response);
            }
        } catch (Exception e) {
            e.printStackTrace();

            throw new RuntimeException(e);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值