标签:数位 形参 equals == spring nta servlet 定义 ret
MVC顶层设计
一、请求调用
public class GPDispatcherServlet extends HttpServlet {
//保存Controller中URL和Method的对应关系
private List handlerMappings = new ArrayList();
private Map handlerAdapters = new HashMap();
private List viewResolvers = new ArrayList();
//IoC容器的访问上下文
private GPApplicationContext applicationContext = null;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//6、根据URL委派给具体的调用方法
try {
doDispatch(req,resp);
} catch (Exception e) {
e.printStackTrace();
// resp.getWriter().write("500 Exception,Detail: " + Arrays.toString(e.getStackTrace()));
Map model = new HashMap();
model.put("detail","500 Exception,Detail: ");
model.put("stackTrace",Arrays.toString(e.getStackTrace()));
try {
processDispatchResult(req,resp,new GPModelAndView("500",model));
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//1、根据URL 拿到对应的Handler
GPHandlerMapping handler = getHandler(req);
if(null == handler){
processDispatchResult(req,resp,new GPModelAndView("404"));
return;
}
//2、根据HandlerMapping拿到HandlerAdapter
GPHandlerAdapter ha = getHandlerAdapter(handler);
//3、根据HandlerAdapter拿到对应的ModelAndView
GPModelAndView mv = ha.handle(req,resp,handler);
//4、根据ViewResolver找到对应View对象
//通过View对象渲染页面,并返回
processDispatchResult(req,resp,mv);
}
private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, GPModelAndView mv) throws Exception {
if(null == mv){return;}
if(this.viewResolvers.isEmpty()){return;}
for (GPViewResolver viewResolver : this.viewResolvers) {
GPView view = viewResolver.resolveViewName(mv.getViewName());
view.render(mv.getModel(),req,resp);
return;
}
}
private GPHandlerAdapter getHandlerAdapter(GPHandlerMapping handler) {
if(this.handlerAdapters.isEmpty()){ return null;}
GPHandlerAdapter ha = this.handlerAdapters.get(handler);
return ha;
}
private GPHandlerMapping getHandler(HttpServletRequest req) {
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replaceAll(contextPath,"").replaceAll("/+","/");
for (GPHandlerMapping handlerMapping : this.handlerMappings) {
Matcher matcher = handlerMapping.getPattern().matcher(url);
if(!matcher.matches()){ continue;}
return handlerMapping;
}
return null;
}
@Override
public void init(ServletConfig config) throws ServletException {
applicationContext = new GPApplicationContext(config.getInitParameter("contextConfigLocation"));
//========== MVC ==========
initStrategies(applicationContext);
System.out.println("GP Spring framework is init.");
}
//初始化策略
protected void initStrategies(GPApplicationContext context) {
//handlerMapping
initHandlerMappings(context);
//初始化参数适配器
initHandlerAdapters(context);
//初始化视图转换器
initViewResolvers(context);
}
private void initViewResolvers(GPApplicationContext context) {
String templateRoot = context.getConfig().getProperty("templateRoot");
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
File templateRootDir = new File(templateRootPath);
for (File file : templateRootDir.listFiles()) {
this.viewResolvers.add(new GPViewResolver(templateRoot));
}
}
private void initHandlerAdapters(GPApplicationContext context) {
for (GPHandlerMapping handlerMapping : handlerMappings) {
this.handlerAdapters.put(handlerMapping,new GPHandlerAdapter());
}
}
private void initHandlerMappings(GPApplicationContext context) {
if(this.applicationContext.getBeanDefinitionCount() == 0 ){ return; }
for (String beanName : this.applicationContext.getBeanDefinitionNames()) {
Object instance = applicationContext.getBean(beanName);
Class> clazz = instance.getClass();
if(!clazz.isAnnotationPresent(GPController.class)){ continue; }
String baseUrl = "";
if(clazz.isAnnotationPresent(GPRequestMapping.class)){
GPRequestMapping requestMapping = clazz.getAnnotation(GPRequestMapping.class);
baseUrl = requestMapping.value();
}
//只迭代public方法
for (Method method : clazz.getMethods()) {
if(!method.isAnnotationPresent(GPRequestMapping.class)){ continue; }
GPRequestMapping requestMapping = method.getAnnotation(GPRequestMapping.class);
// //demo//query
String regex = ("/" + baseUrl + "/" + requestMapping.value())
.replaceAll("\\*",".*")
.replaceAll("/+","/");
Pattern pattern = Pattern.compile(regex);
handlerMappings.add(new GPHandlerMapping(pattern,instance,method));
System.out.println("Mapped : " + regex + " --> " + method);
}
}
}
}
二、请求映射
public class GPHandlerMapping {
private Object controller; //保存方法应对的实例
protected Method method; //保存映射的方法
protected Pattern pattern; //URL 的正则匹配
public GPHandlerMapping(Pattern pattern,Object controller,Method method) {
this.controller = controller;
this.method = method;
this.pattern = pattern;
}
public Method getMethod() {
return method;
}
public Pattern getPattern() {
return pattern;
}
public Object getController() {
return controller;
}
}
三、请求方法适配器
public class GPHandlerAdapter {
public GPModelAndView handle(HttpServletRequest req, HttpServletResponse resp, GPHandlerMapping handler) throws Exception {
Method method = handler.getMethod();
//1、先把形参的位置和参数名字建立映射关系,并且缓存下来
Map paramIndexMapping = new HashMap();
Annotation[][] pa = method.getParameterAnnotations();
for (int i = 0; i [] paramTypes = method.getParameterTypes();
for (int i = 0; i type = paramTypes[i];
if(type == HttpServletRequest.class || type == HttpServletResponse.class){
paramIndexMapping.put(type.getName(),i);
}
}
//2、根据参数位置匹配参数名字,从url中取到参数名字对应的值
Object[] paramValues = new Object[paramTypes.length];
//http://localhost/demo/query?name=Tom&name=Tomcat&name=Mic
Map params = req.getParameterMap();
for (Map.Entry param : params.entrySet()) {
String value = Arrays.toString(param.getValue())
.replaceAll("\\[|\\]","")
.replaceAll("\\s","");
if(!paramIndexMapping.containsKey(param.getKey())){continue;}
int index = paramIndexMapping.get(param.getKey());
//涉及到类型强制转换
paramValues[index] = caseStringValue(value,paramTypes[index]);
}
if(paramIndexMapping.containsKey(HttpServletRequest.class.getName())){
int index = paramIndexMapping.get(HttpServletRequest.class.getName());
paramValues[index] = req;
}
if(paramIndexMapping.containsKey(HttpServletResponse.class.getName())){
int index = paramIndexMapping.get(HttpServletResponse.class.getName());
paramValues[index] = resp;
}
Object result = method.invoke(handler.getController(),paramValues);
if(result == null || result instanceof Void){ return null;}
boolean isModelAndView = handler.getMethod().getReturnType() == GPModelAndView.class;
if(isModelAndView){
return (GPModelAndView) result;
}
return null;
}
private Object caseStringValue(String value, Class> paramType) {
if(String.class == paramType){
return value;
}
if(Integer.class == paramType){
return Integer.valueOf(value);
}else if(Double.class == paramType){
return Double.valueOf(value);
}else {
if(value != null){
return value;
}
return null;
}
}
}
四、页面数据封装
public class GPModelAndView {
private String viewName;
private Map model;
public GPModelAndView(String viewName) {
this.viewName = viewName;
}
public GPModelAndView(String viewName, Map model) {
this.viewName = viewName;
this.model = model;
}
public String getViewName() {
return viewName;
}
public Map getModel() {
return model;
}
}
五、试图解析器
public class GPViewResolver {
//.vm .ftl .jsp .gp .tom
private final String DEFAULT_TEMPLATE_SUFFIX = ".html";
private File templateRootDir;
public GPViewResolver(String templateRoot) {
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
templateRootDir = new File(templateRootPath);
}
public GPView resolveViewName(String viewName) {
if(null == viewName || "".equals(viewName.trim())){return null;}
viewName = viewName.endsWith(DEFAULT_TEMPLATE_SUFFIX) ? viewName : (viewName + DEFAULT_TEMPLATE_SUFFIX);
File templateFile = new File((templateRootDir.getPath() + "/" + viewName)
.replaceAll("/+","/"));
return new GPView(templateFile);
}
}
六、自定义引擎模板
public class GPView {
private File viewFile;
public GPView(File templateFile) {
this.viewFile = templateFile;
}
public void render(Map model, HttpServletRequest req, HttpServletResponse resp) throws Exception {
//无反射,不框架
//无正则,不架构
StringBuffer sb = new StringBuffer();
RandomAccessFile ra = new RandomAccessFile(this.viewFile,"r");
String line = null;
while (null != (line = ra.readLine())){
line = new String(line.getBytes("iso-8859-1"),"utf-8");
Pattern pattern = Pattern.compile("¥\\{[^\\}]+\\}",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()){
// ¥{teacher}
String paramName = matcher.group();
paramName = paramName.replaceAll("¥\\{|\\}","");
Object paramValue = model.get(paramName);
if(null == paramValue){continue;}
line = matcher.replaceFirst(makeStringForRegExp(paramValue.toString()));
matcher = pattern.matcher(line);
}
sb.append(line);
}
resp.setCharacterEncoding("utf-8");
resp.getWriter().write(sb.toString());
}
//处理特殊字符
public static String makeStringForRegExp(String str) {
return str.replace("\\", "\\\\").replace("*", "\\*")
.replace("+", "\\+").replace("|", "\\|")
.replace("{", "\\{").replace("}", "\\}")
.replace("(", "\\(").replace(")", "\\)")
.replace("^", "\\^").replace("$", "\\$")
.replace("[", "\\[").replace("]", "\\]")
.replace("?", "\\?").replace(",", "\\,")
.replace(".", "\\.").replace("&", "\\&");
}
}
21. 用30个类手写V2.0版本之MVC实现
标签:数位 形参 equals == spring nta servlet 定义 ret
原文地址:https://www.cnblogs.com/JustDoIt-1221/p/14682640.html