数据人与超自然意识 发表于 2024-5-18 05:49:46

SpringMVC学习总结 + 【手写SpringMVC底层机制焦点】

SpringMVC笔记

SpringMVC介绍

基本介绍


[*]SpringMVC 是WEB 层框架, 接受了Web 层组件, 支持MVC 的开发模式/开发架构
[*]SpringMVC 通过注解,让POJO 成为控制器,不需要继承类或者实现接口
[*]SpringMVC 接纳低耦合的组件设计方式,具有更好扩展和灵活性.
[*]支持REST 格式的URL 请求.
Spring MVC和Spring之间的关系


[*]Spring MVC 只是Spring 处置处罚WEB 层请求的一个模块/组件, Spring MVC 的基石是Servlet【Java WEB】
[*]Spring Boot 是为了简化开发者的使用, 推出的封神框架(约定优于配置,简化了Spring的配置流程), SpringBoot 包罗许多组件/框架,Spring 就是最焦点的内容之一,也包罗SpringMVC
[*]Spring Boot > Spring > Spring MVC
@RequestMapping

基本介绍

@RequestMapping 注解可以指定控制器/处置处罚器的某个方法的请求的url
@RequestMapping(value = "/buy")
    public String buy(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("购买商品");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }其它使用方式


[*]@RequestMapping 可以修饰方法和类

[*]@RequestMapping 注解可以修饰方法,还可以修饰类当同时修饰类和方法时,
请求的url 就是组合/类请求值/方法请求值
@RequestMapping(value = "/user" )@Controller public class UserHandler {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>@RequestMapping(value = "/buy")
    public String buy(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("购买商品");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }}此时url = /user/buy

[*]@RequestMapping 可以指定请求方式

[*]@RequestMapping 还可以指定请求的方式(post/get/put/delete..), 请求的方式需
要和指定的一样,否则报错

@RequestMapping(value = "/find", method = RequestMethod.GET)
    public String search(String bookId) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("查询书籍bookId= " + bookId);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }

[*]SpringMVC 控制器默认支持GET 和POST 两种方式, 也就是你不指定method , 可以接收
GET 和POST 请求
@RequestMapping(value = "/buy")//默认支持GET 和POST 两种方式
    public String buy(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("购买商品");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }3.@RequestMapping 可指定params 和headers 支持简单表达式

[*]param1: 表示请求必须包罗名为param1 的请求参数
[*]!=param1: 表示请求不能包罗名为param1 的请求参数
[*]param1 != value1: 表示请求包罗名为param1 的请求参数,但其值不能为value1
[*]{"param1=value1", "param2"}: 请求必须包罗名为param1 和param2 的两个请求参数,
且param1 参数的值必须为value1
@RequestMapping(value = "/find", params = "bookId", method = RequestMethod.GET)
public String search(String bookId) {
System.out.println("查询书籍bookId= " + bookId);
return "success";
}4.@RequestMapping 支持Ant 风格资源地址

[*]?:匹配文件名中的一个字符
[*]*:匹配文件名中的恣意字符
[*]**:匹配多层路径

[*]Ant 风格的url 地址举例
/user/*/createUser: <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>匹配/user/aaa/createUser、/user/bbb/createUser 等URL
/user/**/createUser: <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>匹配/user/createUser、/user/aaa/bbb/createUser 等URL
/user/createUser??: <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>   匹配/user/createUseraa、/user/createUserbb 等URL

5.@RequestMapping 可配合@PathVariable 映射URL 绑定的占位符

[*]不需要在url 地址上带参数名了,更加的简洁明了
// 我们希望目标方法获取到username 和userid, value="/xx/{username}" -@PathVariable("username")
    @RequestMapping(value = "/reg/{username}/{userId}")
    public String register(@PathVariable("username") String username,

    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>    @PathVariable("userId") String userId){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("接收到参数--" + "username= " + username + "--" + "usreid= " + userId);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }<a target="_blank" href="https://www.cnblogs.com/user/reg/kristina/300">占位符的演示</a>6.请求的简写情势
​<bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>@GetMapping @PostMapping @PutMapping @DeleteMapping
Rest请求风格

基本介绍


[*]REST:即Representational State Transfer。(资源)表现层状态转化。是现在流行的请求方式。它结构清楚, 许多网站接纳。
[*]HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:
[*]GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
传统的请求方法

在url中:
getBook?id=1 GET
delete?id=1 GET
update POST
add POST
分析: 传统的url 是通过参数来分析crud 的类型,rest 是通过get/post/put/delete 来分析crud 的类型
REST 的焦点过滤器


[*]当前的浏览器只支持post/get 请求,因此为了得到put/delete 的请求方式需要使用Spring
提供的HiddenHttpMethodFilter 过滤器进行转换.
[*]HiddenHttpMethodFilter:浏览器form 表单只支持GET 与POST 请求,而DELETE、PUT
等method 并不支持,Spring 添加了一个过滤器,可以将这些请求转换为标准的http 方
法,使得支持GET、POST、PUT 与DELETE 请求
[*]HiddenHttpMethodFilter 能对post 请求方式进行转换
[*]过滤器需要在web.xml 中配置
配置过滤器

<filter>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>当我们需要 用delete/put 的方式时,
name="_method" 名字需要写成_method 因为背景的HiddenHttpMethodFilter
就是按这个名字来获取hidden 域的值,从而进行请求转换的.
public String delBook(@PathVariable("id") String id) {
System.out.println("删除书籍id= " + id);
//return "success"; [如果这样返回会报错JSPs only permit GET POST orHEAD]
return "redirect:/user/success"; //重定向到一个没有指定method 的Handler 方法
}注意事项


[*]HiddenHttpMethodFilter, 在将post 转成delete / put 请求时,是按_method 参数名来读取的
[*]如果web 项目是运行在Tomcat 8 及以上,会发现被过滤成DELETE 和PUT 请求,到达控制器时能顺利实行,但是返回时(forward)会报HTTP 405 的错误提示:消息JSP 只允许GET、POST 或HEAD。
[*]因此,将请求转发(forward)改为请求重定向(redirect):重定向到一个Handler,由Handler 转发到页面
SpringMVC映射请求数据

获取参数值

/**
* @RequestParam(value="name", required=false)
* 1.@RequestParam : 表示说明一个接受到的参数
* 2.value="name" : 接收的参数名是name
* 3.required=false : 表示该参数可以有,也可以没有,如果required=true,表示必须传递该参数.
* 默认是required=true
*/
@RequestMapping("vote01")
    public String test01(@RequestParam(value = "name",required = false) String username){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("得到的username= "+username);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }
[*]@RequestParam 表示会接收提交的参数
[*]value = "name" 表示提交的参数名是name
[*]required = false 表示该参数可以没有,默认是true 表示必须有这个参数
[*]当我们使用@RequestParam(value = "name",required = false) 就表示 请求的参数名和目的方法的形参名 可以不一致
获取Http请求消息头

@RequestMapping(value = "/vote02")
    public String test02(@RequestHeader(value = "Accept-Encoding")String ae,

    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>@RequestHeader(value = "Host")String host) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("Accept-Encoding =" + ae);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("Host =" + host);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//返回到一个结果
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }获取javabean 情势的数据

@RequestMapping(value = "/vote03")
    public String test03(Master master) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("主人信息= " + master);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//返回结果
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }
[*]方法的形参 (Master master) 用对应的对象类型指定即可,SpringMVC会自动的进行封装
[*]如果自动的完成封装,要求提交的数据参数名和对象的字段名保持一致
[*]支持级联数据获取: 如果对象的属性任然是一个对象,就通过    字段名.字段名 来提交
比如Master<bean >
        <property name="order" value="99"></property>
</bean>,可以通过<bean >
        <property name="order" value="99"></property>
</bean> pet.id ,pet.name<bean >
        <property name="order" value="99"></property>
</bean>来指定
[*]如果参数名和字段名不匹配,则对象的属性就是null
ServletAPI


[*]开发中原生的ServletAPI仍然可以使用
@RequestMapping(value = "/vote04")
    public String test04(HttpServletRequest request,HttpServletResponse response) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String username = request.getParameter("username");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String password = request.getParameter("password");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("username= "+username+" ,password= "+password);
<bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>//返回结果
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }

[*]除了HttpServletRequest, HttpServletResponse 还可以其它对象也可以这样的情势获取

[*]HttpSession、java.security.Principal,InputStream,OutputStream,Reader,Writer

模型数据

数据放入Request域

通过HttpServletRequest放入Request域


[*]通过HttpServletRequest放入Request域是默认机制
@RequestMapping(value = "/vote05")
    public String test05(Master master) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "vote_ok";
    }
[*]当我们提交的数据和对象名保持一致,那么SpringMVC回自动封装成一个对象【在前面 获取javabean 情势的数据 讲过】
[*]SpringMVC还会有一个机制,会自动将封装的这个对象【model模型】放入Request域
[*]也可以手动将对象放入Request域
[*]会以 k-v 的情势放入Request域,k 是类名首字母小写,v 是对象


[*]如果我们需要向Request域中添加新的属性/对象
request.setAttribute("address","beijing");
[*]如果我们要修改默认机制自动放入的对象的属性
master.setName("pp");通过请求的方法参数Map放入Request域

@RequestMapping(value = "/vote06")
    public String test06(Master master, Map<String,Object> map) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>map.put("address","tianjing");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>map.put("master",null);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//返回到一个结果
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "vote_ok";
    }

[*]SpringMVC会遍历Map,然会将map中的 k-v 存放到Request域
[*]如果 map.put("master",null); 会覆盖默认机制的master,为null
通过返回ModelAndView对象实现Request域数据

@RequestMapping(value = "/vote07")
    public ModelAndView test07(Master master) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ModelAndView modelAndView = new ModelAndView();
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>modelAndView.addObject("address","shanghai");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>modelAndView.addObject("master",null);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//指定跳转的视图名称
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>modelAndView.setViewName("vote_ok");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return modelAndView;
    }

[*]SpringMVC会遍历ModelAndView,然会将ModelAndView中的 k-v 存放到Request域
[*]如果 modelAndView.addObject("master",null); 会覆盖默认机制的master,为null
注意事项:

[*]从本质上看,请求响应的方法 return "xx",是返回了一个字符串,其实本质是返回一个ModelAndView对象,只是默认被封装起来了
[*]ModelAndView对象既可以包罗model数据,也可以包罗视图信息
[*]ModelAndView对象的addObject("","");方法 可以添加key -value数据,默认在Request域中
[*]ModelAndView对象setView方法是指定 视图名称
数据放入Session域

@RequestMapping(value = "/vote08")
    public String test08(Master master,HttpSession session){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>session.setAttribute("master",master);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>session.setAttribute("address","guangzhou");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "vote_ok";
    }@ModelAttribute

@ModelAttribute
    public void prepareModel(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("prepareModel()-----完成准备工作-----");
    }
[*]在某个方法上加上 @ModelAttribute 注解,那么在调用该Handler的任何方法都会调用这个方法
[*]类似Aop的前置关照
视图和视图解析器

基本介绍


[*]在springMVC 中的目的方法最终返回都是一个视图(有各种视图).
[*]返回的视图都会由一个视图解析器来处置处罚(视图解析器有许多种)
自定义视图


[*]在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由SpringMVC 的 InternalResourceViewResolver 视图处置处罚器来处置处罚的
​<bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>前缀 value="/WEB-INF/pages/"和 后缀 value=".jsp" 之后会拼接 返回给视图解析器的返回值
    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>2. 在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求.需要在spring配置文件 , 增加自定义视图解析器

<bean >
        <property name="order" value="99"></property>
</bean>

[*]name="order" :表示给这个解析器设置优先级,
[*]我们自己的视图解析优先级高,Order 值越小,优先级越高
编写自己的视图


[*]继承 AbstractView 就可以作为一个视图使用
[*]@Component(value = "myView")会作为id= myView 的一个组件 注入到容器中
@Component(value = "zyView")
public class MyView extends AbstractView {
    @Override
    protected void renderMergedOutputModel(Map<String, Object> map,
HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//该方法完成视图渲染
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//并且可以确定我们要跳转的页面 /WEB-INF/pages/my_view.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("进入到自己的视图..");

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//请求转发到 /WEB-INF/pages/my_view.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//第一个斜杠会解析成 工程路径-> springmvc/
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>httpServletRequest.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    .forward(httpServletRequest,httpServletResponse);
    }
}进行跳转

@RequestMapping("/goods")
@Controller
public class GoodsHandler {
    @RequestMapping(value = "/buy")
    public String buy() {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("--buy()被调用--");
       return "zyView";
    }
}自定义视图小结


[*]自定义视图: 创建一个View 的bean, 该bean 需要继承自AbstractView, 并实现 renderMergedOutputModel 方法.
[*]并把自定义View 参加到IOC 容器中
[*]自定义视图的视图处置处罚器,使用BeanNameViewResolver, 这个视图处置处罚器也需要配置到ioc 容器
[*]BeanNameViewResolver 的调用优先级需要设置一下,设置order 比Integer.MAX_VAL 小的值. 以确保其在InternalResourceViewResolver 之前被调用
自定义视图-工作流程


[*]SpringMVC 调用目的方法, 返回自定义View 在IOC 容器中的id
[*]SpringMVC 调用BeanNameViewResolver 解析视图: 从IOC 容器中获取返回id 值对应的bean, 即自定义的View 的对象
[*]SpringMVC 调用自定义视图的renderMergedOutputModel 方法渲染视图
[*]如果在SpringMVC 调用目的方法, 返回自定义View 在IOC 容器中的id不存在, 则仍然按照默认的视图处置处罚器机制处置处罚
自定义解析器的实行流程-源码

/** * 自定义解析器的实行流程 *1. *    @RequestMapping(value = "/buy") *   public String buy() { *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> System.out.println("--buy()被调用--"); *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "zyView";--> *   } *2. *ApplicationContext context = obtainApplicationContext(); * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (!context.containsBean(viewName)) {//判断viewName是否在容器中 * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>// Allow for ViewResolver chaining... * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return null; *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    } * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (!context.isTypeMatch(viewName, View.class)) {//判断是否继承了 AbstractView 实际上是判断是否实现了View接口 因为AbstractView实现了View接口 * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (logger.isDebugEnabled()) { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>logger.debug("Found bean named '" + viewName + "' but it does not implement View"); *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>// Since we're looking into the general ApplicationContext here, * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>// let's accept this as a non-match and allow for chaining as well... * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return null; *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return context.getBean(viewName, View.class);    --> * <bean >
        <property name="order" value="99"></property>
</bean>} * <bean >
        <property name="order" value="99"></property>
</bean>3. * <bean >
        <property name="order" value="99"></property>
</bean> protected void renderMergedOutputModel(Map map, * HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { * *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> //该方法完成视图渲染 *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> //而且可以确定我们要跳转的页面 /WEB-INF/pages/my_view.jsp *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> System.out.println("进入到自己的视图.."); * *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> //请求转发到 /WEB-INF/pages/my_view.jsp *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> //第一个斜杠会解析成 工程路径-> springmvc/ *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> httpServletRequest.getRequestDispatcher("/WEB-INF/pages/my_view.jsp") *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>   .forward(httpServletRequest,httpServletResponse); --> *   } * } * <bean >
        <property name="order" value="99"></property>
</bean>4. * <bean >
        <property name="order" value="99"></property>
</bean>进入到my_view页面

* 是从自定义视图来的...
* * */默认解析器的实行流程-源码

/** * 默认解析器的实行流程 * 1. * public String buy() { *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> System.out.println("--buy()被调用--"); *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "zyView";-> *   } * 2. * public InternalResourceViewResolver(String prefix, String suffix) { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>this(); * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>setPrefix(prefix);//用于拼接 * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>setSuffix(suffix);//用于拼接 *} * 3. * protected AbstractUrlBasedView buildView(String viewName) throws Exception { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>InternalResourceView view = (InternalResourceView) super.buildView(viewName);//调用super.buildView(viewName) * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (this.alwaysInclude != null) { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>view.setAlwaysInclude(this.alwaysInclude); *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    } * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>view.setPreventDispatchLoop(true); * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return view; * } * 4. * 找不到 报错404 */找不到自定义解析器 会调用默认解析器

/** * 找不到自定义解析器 会调用默认解析器 * 1. * public String buy() { *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> System.out.println("--buy()被调用--"); *<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "zyView"; --> *   } * 2. *ApplicationContext context = obtainApplicationContext(); * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (!context.containsBean(viewName)) {//找不到返回null * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>// Allow for ViewResolver chaining... * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return null;--> *   } * 3. *if (this.viewResolvers != null) { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>for (ViewResolver viewResolver : this.viewResolvers) { //遍历解析器 * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>View view = viewResolver.resolveViewName(viewName, locale);//此时以及走默认解析器那一套了 * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (view != null) { * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return view;//进行拼接前缀和后缀 但找不到 *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} *    } *4. *拼接后找不到 报错 404 */默认解析器一旦解析不会去自定义解析器


[*]因为默认解析器会拼接 view != null 就return了
<bean >
        <property name="order" value="99"></property>
</bean> * if (this.viewResolvers != null) {   * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>for (ViewResolver viewResolver : this.viewResolvers) {   * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>View view = viewResolver.resolveViewName(viewName, locale);   * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>if (view != null) {   * <bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>return view;   *<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}   *   }目的方法直接指定转发或重定向


[*]默认返回的方式是请求转发,然后用视图处置处罚器进行处置处罚
@RequestMapping(value = "/buy")
    public String buy(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";
    }

[*]也可以在目的方法直接指定重定向或转发的url 地址
请求转发:return "forword:路径"
return "forword:/WEB-INF/pages/my_view.jsp"重定向:return "redirect:路径"
return "redirect:login.jsp"注意事项:

[*]对于重定向,不能重定向到WEB-INF目录下
重定向在响应头返回的URL中是<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>   /工程路径/login.jsp【此时,浏览器会将第一个 / 处置处罚成 IP:端口/工程路径/login.jsp】
[*]对于请求转发,是在服务器内部进行,第一个 / 解析成 工程路径,进行转发
数据格式化

基本介绍

引出:在我们提交数据(比如表单时)SpringMVC 怎样对提交的数据进行转换和处置处罚的??

[*]基本数据类型可以和字符串之间自动完成转换
[*]Spring MVC 上下文中内建了许多转换器,可完成大多数Java 类型的转换工作
基本数据类型和字符串自动转换

<form:form action="save" method="post" modelAttribute="monster">
    妖怪名字: <form:input path="name"/> <form:errors path="name"/> <br><br>
    妖怪年龄~: <form:input path="age"/> <form:errors path="age"/><br><br>
    电子邮件: <form:input path="email"/> <form:errors path="email"/><br><br>
    妖怪生日: <form:input path="birthday"/> <form:errors path="birthday"/>要求以"9999-11-11"的形式<br><br>
    妖怪薪水: <form:input path="salary"/> <form:errors path="salary"/>要求以"123,890.12"的形式<br><br>
    <input type="submit" value="添加妖怪"/>
</form:form>
[*]SpringMVC 表单标签在显示之前必须在request 中有一个bean, 该bean 的属性和表单标签的字段要对应!
[*]request 中的key 为: form 标签的modelAttribute 属性值, 比如这里的monsters
[*]SpringMVC 的form:form 标签的action 属性值中的/ 不代表WEB 应用的根目录.
@RequestMapping(value = "/addMonsterUI")
    public String addMonsterUI(Map<String, Object> map) {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//这里需要给request 增加一个monster , 因为jsp 页面的modelAttribute="monster"需要
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//是springMVC 的内部的检测机制即使是一个空的也需要,否则报错
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>map.put("monster", new Monster());
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "datavalid/monster_addUI";
    }分析:

[*]当我们在浏览器发送 age=10 时,会把10转换成String类型,到达后端后,又会把String转成 int/Integer
[*]而发送 age=aaa 时,会把aaa转成 string类型,到达后端后,把String类型 的 aaa转换成 int/Integer,此时会报错
特别数据类型和字符串间的转换


[*]特别数据类型和字符串之间的转换使用注解(比如日期,规定格式的小数比如货币情势等)
[*]对于日期和货币可以使用@DateTimeFormat 和@NumberFormat 注解. 把这两个注解标志在字段上即可.(JavaBean上)
@DateTimeFormat(pattern = "yyy-MM-dd")
    private Date birthday;
验证国际化


[*]对输入的数据(比如表单数据),进行必要的验证,并给出相应的提示信息
[*]对于验证表单数据,springMVC 提供了许多实用的注解, 这些注解由JSR 303 验证框架提供.
JSR 303 验证框架


[*]JSR 303 是Java 为Bean 数据正当性校验提供的标准框架,它已经包罗在JavaEE 中
[*]JSR 303 通过在Bean 属性上标注类似于@NotNull、@Max 等标准的注解指定校验规则,
并通过标准的验证接口对Bean 进行验证
[*]JSR 303 提供的基本验证注解有:
https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408201958021-461769273.png
Hibernate Validator 扩展注解


[*]Hibernate Validator 和Hibernate 没有关系,只是JSR 303 实现的一个扩展.
[*]Hibernate Validator 是JSR 303 的一个参考实现,除支持全部标准的校验注解外,它还支
持以下的扩展注解:
[*]扩展注解有如下:
https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202112477-823494571.png
<bean >
        <property name="order" value="99"></property>
</bean>@NotNull(message = "年龄必须1-100")    @Range(min = 1,max = 100)    private Integer age;    @NotNull    private String name ;    @NotNull(message = "生日必须符合格式")    @DateTimeFormat(pattern = "yyy-MM-dd")
    private Date birthday;    @NotNull(message = "salary必须符合格式")    @NumberFormat(pattern = "###,###.##")    private Float salary;<bean >
        <property name="order" value="99"></property>
</bean>@RequestMapping(value = "/save")    public String save(@Valid Monster monster, Errors errors, Map map) {}
[*]@Valid Monster monster:表示对monster 接收的数据进行校验
[*]Errors errors: 表示如果校验出现错误,将校验的错误信息保存到 errors 中
[*]Map map:如果校验出现错误,会将校验的错误信息保存到map,而且同时保存 monster对象


[*]在前端使用 回显错误信息
<bean >
        <property name="order" value="99"></property>
</bean>妖怪名字:   

    妖怪年龄~:

    电子邮件:

    妖怪生日:要求以"9999-11-11"的情势

    妖怪薪水:要求以"123,890.12"的情势

自定义验证错误信息

1.需要在Spring配置文件中配置相关bean


    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>2.需要在src目录下创建 i18nxxx.properties去读取错误信息

NotEmpty.monster.name=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a
typeMismatch.monster.age=\u5e74\u9f84\u8981\u6c42\u5728\u0031\u002d\u0031\u0035\u0030\u4e4b\u95f4
typeMismatch.monster.birthday=\u751f\u65e5\u683c\u5f0f\u4e0d\u6b63\u786e
typeMismatch.monster.salary=\u85aa\u6c34\u683c\u5f0f\u4e0d\u6b63\u786e3.用工具将希望自定义的错误信息转换成Unicode编码填入i18nxxx.properties

注意事项


[*]在需要验证的Javabean/POJO 的字段上加上相应的验证注解.
[*]目的方法上,在JavaBean/POJO 类型的参数前, 添加@Valid 注解. 告知SpringMVC该bean 是需要验证的
<bean >
        <property name="order" value="99"></property>
</bean>@RequestMapping(value = "/save")    public String save(@Valid Monster monster, Errors errors, Map map) {}
[*]在@Valid 注解之后, 添加一个Errors 或BindingResult 类型的参数, 可以获取到验证的错误信息
[*]需要使用 标签来显示错误消息, 这个标签,需要写在form:form 标签内生效.
<form:form action="save" method="post" modelAttribute="monster">
    妖怪名字: <form:input path="name"/> <form:errors path="name"/> <br><br>
</form:form>
[*]错误消息的国际化文件i18n.properties , 中文需要是Unicode 编码,使用工具转码.
格式: 验证规则.表单modelAttribute 值.属性名=消息信息
NotEmpty.monster.name=\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A
typeMismatch.monster.age=\u7C7B\u578B\u4E0D\u5339\u914D
[*]注解@NotNull 和@NotEmpty 的区别分析


[*]@NotEmpty 是判断 null 的 而且可以接收 任何类型
[*]@NotNull是判断null 和 empty的,接收String,collection,map和array
[*]如果是字符串验证空, 建议使用@NotEmpty

[*]SpingMVC 验证时,会根据差别的验证错误, 返回对应的信息
注解组合使用


[*]使用@NotNull + @Range 组合使用
<bean >
        <property name="order" value="99"></property>
</bean>@NotNull(message = "年龄必须1-100")    @Range(min = 1,max = 100)    private Integer age;取消属性绑定 @InitBinder 注解


[*]不希望接收到某个表单对应的属性的值,则可以通过@InitBinder 注解取消绑定.

[*]使用@InitBinder 标识的该方法,可以对WebDataBinder 对象进行初始化。
[*]WebDataBinder 是DataBinder 的子类,用于完成由表单字段到JavaBean 属性的绑定
[*]@InitBinder 方法不能有返回值,它必须声明为void。
[*]@InitBinder 方法的参数通常是是WebDataBinder
<bean >
        <property name="order" value="99"></property>
</bean>@InitBinder    public void initBinder(WebDataBinder webDataBinder){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>webDataBinder.setDisallowedFields("name");//表示取消属性name的绑定; 这里可以填写多个字段    }

[*]取消属性的绑定,那么在JavaBean中的校验注解也应该去掉
中文乱码问题处置处罚


[*]Spring提供的过滤器处置处罚中文
<filter>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><filter-name>CharacterEncodingFilter</filter-name>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><init-param>
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><param-name>encoding</param-name>
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><param-value>utf-8</param-value>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans></init-param>
</filter>
<filter-mapping>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><filter-name>CharacterEncodingFilter</filter-name>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><url-pattern>/*</url-pattern>
</filter-mapping>处置处罚JSON格式

@ResponseBody


[*]服务器 -----JSON数据-----> 客户端/浏览器
@RequestMapping(value = "/json/dog")
    @ResponseBody
    public Dog getJson(){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Dog dog = new Dog("大黄", "贝加尔");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return dog;
    }@RequestBody

客户端/浏览器-----JSON数据-----> 服务器
@RequestMapping(value = "/save2")
@ResponseBody
public User save2(@RequestBody User user){
    System.out.println("user= "+user);
    return user;
}
[*]将客户端/浏览器发送的json字符串数据封装成 JavaBean对象
[*]再把这个 JavaBean对象 以 json对象情势返回
[*](@RequestBody User user)在形参上指定
[*]SpringMVC就会将提交的json字符串数据填充给指定JavaBean
注意事项


[*]目的方法正常返回json需要的数据,可以是对象也可以是集合
[*]@ResponseBody可以写在类上,这样对该类全部的方法生效
[*]@ResponseBody + @Controller 可以直接写成@RestController
HttpMessageConverter


[*]SpringMVC 处置处罚JSON-底层实现是依靠HttpMessageConverter来进行转换的
工作机制简图

https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202049715-1045576664.png

[*]使用HttpMessageConverter 将请求信息转化并绑定到处置处罚方法的入参中, 或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:

[*]使用@RequestBody / @ResponseBody 对目的方法进行标注
[*]使用HttpEntity / ResponseEntity 作为目的方法的入参或返回值

[*]当控制器处置处罚方法使用到@RequestBody/@ResponseBody 或HttpEntity/ResponseEntity 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错
SpringMVC文件上传


[*]在SpringMVC 中,通过返回ResponseEntity的类型,可以实现文件下载的功能
[*]需要构建 ResponseEntity 对象,需要1.得到http响应头<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> 2.http响应状态<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>3.下载文件的数据
@RequestMapping(value="/downFile")
    public ResponseEntity<byte[]> downFile(HttpSession session) throwsException{
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//1.先获取到要下载 的 InputStream
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>InputStream resourceAsStream =
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    session.getServletContext().getResourceAsStream("/img/1.jpg");

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//2.开辟存放文件的byte数组 -> 支持二进制数据
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//resourceAsStream.available() 返回资源文件的大小
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>byte[] bytes = new byte;

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//3. 将要下载的文件数据读入到byte数组
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>resourceAsStream.read(bytes);

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>/*
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ResponseEntity 的构造器:
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>this(body, headers, (Object) status);
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> */
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//准备构造ResponseEntity 对象
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//4.构建httpStatus
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>HttpStatus httpStatus = HttpStatus.OK;
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//5.构建http响应头
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>HttpHeaders headers = new HttpHeaders();
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//指定浏览器以附件的形式处理回送数据
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>headers.add("Content-Disposition","attachment;filename=1.jpg");
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ResponseEntity<byte[]> responseEntity =
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    new ResponseEntity<>(bytes, headers, httpStatus);
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return responseEntity;
    }

[*]文件下载响应头的设置
content-type 指示响应内容的格式
content-disposition 指示如那边置处罚响应内容,一样寻常有两种方式:1. inline:直接在页面显示<bean >
        <property name="order" value="99"></property>
</bean>2.attchment:以附件情势下载
SpringMVC文件上传

基本介绍


[*]Spring MVC 为文件上传提供了直接的支持,
[*]这种支持是通过即插即用的MultipartResolver 实现的。
[*]Spring 用Jakarta Commons FileUpload 技术实现了一个MultipartResolver 实现类:CommonsMultipartResovler
[*]Spring MVC 上下文中默认没有装配MultipartResovler,因此默认情况下不能处置处罚文件的上传工作,
[*]如果想使用Spring 的文件上传功能,需现在上下文中配置MultipartResolver
<bean >
        <property name="order" value="99"></property>
</bean><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>

[*]需要在form表单添加属性 enctype="multipart/form-data"
<form action="<%=request.getContextPath()%>/fileUpload" method="post" enctype="multipart/form-data">
    文件介绍:<input type="text" name="introduce"><br>
    选择文件:<input type="file" name="file"><br>
    <input type="submit" value="上传文件">
</form>文件上传

//编写方法 处置处罚文件上传的请求    @RequestMapping(value = "/fileUpload")    public String fileUpload(@RequestParam(value = "file") MultipartFile file,
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>    HttpServletRequest request, String introduce) throws IOException {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//接收到提交的文件名<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String originalFilename = file.getOriginalFilename();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("提交的文件名= " + originalFilename);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("文件介绍= " + introduce);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//获取到文件保存的目的位置/路径<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String filePath =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    request.getServletContext().getRealPath("/img/" + originalFilename);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//创建文件<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>File saveToFile = new File(filePath);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//将上传的文件转存到 saveToFile<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>file.transferTo(saveToFile);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "success";    }拦截器

基本介绍


[*]Spring MVC 也可以使用拦截器对请求进行拦截处置处罚,
[*]用户可以自定义拦截器来实现特定的功能.
[*]自定义的拦截器必须实现HandlerInterceptor 接口
自定义拦截器的三个方法


[*]preHandle():这个方法在业务处置处罚器处置处罚请求之前被调用,在该方法中对用户请求request 进行处置处罚。
[*]postHandle():这个方法在目的方法处置处罚完请求后实行
[*]afterCompletion():这个方法在完全处置处罚完请求后被调用,可以在该方法中进行一些资源
清理的操作。
在Spring配置文件中配置拦截器

默认配置是都全部的目的方法都进行拦截, 也可以指定拦截目的方法, 比如只是拦截hi
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> //直接引用对应拦截器    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>mvc:mapping 支持通配符, 同时指定不对哪些目的方法进行拦截
    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>

[*]这样配置会拦截h打头的url指定的方法
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>

[*]这样配置会拦截h打头的url指定的方法而且排除 url是hello的方法
自定义拦截器实行流程分析图

https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202148244-904128437.png
● 自定义拦截器实行流程分析

[*]如果preHandle 方法返回false, 则不再实行目的方法, 可以在此指定返回页面
[*]postHandle 在目的方法被实行后实行. 可以在方法中访问到目的方法返回的 ModelAndView 对象
[*]若preHandle 返回true, 则afterCompletion 方法在渲染视图之后被实行.
[*]若preHandle 返回false, 则afterCompletion 方法不会被调用
[*]在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效
注意事项


[*]拦截器需要配置才生效,不配置是不生效的.
[*]如果preHandler() 方法返回了false, 就不会实行目的方法(前提是你的目的方法被拦截了), 程序员可以在这里根据业务需要指定跳转页面.
多个拦截器

https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202216116-2141322211.jpg
注意事项


[*]如果第1 个拦截器的preHandle() 返回false , 后面都不在实行
[*]如果第2 个拦截器的preHandle() 返回false , 就直接实行第1 个拦截器的
afterCompletion()方法, 如果拦截器更多,规则类似
[*]前面说的规则,都是目的方法被拦截的前提
异常处置处罚

基本介绍


[*]Spring MVC 通过HandlerExceptionResolver 处置处罚程序的异常,包括Handler 映射、数据绑定以及目的方法实行时发生的异常。
[*]紧张处置处罚Handler 中用@ExceptionHandler 注解定义的方法。
[*]ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话, 会找@ControllerAdvice 类的@ExceptionHandler 注解方法, 这样就相当于一个全局异常处置处罚器
[*]如果不去处置处罚异常,tomcat会默认机制处置处罚,用户看到的页面非常不友好
异常处置处罚的优先级

局部异常 > 全局异常 > SimpleMappingExceptionResolver > tomcat默认机制
局部异常

//局部异常就是直接在这个Handler 中编写即可
    @ExceptionHandler({ArithmeticException.class, NullPointerException.class})
    public String localException(Exception ex,HttpServletRequest request){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("异常信息是~" + ex.getMessage());
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//如何将异常的信息带到下一个页面.
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>request.setAttribute("reason", ex.getMessage());
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "exception_mes";
    }全局异常

@ControllerAdvice//@ControllerAdvice 表示了该注解,就是全局异常
public class MyGlobalException {

    @ExceptionHandler({NumberFormatException.class, ClassCastException.class})
    public String globalException(Exception ex, HttpServletRequest request){
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("全局异常处理---"+ex.getMessage());
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>request.setAttribute("reason",ex.getMessage());
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return "exception_mes";
    }

[*]@ControllerAdvice 表示了该注解,就是全局异常
自定义异常


[*]通过@ResponseStatus 注解, 可以自定义异常
[*]格式:@ResponseStatus(reason = "异常原因",value = httpStatus状态 )
@ResponseStatus(reason = "年龄需要在1-120之间",value = HttpStatus.BAD_REQUEST )
public class AgeException extends RuntimeException{//需要继承RuntimeException/Exception
}

[*]自定义异常类需要继承RuntimeException/Exception
[*]httpStatus会有许多状态
https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202244143-282336352.png

[*]如果想在其他页面看到reason信息,加上带String构造器即可
public AgeException(String message) {
    super(message);
}
统一处置处罚异常信息

基本介绍


[*]如果希望对全部异常进行统一处置处罚,可以使用SimpleMappingExceptionResolver
[*]它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
[*]需要在ioc 容器中配置
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>allEx<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>

[*]在这个标签内 就可以配置出现异常需要跳转的页面allEx
[*]key="java.lang.Exception" 是异常的范围,这样设置可以对未知异常进行统一处置处罚,也就是全部异常都处置处罚
SpringMVC实行流程以及源码剖析

SpringMVC实行流程表示图

https://img2024.cnblogs.com/blog/3419314/202404/3419314-20240408202259410-1356417643.png
实行流程-源码剖析


[*]发出请求url
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   logRequest(request);
[*]调用处置处罚器映射器
//getWebApplicationContext() 就是Spring容器
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
//走完这一步前端控制器就有了Spring容器

doDispatch(request, response);//进入分发
    2.1 HandlerExecutionChain mappedHandler = null;//有属性 处理器链
    2.2 mappedHandler = getHandler(processedRequest);// mappedHandler中已经有 目标Handler 和 拦截器链
[*]调用处置处罚器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//得到处理器适配器
String method = request.getMethod();得到请求方式
[*]调用Handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//调用Handler

mav = invokeHandlerMethod(request, response, handlerMethod);

invocableMethod.invokeAndHandle(webRequest, mavContainer);//调用Handler中的目标方法了

ModelAndView modelAndView = new ModelAndView();//到达目标方法

return invoke0(this.method, var1, var2);//目标方法执行完毕返回

return getModelAndView(mavContainer, modelFactory, webRequest);

return mav;//返回给前端处理器

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//回到起点,返回了一个 ModelAndView
[*]调用视图解析器
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);render(mv, request, response);//进行渲染    //进入render 方法<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String viewName = mv.getViewName();//拿到视图名称<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>view = resolveViewName(viewName, mv.getModelInternal(), locale, request);//进行视图解析<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//调用视图解析器<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (this.viewResolvers != null) {      for (ViewResolver viewResolver : this.viewResolvers) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> View view = viewResolver.resolveViewName(viewName, locale);//解析完毕返回视图<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> if (view != null) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>return view;//返回视图给前端控制器<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans> }   }   }
[*]视图渲染
view.render(mv.getModelInternal(), request, response);

renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);//渲染合并 输出模型
    //进入方法
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);//获得RequestDispatcher
[*]返回响应
rd.forward(request, response);//返回响应
手写SpringMVC底层机制!


[*]前景提要:实现的是SpringMVC焦点机制
[*]对一些细枝末节的代码做了简化,比如字符串的处置处罚...
[*]完成哪些机制

[*]机制一: 通过@RequestMapping ,可以标志一个方法,编写路径url,浏览器就能通过url完成调用
[*]机制二: 进行依靠注入,使之不需要传统的new 一个对象,而是直接从IOC容器中获得
[*]机制三:通过@RequestParam,如果浏览器传递的参数名和目的方法的形参不一致,可以通过value设置进行匹配
[*]机制四:在目的方法完成后,跳转到相关页面 请求转发/重定向
[*]机制五:在目的方法完成后,通过@Response注解,向浏览器发送JSON格式数据

手写添加配置

思路


[*]需要配置pom.xml的依靠
[*]需要写一个Servlet 作为前端控制器
[*]需要配置Web.xml 中的前端控制器 1).url 2)配置spring容器配置文件的classpath:3)跟随Tomcat 自启动
[*]需要配置spring容器配置文件
[*]需要配置spring容器配置文件 扫描的路径
实现


[*]需要配置pom.xml的依靠
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>javax.servlet      javax.servlet-api      3.1.0      provided<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>dom4j      dom4j      1.1<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    org.apache.commons      commons-lang3      3.12.0   

[*]需要写一个Servlet 作为前端控制器
public class ZyDispatcherServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("ZyDispatcherServlet-doPost--");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("ZyDispatcherServlet-doGet--");
    }
}

[*]需要配置Web.xml 中的前端控制器 1).url 2)配置spring容器配置文件的classpath:3)跟随Tomcat 自启动
[*]需要配置spring容器配置文件 扫描的路径
   ZyDispatcherServlet    com.code_study.zyspringmvc.servlet.ZyDispatcherServlet<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>      contextConfigLocation      classpath:zyspringmvc.xml<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>1<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ZyDispatcherServlet    /

[*]需要配置spring容器配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>完成浏览器可以请求控制层

思路


[*]创建@Controller和自己的Controller
[*]编写工具类XMLParser,解析spring容器配置文件
[*]开发自己的 Spring容器,得到扫描类的全路径列表
[*]开发自己的 前端控制器,实例化对象到容器中
[*]完成请求的URL和控制器方法的映射关系
[*]完成前端控制器分发请求到对应控制器

[*]自定义注解@Controller
[*]创建Controller
[*]需要写一个工具类XMLParser来解析在spring容器配置文件 扫描的路径的包 返回全部的路径
[*]这个全部的路径 一个split(",")分隔,都进行扫描
[*]需要写自己的 前端控制器
[*]需要写自己的 Spring容器
[*]在前端控制器中 需要添加方法 scanPackage() 扫描 XMLParser 解析出来的路径
[*]在Spring容器中 需要添加一个属性 classFullPathList 来保存扫描出来的类的全路径
[*]需要添加一个属性 ioc 来存放反射生成的bean对象 也就是过滤classFullPathList中没有@Controller注解的一些路径 并实例化
[*]需要添加类Handler 这个类要保存 一个url 对应的 一个控制器的方法的 映射 ,也就是说,根据这个url,可以找到对应控制器的对应方法
[*]需要添加一个属性 HandlerList 用于 保存Handler 【url 和 控制器的映射】
[*]需要添加三个方法 一个是initHandlerMapping(),完成 url 对应的 一个控制器的方法的 映射,即 将ioc 中bean 中的 方法进行反射,获取url,将 url,method,bean 封装成Handler放入HandlerList保存
[*]添加第二个方法 getHandler(),需要将浏览器发送的request请求中的 uri拿出来,遍历HandlerList进行配对,如果有 就返回对应的Handler
[*]添加第三个方法 executeDispatch(),进行分发处置处罚,需要 调用getHandler() 获取浏览器发送的request请求 对应的 Handler,获取Handler中的method 进行反射调用,method .invoke() 实现分发请求。
实现


[*]自定义注解@Controller
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
    String value() default "";
}
[*]创建Controller
@Controller
public class MonsterController {
}
[*]需要写一个工具类XMLParser来解析在spring容器配置文件 扫描的路径的包 返回全部的路径
public class XMLParser {    public static String getBasePackage(String xmlFile){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>SAXReader saxReader = new SAXReader();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ClassLoader classLoader = XMLParser.class.getClassLoader();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>InputStream resourceAsStream = classLoader.getResourceAsStream(xmlFile);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Document document = saxReader.read(resourceAsStream);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Element rootElement = document.getRootElement();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Element element = rootElement.element("component-scan");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String basePackage = element.attribute("base-package").getText();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>return basePackage;<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} catch (DocumentException e) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>throw new RuntimeException(e);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }}
[*]这个全部的路径 一个split(",")分隔,都进行扫描
[*]需要写自己的 前端控制器
[*]需要写自己的 Spring容器
[*]在前端控制器中 需要添加方法 scanPackage() 扫描 XMLParser 解析出来的路径
public void scanPackage(String pack) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//获得包地点的工作路径 [绝对路径]<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>URL url =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    this.getClass().getClassLoader().//获取类的加载器<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//得到指定包对应的工作路径 [绝对路径]    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>getResource("/" + pack.replaceAll("\\.", "/"));<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>// System.out.println("url= "+url);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//根据得到的路径,对其进行扫描,把类的全路径 保存到 classFullPathList<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String path = url.getFile();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//在io中 把目录也是为一个文件<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>File file = new File(path);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//遍历file 【遍历出文件和子目录】<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (File f : file.listFiles()) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (f.isDirectory()) {//如果是目录<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //需要递归扫描 找子目录<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    scanPackage(pack + "." + f.getName());<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //的确是个文件<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //扫描到的文件可能是 .class 文件 也可能是其他文件<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //就算是.class 文件 也需要判断是否需要注入容器 有无加 @Controller注解<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //现在无法拿到注解 因为没法反射 所以先把文件的全路径都保存到 classFullPathList 之后在注入对象到容器时再处置处罚<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    String classFullPath =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//类的全路径不需要.class 去掉.class<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>pack + "." + f.getName().replaceAll(".class", "");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //保存到 classFullPathList<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    classFullPathList.add(classFullPath);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }
[*]在Spring容器中 需要添加一个属性 classFullPathList 来保存扫描出来的类的全路径
//保存扫描的包/子包类的全路径    private List classFullPathList =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>new ArrayList();
[*]需要添加一个属性 ioc 来存放反射生成的bean对象 也就是过滤classFullPathList中没有@Controller注解的一些路径 并实例化
//定义属性 ioc -> 存放反射生成的bean对象 比如Controller / Service /Daopublic ConcurrentHashMap ioc =<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>new ConcurrentHashMap();
[*]编写方法,将扫描到的类,在满足情况下 反射到ioc容器
//编写方法,将扫描到的类,在满足情况下 反射到ioc容器    public void executeInstance() {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (classFullPathList.size() == 0) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//分析没有扫描到类<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>return;<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//遍历classFullList<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (String classFullPath : classFullPathList) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Class clazz = Class.forName(classFullPath);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    if (clazz.isAnnotationPresent(Controller.class)) {//处置处罚@Controller<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String className = clazz.getSimpleName();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Object instance = clazz.newInstance();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String value = clazz.getAnnotation(Controller.class).value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (!"".equals(value)) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>className = value;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>className = StringUtils.uncapitalize(className);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ioc.put(className, instance);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    else if (clazz.isAnnotationPresent(Service.class)) {//处置处罚@Service<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String className = clazz.getSimpleName();//类名<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Service serviceAnnotation = clazz.getAnnotation(Service.class);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String value = serviceAnnotation.value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (!"".equals(value)) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>className = value;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Object instance = clazz.newInstance();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>ioc.put(className, instance);<bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean><bean >
        <property name="order" value="99"></property>
</bean>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} catch (Exception e) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    throw new RuntimeException(e);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }
[*]需要添加类Handler 这个类要保存 一个url 对应的 一个控制器的方法的 映射 ,也就是说,根据这个url,可以找到对应控制器的对应方法
ZyHandler {    private String url;    private Method method;    private Object controller;    public ZyHandler() {    }    public ZyHandler(String url, Method method, Object controller) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>this.url = url;<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>this.method = method;<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>this.controller = controller;    }//需要提供getter和setter方法...
[*]需要添加一个属性 HandlerList 用于 保存Handler 【url 和 控制器的映射】
//定义属性 HandlerList -> 保存ZyHandler 【url 和 控制器的映射】    private List HandlerList =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>new ArrayList();
[*]需要添加三个方法 一个是initHandlerMapping(),完成 url 对应的 一个控制器的方法的 映射,即 将ioc 中bean 中的 方法进行反射,获取url,将 url,method,bean 封装成Handler放入HandlerList保存
private void initHandlerMapping(){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//遍历 ioc<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (Map.Entry entry:zyWebApplicationContext.ioc.entrySet()) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (zyWebApplicationContext.ioc.isEmpty()){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    return;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Object bean = entry.getValue();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Class clazz = bean.getClass();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (clazz.isAnnotationPresent(Controller.class)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Method[] declaredMethods = clazz.getDeclaredMethods();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    for (Method declaredMethod : declaredMethods) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (declaredMethod.isAnnotationPresent(RequestMapping.class)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String url = declaredMethod.getAnnotation(RequestMapping.class).value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>ZyHandler zyHandler = new ZyHandler(url, declaredMethod, bean);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>HandlerList.add(zyHandler);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }
[*]添加第二个方法 getHandler(),需要将浏览器发送的request请求中的 uri拿出来,遍历HandlerList进行配对,如果有 就返回对应的Handler
//编写方法,通过request对象 返回ZyHandler对象 ,如果没有返回null    private ZyHandler getZyHandler(HttpServletRequest request) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String requestURI = request.getRequestURI();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//遍历HandlerList<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (ZyHandler zyHandler : HandlerList) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (requestURI.equals(zyHandler.getUrl())){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    return zyHandler;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return null;    }
[*]添加第三个方法 executeDispatch(),进行分发处置处罚,需要 调用getHandler() 获取浏览器发送的request请求 对应的 Handler,获取Handler中的method 进行反射调用,method .invoke() 实现分发请求。
   public void executeDispatch(HttpServletRequest request,HttpServletResponse response){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ZyHandler zyHandler = getZyHandler(request);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (null == zyHandler){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>   response.getWriter().write("404 NOT FOUND

");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Method method = zyHandler.getMethod();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>method.invoke(zyHandler.getController(),request,response);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} catch (Exception e) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>throw new RuntimeException(e);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }从web.xml文件中动态获取spring配置文件

思路


[*]首先,我们自己写的前端控制器是一个Servlet,它有 servletConfig,可以servletConfig.getInitParameter("xxx") 来获取之前在web.xml配置的classpath:
[*]工具类XMLParser 是在spring容器中解析的 ,web.xml配置的classpath: 是在前端控制器中获取的,因此需要spring容器提供有参构造器,在前端控制器添加参数 spring容器,将classpath 传到spring容器中进行解析。
实现


[*]首先,我们自己写的前端控制器是一个Servlet,它有 servletConfig,可以servletConfig.getInitParameter("xxx") 来获取之前在web.xml配置的classpath:
[*]工具类XMLParser 是在spring容器中解析的 ,web.xml配置的classpath: 是在前端控制器中获取的,因此需要spring容器提供有参构造器,在前端控制器添加参数 spring容器,将classpath 传到spring容器中进行解析。
@Override    public void init() throws ServletException {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String configLocation = getServletConfig().getInitParameter("contextConfigLocation");<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("ZyDispatcherServlet 初始化---");<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>zyWebApplicationContext = new ZyWebApplicationContext(configLocation);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>zyWebApplicationContext.init();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>initHandlerMapping();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("HandlerList= "+HandlerList);    } privateString configLocation;    public ZyWebApplicationContext(String configLocation) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>this.configLocation = configLocation;    } public void init(){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("ZyWebApplicationContext 初始化---");<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String basePackage = XMLParser.getBasePackage(configLocation.split(":"));<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String[] basePackages = basePackage.split(",");<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (basePackages.length >0) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>for (Stringpack : basePackages) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    scanPackage(pack);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} }@Service注解

思路


[*]@Service注解是写在类上的 即@Target(ElementType.TYPE)
[*]这个注解标识的类就是一个Service,那么同样是在executeInstance()方法中判断是否有注解@Service,有的话就保存到ioc容器中
[*]由于是Service,那么保存进ioc 的 k-v 中的 k 就有三种。第一种,就是默认值,用接口的类型的名字首字母小写;第二种,在@Service注解种设置了value属性,那么 k = value;第三章,需要用类名首字母小写也可以获取bean
实现


[*]@Service注解是写在类上的 即@Target(ElementType.TYPE)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
    String value() default "";
}
[*]这个注解标识的类就是一个Service,那么同样是在executeInstance()方法中判断是否有注解@Service,有的话就保存到ioc容器中
[*]由于是Service,那么保存进ioc 的 k-v 中的 k 就有三种。第一种,就是默认值,用接口的类型的名字首字母小写;第二种,在@Service注解种设置了value属性,那么 k = value;第三章,需要用类名首字母小写也可以获取bean
public void executeInstance() {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (classFullPathList.size() == 0){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>return;<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//遍历 classFullPathList<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (String classFullPath : classFullPathList) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Class clazz = Class.forName(classFullPath);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    if (clazz.isAnnotationPresent(Controller.class)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Controller controller = clazz.getAnnotation(Controller.class);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String value = controller.value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String className = clazz.getSimpleName();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Object instance = clazz.newInstance();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if ("".equals(value)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>className = StringUtils.uncapitalize(className);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>className = value;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ioc.put(className,instance);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    } else if (clazz.isAnnotationPresent(Service.class)) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Service serviceAnnotation = clazz.getAnnotation(Service.class);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String annoattionValue = serviceAnnotation.value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Object instance = clazz.newInstance();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if ("".equals(annoattionValue)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Class[] interfaces = clazz.getInterfaces();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>for (Class anInterface : interfaces) {
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   String simpleName = anInterface.getSimpleName();
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   simpleName = StringUtils.uncapitalize(simpleName);
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   ioc.put(simpleName,instance);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//可以通过类名首字母小写<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String simpleName = clazz.getSimpleName();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>simpleName = StringUtils.uncapitalize(simpleName);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>ioc.put(simpleName,instance);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>ioc.put(annoattionValue,instance);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} catch (Exception e) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    throw new RuntimeException(e);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }@Autowried 依靠注入

思路


[*]@Autowried注解是用在字段上,通过ioc容器自动装配,因此 @Target(ElementType.FIELD)
[*]需要遍历ioc中全部的 bean 中的全部字段,来进行判断是否需要自动装配
[*]通过反射获取字段,判断该字段是否带有@Autowried 注解,有的话就判断value值
[*]value为"",分析按默认规则 用字段类型首字母小写 去ioc容器进行查找,如果没有抛出空指针异常throw new NullPointerException("ioc 没有该bean");
[*]如果有值,去ioc容器进行查找该值对应的bean,如果没有抛出空指针异常throw new NullPointerException("ioc 没有该bean");如果有该bean,就用该字段的set()方法将本身的bean 和 查找ioc获取的bean进行装配
[*]即 declaredField.set(bean, beanInIOC);
[*]由于字段是私有属性private,需要暴力破解declaredField.setAccessible(true);
实现


[*]@Autowried注解是用在字段上,通过ioc容器自动装配,因此 @Target(ElementType.FIELD)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    String value() default "";
}
[*]需要遍历ioc中全部的 bean 中的全部字段,来进行判断是否需要自动装配
[*]通过反射获取字段,判断该字段是否带有@Autowried 注解,有的话就判断value值
[*]value为"",分析按默认规则 用字段类型首字母小写 去ioc容器进行查找,如果没有抛出空指针异常throw new NullPointerException("ioc 没有该bean");
[*]如果有值,去ioc容器进行查找该值对应的bean,如果没有抛出空指针异常throw new NullPointerException("ioc 没有该bean");如果有该bean,就用该字段的set()方法将本身的bean 和 查找ioc获取的bean进行装配
[*]即 declaredField.set(bean, beanInIOC);
[*]由于字段是私有属性private,需要暴力破解declaredField.setAccessible(true);
public voidexecuteAutoWired(){    //遍历ioc    if (ioc.isEmpty()){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return;    }    //获取容器里的全部bean 以及 bean对应的字段    for (Map.Entry entry : ioc.entrySet()) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Object bean = entry.getValue();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Class clazz = bean.getClass();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Field[] declaredFields = clazz.getDeclaredFields();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (Field declaredField : declaredFields) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//通过反射获取字段,判断该字段是否带有@Autowried 注解,有的话就判断value值<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (declaredField.isAnnotationPresent(Autowired.class)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Autowired annotation =<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>declaredField.getAnnotation(Autowired.class);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    String beanName = annotation.value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//value为"",分析按默认规则 用字段类型首字母小写 去ioc容器进行查找,<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if ("".equals(beanName)){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>beanName = declaredField.getType().getSimpleName();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>beanName = StringUtils.uncapitalize(beanName);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Object iocBean = ioc.get(beanName);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//如果没有抛出空指针异常<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (null == iocBean){
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   throw new NullPointerException("ioc 没有该Bean");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>declaredField.setAccessible(true);//暴力破解<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>declaredField.set(bean,iocBean);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    } catch (IllegalAccessException e) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>throw new RuntimeException(e);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}    }}@RequestParam

思路


[*]@RequestParam 是写在PARAMETER上的 也就是说 @Target(ElementType.PARAMETER)
[*]这个注解实现的功能 大方向是 分发请求 也就是说 写在 executeDispatch()方法中的
[*]要实现 @RequestParam 需要将形参列表封装到一个数组中 , 因为反射 invoke 可以传入一个数组作为可变参数解析
[*]那么就需要两个数组 一个数组是新创建的数组(大小应与,目的数组的形参个数一致) 将实参放入进去 ;另一个是 反射拿到的目的方法的形参的数组
[*]这两个数组的内容需要一一对应,因为反射需要序次一致
[*]需要获取到request 中请求的参数Map 获取参数名和参数值
[*]可以将功能具体化到 完成这个新数组的实参填写 【完成新数组之后放入invoke方法进行反射就行】
[*]将步调拆解成 1)完成HttpServletRequest 和 HttpServletResponse 的填写 ;2)完成带有@RequestParam注解的形参的填写;3)完成普通的方法参数没有@RequestParam注解的形参的填写
[*]完成HttpServletRequest 和 HttpServletResponse 的填写:就需要先拿到目的方法的全部参数。根据类型的名称 和 形参列表进行匹配 填写
[*]完成带有@RequestParam注解的形参的填写:需要添加方法,获取目的方法中 带有@RequestParam注解的形参是属于第几个参数的,返回int 代表第几个参数,如果有@RequestParam注解,就会返回相应的索引,如果没有就会返回-1 进行普通方法参数的填写 处置处罚
[*]普通方法参数的 填写:需要添加方法,将目的方法的全部的形参的名称 反射保存到 List 返回,再通过遍历判断 请求的参数名和 List中一致的 填写到 数组中
[*]普通方法参数的 填写 需要插件,使用java8的特性 解决在默认情况下 parameter.getName() 获取的名字不是形参真正的名字,而是的问题
实现


[*]@RequestParam 是写在PARAMETER上的 也就是说 @Target(ElementType.PARAMETER)
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value() default "";
}
[*]这个注解实现的功能 大方向是 分发请求 也就是说 写在 executeDispatch()方法中的
[*]要实现 @RequestParam 需要将形参列表封装到一个数组中 , 因为反射 invoke 可以传入一个数组作为可变参数解析
Method method = zyHandler.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes();//形参数组
Object[] params = new Object;
[*]那么就需要两个数组 一个数组是新创建的数组(大小应与,目的数组的形参个数一致) 将实参放入进去 ;另一个是 反射拿到的目的方法的形参的数组
[*]这两个数组的内容需要一一对应,因为反射需要序次一致
[*]需要获取到request 中请求的参数Map 获取参数名和参数值
request.setCharacterEncoding("utf-8");
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
    String name = entry.getKey();//参数 键
    String value = entry.getValue();//参数 值
[*]可以将功能具体化到 完成这个新数组的实参填写 【完成新数组之后放入invoke方法进行反射就行】
[*]将步调拆解成 1)完成HttpServletRequest 和 HttpServletResponse 的填写 ;2)完成带有@RequestParam注解的形参的填写;3)完成普通的方法参数没有@RequestParam注解的形参的填写
[*]完成HttpServletRequest 和 HttpServletResponse 的填写:就需要先拿到目的方法的全部参数。根据类型的名称 和 形参列表进行匹配 填写
for (int i = 0; i < parameterTypes.length; i++) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Class parameterType = parameterTypes;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if ("HttpServletRequest".equals(parameterType.getSimpleName())) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = request;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} else if ("HttpServletResponse".equals(parameterType.getSimpleName())) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = response;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }
[*]完成带有@RequestParam注解的形参的填写:需要添加方法,获取目的方法中 带有@RequestParam注解的形参是属于第几个参数的,返回int 代表第几个参数,如果有@RequestParam注解,就会返回相应的索引,如果没有就会返回-1 进行普通方法参数的填写 处置处罚
//获取目的方法中 带有@RequestParam注解的形参是属于第几个参数的,返 private int getRequestParamterIndex(Method method,String name){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>Parameter[] parameters = method.getParameters();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>for (int i = 0; i < parameters.length; i++) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Parameter parameter = parameters;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    if (parameter.isAnnotationPresent(RequestParam.class)) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String value = parameter.getAnnotation(RequestParam.class).value();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (name.equals(value)) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>return i;//返回int 代表第几个参数<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return -1;    }int requestParamterIndex = getRequestParamterIndex(zyHandler.getMethod(), name);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (requestParamterIndex != -1) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = value;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}
[*]普通方法参数的 填写:需要添加方法,将目的方法的全部的形参的名称 反射保存到 List 返回,再通过遍历判断 请求的参数名和 List中一致的 填写到 数组中
<bean >
        <property name="order" value="99"></property>
</bean>//将目的方法的全部的形参的名称 反射保存到 List 返回    private List getParameterNames(Method method){<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>List parameterList = new ArrayList();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//获取到全部的参数名称<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Parameter[] parameters = method.getParameters();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>for (Parameter parameter : parameters) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//在默认情况下 parameter.getName() 获取的名字不是形参真正的名字<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//而是<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//需要插件,使用java8的特性 解决<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String name = parameter.getName();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>parameterList.add(name);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>System.out.println("目的方法的形参列表=" + parameterList);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>return parameterList;    }else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//没找到@RequestParam 对应参数--使用默认机制<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//1. 得到目的方法的全部形参名<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//2. 对得到目的方法的全部形参名进行遍历,<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//如果匹配就把当前请求的参数值放入params<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>List parameterNames = getParameterNames(zyHandler.getMethod());<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>for (int i = 0; i < parameterNames.size(); i++) {
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   if (name.equals(parameterNames.get(i))) {    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>params = value;    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>break;
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}
[*]普通方法参数的 填写 需要插件,使用java8的特性 解决在默认情况下 parameter.getName() 获取的名字不是形参真正的名字,而是的问题
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>com.fasterxml.jackson.core      jackson-databind      2.14.0   

[*]完整代码
public void executeDispatch(HttpServletRequest request, HttpServletResponse response) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ZyHandler zyHandler = getZyHandler(request);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>try {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if (null == zyHandler) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    response.getWriter().write("404 NOT FOUND!

");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>} else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Method method = zyHandler.getMethod();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Class[] parameterTypes = method.getParameterTypes();//形参数组<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Object[] params = new Object;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //遍历 parameterTypes<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //获取 HttpServletRequest , HttpServletResponse 在形参数组中的位置<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //将request 和 response 保存到params相应的位置上<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    for (int i = 0; i < parameterTypes.length; i++) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>Class parameterType = parameterTypes;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if ("HttpServletRequest".equals(parameterType.getSimpleName())) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = request;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} else if ("HttpServletResponse".equals(parameterType.getSimpleName())) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = response;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    //获取request中的<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    request.setCharacterEncoding("utf-8");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    Map parameterMap = request.getParameterMap();<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    for (Map.Entry entry : parameterMap.entrySet()) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String name = entry.getKey();//参数 键<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String value = entry.getValue();//参数 值<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//获取形参数组中 带有@RequestParam 的形参 的位置<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>//将带有@RequestParam 保存到params相应的位置上<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>int requestParamterIndex = getRequestParamterIndex(zyHandler.getMethod(), name);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (requestParamterIndex != -1) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>params = value;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>} else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//没找到@RequestParam 对应参数--使用默认机制<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//1. 得到目的方法的全部形参名<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//2. 对得到目的方法的全部形参名进行遍历,<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>//如果匹配就把当前请求的参数值放入params<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>List parameterNames = getParameterNames(zyHandler.getMethod());<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>for (int i = 0; i < parameterNames.size(); i++) {
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   if (name.equals(parameterNames.get(i))) {    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>params = value;    <bean >

   
   
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="prefix" value="/WEB-INF/pages/"/>

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="suffix" value=".jsp"/>
    </bean>break;
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   }<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }视图解析

思路


[*]首先 视图解析 它是在分发请求后 在目的方法中进行视图的跳转 forward 或者 redirect,所以这部分的代码应该在 前端处置处罚器的executeDispatch 中 对目的方法进行反射后调用
[*]在对目的方法进行反射 method.invoke() 就会有返回值,根据返回值的类型进行相应业务处置处罚
[*]当返回的是String类型后 我们就可以根据 splic(":")进行分隔
[*]splic(":") 就是进行跳转的方式 forward 或者 redirect
[*]splic(":") 就是进行跳转的页面
[*]如果没有":" ,就分析是默认情况,forward 处置处罚即可
实现


[*]首先 视图解析 它是在分发请求后 在目的方法中进行视图的跳转 forward 或者 redirect,所以这部分的代码应该在 前端处置处罚器的executeDispatch 中 对目的方法进行反射后调用
[*]在对目的方法进行反射 method.invoke() 就会有返回值,根据返回值的类型进行相应业务处置处罚
Object result = zyHandler.getMethod().invoke(zyHandler.getController(), params);
[*]当返回的是String类型后 我们就可以根据 splic(":")进行分隔
[*]splic(":") 就是进行跳转的方式 forward 或者 redirect
[*]splic(":") 就是进行跳转的页面
[*]如果没有":" ,就分析是默认情况,forward 处置处罚即可
if (result instanceof String){<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>       String viewName =(String) result;<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>if (viewName.contains(":")) {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String viewType = viewName.split(":");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>String viewPage = viewName.split(":");<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>if ("forward".equals(viewType)){
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   request.getRequestDispatcher(viewPage).forward(request,response);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}else if (("redirect".equals(viewType))){
    <bean id="messageSource" class=
<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>"org.springframework.context.support.ResourceBundleMessageSource">
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans><property name="basename" value="i18n"></property>
    </bean>   response.sendRedirect(viewPage);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}else {<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>request.getRequestDispatcher(viewName).forward(request,response);<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor><?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>}<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor02"/>
</mvc:interceptor>    }@ResponseBody 返回JSON数据

实现


[*]首先@ResponseBody是写在方法上的 因此 @Target(ElementType.METHOD)
[*]没有默认值 @ResponseBody仅仅作为一个标识
[*]@ResponseBody它是在分发请求后 在目的方法中标识该方法返回JSON格式的数据给浏览器,所以这部分的代码应该在 前端处置处罚器的executeDispatch 中 对目的方法进行反射后调用
[*]在对目的方法进行反射 method.invoke() 就会有返回值,根据返回值的类型进行相应业务处置处罚
[*]当返回的是一个集合类型,而且判断该方法有注解@ResponseBody ,就分析是需要向浏览器返回JSON格式数据
[*]用jackson 包下的 objectWriter对象的 objectMapper.writeValueAsString()方法 ,可以很轻松的将集合转化为JSON进行返回
[*]不要忘了设置response格式,防止乱码,response.setContentType("text/html;charset=utf-8");
[*]直接用response.getWriter.writer()将转化后的结果返回给浏览器即可
思路


[*]首先@ResponseBody是写在方法上的 因此 @Target(ElementType.METHOD)
[*]没有默认值 @ResponseBody仅仅作为一个标识
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}
[*]@ResponseBody它是在分发请求后 在目的方法中标识该方法返回JSON格式的数据给浏览器,所以这部分的代码应该在 前端处置处罚器的executeDispatch 中 对目的方法进行反射后调用
[*]在对目的方法进行反射 method.invoke() 就会有返回值,根据返回值的类型进行相应业务处置处罚
[*]当返回的是一个集合类型,而且判断该方法有注解@ResponseBody ,就分析是需要向浏览器返回JSON格式数据
[*]用jackson 包下的 objectWriter对象的 objectMapper.writeValueAsString()方法 ,可以很轻松的将集合转化为JSON进行返回
else if (result instanceof ArrayList) {    if (zyHandler.getMethod().isAnnotationPresent(ResponseBody.class)) {<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>ObjectMapper objectMapper = new ObjectMapper();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>String json = objectMapper.writeValueAsString(result);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>response.setContentType("text/html;charset=utf-8");<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>PrintWriter writer = response.getWriter();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>writer.write(json);<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>writer.flush();<?xml version="1.0" encoding="UTF-8" ?>
<beans>
   
    <component-scan base-package="com.code_study.controller,com.code_study.service"></component-scan>
</beans>writer.close();    }}
[*]不要忘了设置response格式,防止乱码,response.setContentType("text/html;charset=utf-8");
[*]直接用response.getWriter.writer()将转化后的结果返回给浏览器即可
本文学习内容来自韩顺平老师的课程
仅供个人参考学习

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: SpringMVC学习总结 + 【手写SpringMVC底层机制焦点】