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
//重写了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方法,子类不需要写,从而没有了冗余代码
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);
}
}
}
去掉service、继承BaseServlet
BaseServlet优化使用到的技术?
反射
继承
将任意一个对象转为json,通过response响应到客户端
//将指定的对象转换为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);
}
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);
}
}
}