從零寫一個Java WEB框架(七)Controller層轉換器
阿新 • • 發佈:2018-11-21
- 該系列,其實是對《架構探險》這本書的實踐。本人想記錄自己的學習心得所寫下的。
- 從一個簡單的Servlet專案開始起步。對每一層進行優化,然後形成一個輕量級的框架。
- 每一篇,都是針對專案的不足點進行優化的。
- 專案已放上github
本篇
上一篇已經為轉換器準備了幾個bean類,例如:Param,View,Data 類。本篇就真正的開始寫轉換器了。
什麼是轉換器呢?
我的理解就是:繼承HttpServlet類,重寫裡面的init()方法Service 方法。
init()方法是建立Servlet容器的時候,會呼叫該方法進行初始化,我們將用這個方法來載入我們的Helper方法。
Service
程式碼實現
DispatcherServlet 轉換器實現
/*
* 請求轉發器
* */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {
private static Logger log = LoggerFactory.getLogger(DispatcherServlet.class);
/*
* 思路:
* 1. 在初始化Servlet容器的時候,載入相關的Helper類,Jsp路徑,靜態資源路徑.
* 2. 從request獲取到請求方法和路徑
* -》根據請求方法和路徑去Controller容器獲取封裝了類和方法的Handler物件
* -》從Handler物件裡拿到類名,然後從Bean容器裡獲取到該類的例項
* -》從request獲取引數,將所有引數存到Param物件裡面
* -》從Handler物件拿到方法名,通過ReflectionUtil工具類呼叫方法(傳入物件,方法名,引數)
* -》從呼叫方法返回的結果判斷是View型別的就進行View處理,返回JSP頁面,如果是Data型別的就返回JSON資料。
*
* */
@Override
public void init(ServletConfig config) throws ServletException {
//初始化相關的Helper
HelperLoader.init();
//獲取ServletContext 物件
ServletContext servletContext = config.getServletContext();
//註冊JSP路徑
ServletRegistration jsp = servletContext.getServletRegistration("jsp");
jsp.addMapping(ConfigHelper.getAppJspPath() + "*");
//註冊處理靜態資源的預設Servlet
ServletRegistration def = servletContext.getServletRegistration("default");
def.addMapping(ConfigHelper.getAppAssetPath() + "*");
log.info("Init() success");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取到請求方法和路徑
String method = req.getMethod().toLowerCase();
//getPathInfo() 和getRequestURI() 去區別就是
// getPathInfo 是從Servlet配置路徑開始獲取額外路徑的。
// getRequestURI 則是從埠號開始獲取路徑的
String pathInfo = req.getPathInfo();
//獲取Handler物件
Handler handler = ControllerHelper.getHandler(method, pathInfo);
if (handler != null) {
//獲取類
Class<?> controllerClass = handler.getControllerClass();
//獲取例項物件
Object bean = BeanHelper.getBean(controllerClass);
//從request獲取引數
Enumeration<String> parameterNames = req.getParameterNames();
Map<String, Object> paramMap = new HashMap<>();
while (parameterNames.hasMoreElements()) {
String s = parameterNames.nextElement();
String parameter = req.getParameter(s);
paramMap.put(s, parameter);
}
//獲取方法名
Method actionMethod = handler.getActionMethod();
Param param = new Param(paramMap);
log.info("呼叫方法名: "+ actionMethod.getName());
//呼叫方法
Object result = ReflectionUtil.invokeMethod(bean, actionMethod, param);
//判斷是否是View
if (result instanceof View) {
View view = (View) result;
String path = view.getPath();
if (StringUtils.isNotEmpty(path)) {
//如果是/開頭,則是重定向
if (path.startsWith("/")) {
resp.sendRedirect(req.getContextPath() + path);
} else {
//轉發
Map<String, Object> map = view.getModel();
for (Map.Entry<String, Object> m : map.entrySet()) {
req.setAttribute(m.getKey(),m.getValue());
log.info("key "+ m.getKey());
}
req.getRequestDispatcher(ConfigHelper.getAppJspPath()+path).forward(req,resp);
}
} else if (result instanceof Data) {
//返回JSON資料
Data data = (Data) result;
Object model = data.getModel();
if (model != null) {
resp.setContentType("application/json");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
String s = JsonUtil.toJson(model);
writer.write(s);
writer.flush();
writer.close();
}
}
}
}
}
}
CustomerController 層實現
@Controller
public class CustomerController {
@Inject
private CustomerService customerService;
/*
* 進入客戶列表介面
* */
@Action("get:/customer")
public View index(Param param) {
List<Customer> customerList = customerService.getCustomerList();
return new View("customer.jsp").addModel("customerList", customerList);
}
/*
* 顯示客戶基本資訊
* */
@Action("get:/customer_show")
public View show(Param param) {
long id = param.getLong("id");
Customer customer = customerService.getCustomer(id);
return new View("customer_show.jsp").addModel("customer", customer);
}
/*
* 進入建立客戶介面
* */
@Action("get:/customer_create")
public View create(Param param) {
return new View("customer_create.jsp");
}
/*
* 處理建立客戶請求
* */
@Action("post:/customer_create")
public Data createSubmit(Param param) {
Map<String, Object> map = param.getMap();
boolean result = customerService.createCustomer(map);
return new Data(result);
}
/*
* 進入編輯客戶 介面
* */
@Action("get:/customer_edit")
public View edit(Param param) {
long id = param.getLong("id");
Customer customer = customerService.getCustomer(id);
return new View("customer_edit.jsp").addModel("customer", customer);
}
/*
* 處理編輯客戶請求
* */
//TODO
/*
* 處理刪除客戶請求
* */
//TODO
}
效果圖
總結
一個輕量級的框架就這樣完成了。從Controller層到Service層,再到Dao層。我覺得框架的雛形已經是出現了,但是我覺得在這麼輕便的框架,我們可以實現很多想法。
下一篇,就是講框架程式碼和業務程式碼分離開。完成一個真正的框架。