javaweb servlet实现简单的mvc分发请求
来源:互联网 发布:画流程图的软件 编辑:程序博客网 时间:2024/05/22 01:40
自定义servlet请求分发,模拟mvc,视图采用freemarker2.3.27
1).创建注解
标记控制器注解Controller
仅仅起到标记的作用,没有什么具体的作用^_^
package com.fkt.core.annotation;import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 标记控制器 * @author xuzhen * */@Target(TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Controller {}
标记映射注解RequestMapping
value就是用来存储请求Url,用来分发请求用的
package com.fkt.core.annotation;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 标记url * @author xuzhen * */@Target({ TYPE, METHOD })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface RequestMapping { /** * 路径映射值 * @return */ String value() default "";}
2).定义实体类
存储视图和数据的实体类ModelAndView
package com.fkt.core.entity;import java.util.HashMap;import java.util.Map;/** * 包含视图和数据的实体类,主要用于freemarker渲染使用 * @author xuzhen * */@SuppressWarnings({"rawtypes","unchecked"})public class ModelAndView { //视图名称 private String viewName = null; //模板根容器 private Map root = null; public ModelAndView() { root = new HashMap(); } public ModelAndView(String viewName) { this(); this.viewName=viewName; } public String getViewName() { return viewName; } public void setViewName(String viewName) { this.viewName = viewName; } public Map getRoot() { return root; } /** * 增加数据 * @param key * @param value */ public void addObject(Object key,Object value) { root.put(key, value); }}
路径映射具体信息的实体类URIInfo
Method是反射包里的一个类,代表类的方法,有点类似c++的方法指针,想具体了解的话,就去看看java的反射吧^_^!
package com.fkt.core.entity;import java.lang.reflect.Method;/** * uri的实体类,包含uri对应的控制器和控制器方法 * @author xuzhen * */public class URIInfo { //控制器键 private String controllerId; //控制器方法 private Method uriMethod; public URIInfo() {} public URIInfo(String controllerId,Method uriMethod) { this.controllerId=controllerId; this.uriMethod=uriMethod; } public String getControllerId() { return controllerId; } public void setControllerId(String controllerId) { this.controllerId = controllerId; } public Method getUriMethod() { return uriMethod; } public void setUriMethod(Method uriMethod) { this.uriMethod = uriMethod; }}
3). 编写反射工具类
根据注解把控制器添加到容器,根据注解存储映射的具体信息(映射路径,控制器方法)
package com.fkt.core.tool;import java.io.File;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.net.URISyntaxException;import java.util.HashMap;import java.util.Map;import java.util.UUID;import com.fkt.core.annotation.Controller;import com.fkt.core.annotation.RequestMapping;import com.fkt.core.entity.URIInfo;/** * 反射相关工具类 * @author xuzhen * */public abstract class ReflexUtils { /** * 根据包名反射解析所有的控制器 * @param packageName * @return * @throws URISyntaxException * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static Map<String,Object> analysisController(String packageName) throws URISyntaxException, ClassNotFoundException, InstantiationException, IllegalAccessException{ Map<String,Object> controllersMap = new HashMap<String,Object>(); ClassLoader classLoader = ReflexUtils.class.getClassLoader(); String packageDirectory = packageName.replace(".", "/"); File directory = new File(classLoader.getResource(packageDirectory).toURI()); for(File file : directory.listFiles()) { String fName = file.getName(); if(!fName.endsWith(".class")) { continue; } fName = fName.substring(0, fName.length() - 6); String className = packageName+"."+fName; Class cl = classLoader.loadClass(className); //检查解析包中的类是否带有Controller注解,没有注解不往容器中添加实例 Annotation controllerAnnotation = cl.getAnnotation(Controller.class); if(controllerAnnotation!=null) { controllersMap.put(UUID.randomUUID().toString(), cl.newInstance()); } } return controllersMap; } /** * 解析控制器上和方法上的RequestMapping注解,并存储对应的方法到容器 * @param controllersMap * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Map<String,URIInfo> analysisURIByController(Map<String,Object> controllersMap){ Map<String,URIInfo> uriInfosMap = new HashMap<String,URIInfo>(); for(String controllerId : controllersMap.keySet()) { Object controller = controllersMap.get(controllerId); Class controllerClass = controller.getClass(); String uriPrefix = ""; //解析类controller上的ReqestMapping注解 Annotation cRequestMappingAnnotation = controllerClass.getAnnotation(RequestMapping.class); if(cRequestMappingAnnotation!=null) { RequestMapping requestMapping = (RequestMapping)cRequestMappingAnnotation; uriPrefix = requestMapping.value(); } Method[] controllerMethods = controllerClass.getMethods(); for(Method controllerMethod : controllerMethods) { Annotation mRequestMappingAnnotation = controllerMethod.getAnnotation(RequestMapping.class); if(mRequestMappingAnnotation!=null) { RequestMapping requestMapping = (RequestMapping)mRequestMappingAnnotation; String uri = uriPrefix+requestMapping.value(); URIInfo uriInfo = new URIInfo(controllerId, controllerMethod); uriInfosMap.put(uri, uriInfo); } } } return uriInfosMap; }}
4). 定义视图解析器,解析freemarker页面
package com.fkt.core.resolver;import java.io.File;import java.io.IOException;import java.io.Writer;import java.net.URI;import javax.servlet.http.HttpServletResponse;import com.fkt.core.entity.ModelAndView;import freemarker.core.ParseException;import freemarker.template.Configuration;import freemarker.template.MalformedTemplateNameException;import freemarker.template.Template;import freemarker.template.TemplateException;import freemarker.template.TemplateExceptionHandler;import freemarker.template.TemplateNotFoundException;/** * 简单的freemarker模板处理引擎 * @author xuzhen * */public class FreemarkerViewResolver { private Configuration cfg = null; private String defaultEncoding = "UTF-8"; public FreemarkerViewResolver() { } public FreemarkerViewResolver(String defaultEncoding) { this.defaultEncoding=defaultEncoding; } /** * 初始化freemarker引擎 * @param directory * @throws IOException */ public void init(URI viewDirectory) throws IOException { cfg = new Configuration(Configuration.VERSION_2_3_27); cfg.setDefaultEncoding(defaultEncoding); cfg.setDirectoryForTemplateLoading(new File(viewDirectory)); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); cfg.setLogTemplateExceptions(false); cfg.setWrapUncheckedExceptions(true); } //视图解析方法 public void resolver(ModelAndView mav,HttpServletResponse response) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException { Template template = cfg.getTemplate(mav.getViewName()); Writer out = response.getWriter(); template.process(mav.getRoot(), out); out.flush(); }}
5). 定义请求分发servlet
package com.fkt.core;import java.io.IOException;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.fkt.core.entity.ModelAndView;import com.fkt.core.entity.URIInfo;import com.fkt.core.resolver.FreemarkerViewResolver;import com.fkt.core.tool.ReflexUtils;/** * freemarker测试核心分发控制器 * @author xuzhen * */public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1762792866529445537L; //定义存储所有的控制器的容器 private Map<String,Object> controllersMap = null; //定义存储uri信息容器 private Map<String,URIInfo> uriInfosMap = null; //创建模板引擎 private FreemarkerViewResolver viewResolver = null; //编码默认使用utf-8 private String defaultCharacterEncoding = "UTF-8"; @Override public void init() throws ServletException { defaultCharacterEncoding = getInitParameter("characterEncoding"); String mvcPackage = getInitParameter("mvcPackage"); String viewDirectory = getInitParameter("viewDirectory"); try { controllersMap = ReflexUtils.analysisController(mvcPackage); uriInfosMap = ReflexUtils.analysisURIByController(controllersMap); viewResolver = new FreemarkerViewResolver(defaultCharacterEncoding); viewResolver.init(getServletContext().getResource(viewDirectory).toURI()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(defaultCharacterEncoding); resp.setCharacterEncoding(defaultCharacterEncoding); String uri = req.getRequestURI().replace(req.getServletContext().getContextPath(), ""); URIInfo uriInfo = uriInfosMap.get(uri); try { Object mavObject = uriInfo.getUriMethod().invoke(controllersMap.get(uriInfo.getControllerId()), req,resp); if(mavObject!=null) { viewResolver.resolver((ModelAndView) mavObject, resp); return; } } catch (Exception e) { //处理最外层捕捉错误,并抛到前台 e.printStackTrace(resp.getWriter()); return; } //没有正确的处理时的输出 resp.getWriter().println("^_^ error!"); resp.getWriter().flush(); } @Override public void destroy() { }}
6). 使用
web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>freemarker-test</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>com.fkt.core.DispatcherServlet</servlet-class> <!-- 要扫描的控制器包 --> <init-param> <param-name>mvcPackage</param-name> <param-value>com.fkt.web.controller</param-value> </init-param> <!-- 视图所在路径 --> <init-param> <param-name>viewDirectory</param-name> <param-value>/WEB-INF/views</param-value> </init-param> <!-- 制定编码 --> <init-param> <param-name>characterEncoding</param-name> <param-value>UTF-8</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping></web-app>
TestController
package com.fkt.web.controller;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.fkt.core.annotation.Controller;import com.fkt.core.annotation.RequestMapping;import com.fkt.core.entity.ModelAndView;@Controllerpublic class TestController { @RequestMapping("/") public ModelAndView index(HttpServletRequest request,HttpServletResponse response) throws IOException { ModelAndView mav = new ModelAndView("index.ftl"); mav.addObject("name", "欢迎进入首页!"); return mav; }}
index.ftl
<!DOCTYPE HTML><html> <head> <title>首页</title> <meta charset="utf-8"/> </head> <body> <h1>${name!""}</h1> </body></html>
代码下载
下载
阅读全文
0 0
- javaweb servlet实现简单的mvc分发请求
- SpringMVC请求分发的简单实现
- SpringMVC请求分发的简单实现
- SpringMVC请求分发的简单实现
- 简单的servlet mvc实现
- JavaWeb开发--Spring开源框架MVC模式的C(分发Servlet)
- 简单的请求分发功能
- 【Servlet】最简单的Servlet JavaWeb程序
- JavaWeb---Servlet的请求和响应
- 抛弃框架:基于MVC模式的CRUD和Servlet(最简单的JavaWeb程序)
- servlet请求分发到不同的servlet方法中
- 《JavaWeb---Servlet的简单例子》---响应浏览器的请求,向浏览器输出数据
- Intellijidea建javaWeb以及Servlet简单实现
- Intellijidea建javaWeb以及Servlet简单实现
- Intellijidea建javaWeb以及Servlet简单实现
- Intellijidea建javaWeb以及Servlet简单实现
- Intellijidea建javaWeb以及Servlet简单实现
- Intellijidea建javaWeb以及Servlet简单实现
- Nginx SSL 结合Tomcat 重定向URL变成HTTP的问题
- 希狄微HL7016芯片简介
- 全国城市三级联动
- BigDecimal 与其他类型转换
- JavaMail带附件时出错
- javaweb servlet实现简单的mvc分发请求
- Spark机器学习
- 如何提取pdf中的文字并将其转换为TXT文档
- 第十四周项目1-验证算法
- 还在用头条?放弃那三俗的软件,来看看这款小程序吧
- CSS样式加载方式
- 数据结构实验之图论十一:AOE网上的关键路径
- 史上最全的maven pom.xml文件教程详解
- Oracle 启动监听命令