在学习专业课JAVAWeb的时候,听老师讲解有些费劲,于是自己去b站上找了网课自行学习,在学到做最终案例的时候,如下,在写Servlet的对应代码时,面对老师提出的问题以及对现书写的Servlet代码优缺点时,因为一个项目中会有很多对应的实体类 我在编写的为 brand(品牌实体类),web层的Servlet个数太多了,下面还会有 user(用户实体类).....等等很多的实体类,这样一来,不利于管理和编写。所以老师给出的解决方案是 将Servlet进行归类,对同一个实体的操作方法写到一个Servlet中,对于同一个实体类的操作方法写到一个Servlet中。如BrandServlet、UserServlet。
下面给出Servlet优化之后的代码 以及继承思想的体现
如下图 左边是优化前 右边是优化后 明显清爽且方便管理
这里最大的不同之处就是在于 访问的路径发生了变化 之前的是通过注解@WebServlet("访问的servlet路径");
优化之后要做到很多的路径都要访问到Servlet,接收很多的资源访问路径,明显之前的单个的servlet做不到,具体是怎么实现的呢?我们往下看 之前我们写的Servlet写的路径是写死了的
这里后面我们采用通配符的方法
只要路径是以/brand/*的路径 后面都可以映射到写的Brand Servlet中去
如上图 灰色部分是项目访问的路径,后面从"/brand/"后面开始就是开始访问资源了,是可以映射到
"/brand/*"上去的,然后一一访问对应的方法 可以和url parttern 匹配上 所以上述的selectAll方法和add方法 都会访问到 "/brand/*" 中去 那么如何去实现分别调用"selectAll" 和 "add"方法呢?
如上图,将访问路径的名称的最后一段 写成与所调用的方法一致即可 我们现在要做的就是获取最后一段的路径,也就是方法名称。 有了方法名称之后自然就可以执行对应的方法了,我们首先通过获取BrandServlet的字节码文件 获取对应方法的method对象 最后通过Method.invoke();把方法进行调用(这里我们要通过反射区获取对象方法,执行方法)。
继承
上面我们说到,要创建一个BrandServlet 这时我们如果直接去继承HttpServlet,HttpServlet里面干了很重要的一件事 在对应的service里面获取了请求的方式(doGet 或 doPost)
HttpServlet里面做的事就是通过 请求方式完成方法的分发。如果将来我们写的BrandServlet 直接继承HttpServlet 那么就只能用里面的doGet 和 doPost方法 并不能自己在里面写自己所需要的方法 selectAll add.....等方法 这个时候就不能去直接继承HttpServlet(不用其根据请求方式进行方法的分发的功能) 自定义Servlet,使用请求路径进行方法的分发 替换 HttpServlet的根据请求方式进行方法分发。 首先定义一个BaseServlet(名字自定义,将来的BrandServlet继承它),
BaseServlet作用:替换HttpServlet 根据请求的最后一段路径来进行方法的分发(这里之所以会调用父类的方法,其实是因为子类没有重写,web的访问,都会由tomcat自动调用service方法,子类继承了父类的service方法!) 重写HttpServlet 里面的doGet 和 doPost方法 下面为具体的实现代码 看注释
BaseServlet:
package com.yzh.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,数据请求的最后一段来进行方法分发
*
* */
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的路径
String uri = req.getRequestURI(); // /brand-case/brand/selectAll
// System.out.println(uri);
//2.获取最后一段路径 方法名
int index = uri.lastIndexOf('/');
String methodName = uri.substring(index + 1); //
// System.out.println(methodName);
//3.执行方法
//3.1 获取BrandServlet/ UserServlet 字节码对象
//谁调用我(this 所在的方法)
//System.out.println(this);
Class<? extends BaseServlet> cls = this.getClass();
//3.2获取方法 method对象
try {
Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//3.3执行方法
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
BrandServlet:
package com.yzh.web.servlet;
import com.alibaba.fastjson.JSON;
import com.yzh.pojo.Brand;
import com.yzh.service.BrandService;
import com.yzh.service.impl.BrandServiceImpl;
import com.yzh.web.servlet.BaseServlet;
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;
//@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet {
//设置成员变量
private BrandService brandService = new BrandServiceImpl();
public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用service查询
List<Brand> brands = brandService.selectAll();
//2.转为json数据
String jsonString = JSON.toJSONString(brands);
//3.写数据 且输出的为中文
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(jsonString);
}
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//1.提交品牌数据
BufferedReader br = request.getReader();
String params = br.readLine(); //json字符串
//转为Brand对象
Brand brand = JSON.parseObject(params, Brand.class);
//2.调用service 添加
brandService.add(brand);
//3.响应成功的标识
response.getWriter().write("success");
}
}
然后展示页面中 前后端交互中的ajax中的url代码也进行修改
axios({
method:"get",
url:"http://localhost:8080/brand-case/brand/selectAll"
优化后的Servlet代码从代码量上来说和之前差别不大,主要是方便管理和阅读,后期维护起来会更加的方便。