目录
- M:model
- V:View
- C:controller
controller
包括了filter,dispatcher,本质是servlet
filter
请求先经过filter,这里用filter实现设置编码。
@WebFilter(urlPatterns = {"*.do"},initParams = {@WebInitParam(name = "encoding",value = "UTF-8")}) public class CharacterEncodingFilter implements Filter { //默认设置编码格式是UTF-8 private String encoding = "UTF-8"; @Override public void init(FilterConfig filterConfig) throws ServletException { //先获取配置的编码格式 String encodingStr = filterConfig.getInitParameter("encoding"); //如果配置的编码格式为空,就使用默认的编码格式 if(StringUtil.isNotEmpty(encodingStr)){ encoding = encodingStr ; } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //使用默认的编码格式 ((HttpServletRequest)servletRequest).setCharacterEncoding(encoding); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
dispatcher
1.拦截*.do结尾的servlet请求。
2.在init方法中获取到beanFactory,beanFactory有获取所有bean(controller,service,DAO)的方法返回一个Map集合。*的内容对应controller的全类名,也就是说获取到*就能获取到处理该请求的对应controller类。
3.截取*的内容,根据*的值从集合中获取controller类
4.获取请求中的operate参数,根据operate的值执行对应controller中的方法。
5.获取请求中的其他参数,给方法中的参数赋值,参数名和参数名相同
6.执行方法,根据方法的返回值判断下面的操作
7.如果是redirect:开头就执行重定向操作,要么就执行渲染操作。
渲染操作是渲染页面,一般是转移到页面时进行的操作。
//执行的操作要和方法名相同 //传入的参数的参数名要和方法的参数名相同 @WebServlet("*.do") public class DispatcherServlet extends ViewBaseServlet { //beanFactory中包含了所有的controller层,service层,DAO层的实现类 private BeanFactory beanFactory; public DispatcherServlet(){ } public void init() throws ServletException { super.init(); ServletContext application = getServletContext(); Object beanFactoryObj = application.getAttribute("beanFactory"); if(beanFactoryObj!=null){ beanFactory = (BeanFactory)beanFactoryObj; }else{ throw new RuntimeException("IOC容器获取失败!"); } } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //拦截所以的servlet请求,并删去后缀,以便找到想要访问的具体controller,比如user.do->user String servletPath = request.getServletPath(); servletPath = servletPath.substring(1); int lastDotIndex = servletPath.lastIndexOf(".do") ; servletPath = servletPath.substring(0,lastDotIndex); //得到想问访问的controller的字符串形式,去找到具体要执行操作的controller的实例 //对应关系已经写到了配置文件中,并将配置文件中的对应关系保存到了map集合中 Object controllerBeanObj = beanFactory.getBean(servletPath); //找到了具体的controller类后,就要考虑执行这个类的什么方法,先获取页面发过来想要进行的操作 //注意操作名和方法名是相同的 String operate = request.getParameter("operate"); //如果请求中没有想要进行的操作,则默认进行index操作即返回主页。 if(StringUtil.isEmpty(operate)){ operate = "index" ; } //获取到方法名之后就要执行这个方法,但是执行方法时要传入参数,所以接下来要获取方法列表中的参数名 try { //先得到这个类的所以方法名 Method[] methods = controllerBeanObj.getClass().getDeclaredMethods(); for(Method method : methods){ //找到想要执行的方法 if(operate.equals(method.getName())){ //获取这个方法中所以参数的方法名 //getParameter方法返回的是方法名的别名 arg0,arg1.... //通过设置来使编译的class文件中带有具体的方法名 //所以设置完后要进行重新编译 Build Parameter[] parameters = method.getParameters(); //获取到参数名后,要给参数赋值 Object[] parameterValues = new Object[parameters.length];