目录
前言
如果使用最基本的servlet进行项目编写,那么每个请求都需要写一个servlet,这样数量过于庞大
所以需要一个通用servlet,通过反射和代理,将请求归类,比如学生请求,就只有一个学生的servlet
servlet里面有很多方法,具体看代码
通用servlet
测试页面
username和passwor是用于测试通用servlet接受参数的情况,并不对数据库进行操作
BaseServlet
BaseServlet的作用就是获取从前台传过来的方法名称,然后利用反射调用对应的方法
1 StudentServlet继承BaseServlet,这样当我们请求 studentServlet?method=login 的时候
会默认调用父类BaseServlet无参的构造方法,BaseServlet也会调用父类HttpServlet的无参构造方法
2 HttpServlet的无参构造方法里默认调用init方法,init里面默认调用service方法,这时候service被重写
所以调用BaseServlet里的service方法
3 最后利用反射调用对应的方法
public class BaseServlet extends HttpServlet
{
// 重写service,因为当请求过来的时候,会自动调用service,所以在这里做文章
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try
{
// 获取method参数的数值
String md = request.getParameter("method");
// 存放要转发的路径,因为执行完方法后可能需要跳转页面
String path = null;
// 获取当前调用对象的字节码对象,也就是子类的对象
Class clazz = this.getClass();
//获取子类对象的Method,md是方法的名称,后面2个是参数类型
Method method=clazz.getMethod(md,HttpServletRequest.class,HttpServletResponse.class);
//如果获取到了
if (null!=method)
{
//调用这个方法,并且传递参数下去,所以我们的方法也需要写上 request,response这2个参数
//this是承载的对象,如果要调用的方法是静态的,那么不需要对象承载
//现在这个this,并不是子类对象,而是父类对象,相当于是父类调用子类的方法,因为是用父类来承载的
//上面的 this.getClass(); 返回的是当前调用对象的字节码对象,为什么这样,需要解析getClass源码
//method.invoke的返回值是Object,也就是我们在studentServlet里的方法可以是任意类型
//而我们强制限制它是String,这里返回的数值也就是我们方法返回的数值
path=(String) method.invoke(this, request,response);
}
//如果path也不为空,注意上面已经用了方法了
if (null!=path)
{
//这里用于转发我们方法返回的地址,由BaseServlet帮我们转发,我们只需要在返回值上写要转发的路径即可
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}
对应的servlet里
public class StudentServlet extends BaseServlet
{
//返回值必须是String
public String login(HttpServletRequest request,HttpServletResponse response)
{
String username=request.getParameter("username");
System.out.println(username);
//这里写你需要去的页面即可,记得一定要加/
return "/index.html";
}
}
通用编码器
只要理解核心部分即可,一个是如果是post请求,直接reques.setChracterEncoding("utf-8")
如果是get请求,把所有的参数都解码转码即可
keySet获取的是参数名,而get(key)获取就是数值的数组
public Map<String,String[]> getParameterMap() {
/**
* 首先判断请求方式
* 若为post request.setchar...(utf-8)
* 若为get 将map中的值遍历编码就可以了
*/
String method = request.getMethod();
if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if("get".equalsIgnoreCase(method)){
Map<String,String[]> map = request.getParameterMap();
if(flag){
for (String key:map.keySet()) {
String[] arr = map.get(key);
//继续遍历数组
for(int i=0;i<arr.length;i++){
//编码
try {
arr[i]=new String(arr[i].getBytes("iso-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
flag=false;
}
//需要遍历map 修改value的每一个数据的编码
return map;
}
return super.getParameterMap();
}