在不使用框架的情况下,如何实现类似spring mvc 的简单效果。
优化servlet,减少Servlet的数量,现在是一个功能一个Servlet,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。
- 封装一个BaseServlet,然后以后自己写的Servlet 就继承BaseServlet
- 在BaseServlet 里面重写service方法
- 在service 方法里利用反射对uri 路径及进行解析,如下
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//System.out.println("baseServlet的service方法被执行了...");
//完成方法分发
//1.获取请求路径
String uri = req.getRequestURI(); // /travel/user/add
System.out.println("请求uri:"+uri);// /travel/user/add
//2.获取方法名称
String methodName = uri.substring(uri.lastIndexOf('/') + 1);
System.out.println("方法名称:"+methodName);
//3.获取方法对象Method
//谁调用我?我代表谁
System.out.println(this);//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
try {
//获取方法
Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射
//method.setAccessible(true);
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 直接将传入的对象序列化为json,并且写回客户端
* @param obj
*/
public void writeValue(Object obj,HttpServletResponse response) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),obj);
}
/**
* 将传入的对象序列化为json,返回
* @param obj
* @return
*/
public String writeValueAsString(Object obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(obj);
}
}
4、举例CategoryServlet 继承BaseServlet,如下:
import cn.itcast.travel.domain.Category;
import cn.itcast.travel.service.CategoryService;
import cn.itcast.travel.service.impl.CategoryServiceImpl;
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.List;
@WebServlet("/category/*")
public class CategoryServlet extends BaseServlet {
private CategoryService service = new CategoryServiceImpl();
/**
* 查询所有
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用service查询所有
List<Category> cs = service.findAll();
//2.序列化json返回
/* ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),cs);*/
writeValue(cs,response);
}
}
注意:此处findAll 以public修饰,不然就要暴力反射了---
这里访问findAll 方法的url 可以这么写,http://localhost:8080/category/findAll,在该Servlet里面可以继续添加其他的业务方法,末尾的路径修改下就行了,如http://localhost:8080/category/findOne