以前我们写web层 servlet的时候格式如下:
需要一个一个写,Servlet个数比较多,以后不利于管理
一、优化前Servlet写法如下:
以添加商品为例
addServlet:
package com.itheima.web.servlet;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import com.itheima.service.impl.BrandServiceImpl;
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.BufferedReader;
import java.io.IOException;
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
// 业务逻辑层类
private BrandService brandService =new BrandServiceImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 通过抓包拿到前端请求过来的数据(演示的是前端的数据为JSON格式)
BufferedReader bufferedReader =request.getReader();
String rl =bufferedReader.readLine(); // 拿到前端请求的JSON数据
// 2. 将JSON数据转换成Java数据 (也就是说将JSON数据转换成Brand对象类型,将数据封装到对象属性中了)
Brand brand =JSON.parseObject(rl,Brand.class);
// 3. 调用BrandService接口中的添加商品方法
brandService.add(brand);
// 4. 响应给前端success的标识信号
response.getWriter().write("success");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
打开服务器:访问该"addServlet"路径,前端的请求就会进入该Servlet层 然后做出相对应的逻辑:
二、优化后的Servlet层代码
总体思路:把增删改查的Servlet 转换成了BrandServlet类当中的方法了 ,然后调用就可以了
BrandServlet:
1、因为该BrandServlet类继承了BaseServlet类,BaseServlet类又继承了HttpServlet并且重写了service()方法,所以就相当于BrandServlet类继承了HttpServlet又重写了service()方法【这就相当于上面的添加商品那一步 addServlet类继承HttpServlet了】
当前端访问路径@WebServlet("/brand/*") 格式的时候,相当于进入到了该BrandServlet类当中了,然后又因为该BrandServlet其实也重写了service()方法,所以服务器路径进来之后,会先调用该service()方法 然后基本上就是映射出该类调用该映射类的增删改查方法而已
注意:其实就是在BrandServlet类下跑程序调用增删改查方法而已,我们可以假想着BaseServlet类当中的service()方法是在BrandServlet类下跑的 (继承原因)
而且我们以后的增删改查商品问题等直接以方法的形式全写在该BrandServlet类当中即可,就不再一个一个创建增删改查的Servlet了,所以就容易管理了
package com.itheima.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* BrandServlet 继承父类BaseServlet
* 父类中继承了HttpServlet 所以相当于BrandServlet继承了HttpServlet
*
* 父类BaseServlet中有service方法 (该方法当客户端访问相对应路径时自动调用该方法中)
* 子类继承了父类 也就是说:这个BrandServlet中实际上也有个service方法 当访问该 @WebServlet("/brand/*")路径时
* 其实调用的是BrandServlet类当中的service()方法
*
*/
@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
/**
* 1、 查询所有商品方法
*/
public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
System.out.println("brand selectAll.....");
}
/**
* 2、 添加商品方法
*/
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
System.out.println("brand add.....");
}
}
BaseServlet:
package com.itheima.web.servlet;
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.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 替换 HttpServlet
*
* 这个 BaseServlet类继承HttpServlet 重写 service方法
*/
public class BaseServlet extends HttpServlet {
// 根据请求的最后一段路径来进行方法分发
@Override // 客户端请求过来会先进入service方法 req域当中封装了客户端请求的数据(和doGet doPost方法一样)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取请求路径
String url =req.getRequestURI();
// System.out.println(url); // 格式: /brand-case/brand/selectAll
// 获取最后一段路径(方法名)
int index =url.lastIndexOf("/"); // 从路径后面数 第一次出现“/”的位置
String methodName =url.substring(index+1); // 获取到从“/”开始截取的后面的路径 (这里我们不要/ 所以+1)
// System.out.println(methodName); // selectAll
// 2. 执行BrandServlet对象中的selectAll方法
// 2.1 获取BrandServlet 字节码对象 Class (映射)
Class<? extends BaseServlet> cls =this.getClass();
// System.out.println(cls); // com.itheima.web.servlet.BrandServlet@24ad61c6
/**
* 特别注意: 这个 this 代表的是谁?
* 因为BrandServlet类继承了BaseServlet,当客户端访问路径到BrandServlet类下时,因为BaseServlet
* 重写了Service方法 所以BrandServlet类当中也有该service方法 (可以看作:BaseServlet类当中的service方法
* 在BrandServlet类当中,当访问该BrandServlet路径下时 会自动调用service()方法, 所以该this表示BrandServlet
* 对象,【也就是说,谁调用这个this所在的方法中,这个this就代表是谁】
*
* 这里的service()方法 其实是BrandServlet对象调用的 所以this表示BrandServlet对象)
*/
// 2.2 获取方法 Method对象(映射)
try {
// 这里直接把methodName传入, 表示该映射类调用methodName方法
// 上面假设拿到客户端发送的selectAll请求,这里我们就表示该映射类BrandServlet调用的是methodName(selectAll方法) )
Method method =cls.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 2.3 调用该方法 (映射)
method.invoke(this,req,resp); // 往映射出来的方法中传客户端请求的数据(传参):把req域和resp域传过去
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
开启服务器访问路径 以(/brand/selectAll为例 【刚好相当于调用BrandServlet的查询所有selectAll的方法】):
因此优化后写商品增删改查逻辑的时候 直接在BrandServlet类当中写成增删改查的方法即可了,不用动BaseServlet类 也不用再一个一个创建增删改查的Servlet了, 增删改查代码如下:
package com.itheima.web.servlet;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import com.itheima.service.impl.BrandServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;
/**
* BrandServlet 继承父类BaseServlet
* 父类中继承了HttpServlet 所以还是相当于BrandServlet继承了HttpServlet
*
* 父类BaseServlet中有service方法 (该方法当客户端访问相对应路径时自动调用该方法中)
* 子类继承了父类 也就是说:这个BrandServlet中实际上也有个service方法 当访问该 @WebServlet("/brand/*")路径时
* 其实调用的是BrandServlet类当中的service()方法
*
*/
@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
private BrandService brandService =new BrandServiceImpl();
/**
* 1、 查询所有商品方法
*
* 这下面逻辑和以前没优化的时候在doGet() doPost()方法当中的逻辑一样
*/
public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// 1. 调用BrandServiceImpl完成查询所有功能
List<Brand> brands =brandService.selectAll();
// 2. 将Java对象数据转换成JSON格式数据,响应给前端
response.setContentType("text/json;charset=utf-8"); // 中文乱码问题
String toString = JSON.toJSONString(brands);
// 3. 响应给前端数据
response.getWriter().write(toString);
}
/**
* 2、 添加商品方法
*/
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// 1. 通过抓包拿到前端请求过来的数据(演示的是前端的数据为JSON格式)
BufferedReader bufferedReader =request.getReader();
String rl =bufferedReader.readLine(); // 拿到前端请求的JSON数据
// 2. 将JSON数据转换成Java数据 (也就是说将JSON数据转换成Brand对象类型,将数据封装到对象属性中了)
Brand brand =JSON.parseObject(rl,Brand.class);
// 3. 调用BrandService接口中的添加商品方法
brandService.add(brand);
// 4. 响应给前端success的标识信号
response.getWriter().write("success");
}
}
开启服务器访问该查询所有商品,调用该查询所有方法时结果如下:
最后把数据用前端页面处理一下即可~
开启服务器访问 brand.html: