ToB企服应用市场:ToB评测及商务社交产业平台
标题:
SpringMVC学习总结 + 【手写SpringMVC底层机制焦点】
[打印本页]
作者:
数据人与超自然意识
时间:
2024-5-18 05:49
标题:
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 域的值,从而进行请求转换的.
[/code][code]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[Pet]<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>[size=6]进入到my_view页面[/size]
* 是从自定义视图来的...
* * */
复制代码
默认解析器的实行流程-源码
/** * 默认解析器的实行流程 * 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 提供的基本验证注解有:
Hibernate Validator 扩展注解
Hibernate Validator 和Hibernate 没有关系,只是JSR 303 实现的一个扩展.
Hibernate Validator 是JSR 303 的一个参考实现,除支持全部标准的校验注解外,它还支
持以下的扩展注解:
扩展注解有如下:
<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\u786e
复制代码
3.用工具将希望自定义的错误信息转换成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来进行转换的
工作机制简图
使用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) 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>//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[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>//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的方法
自定义拦截器实行流程分析图
● 自定义拦截器实行流程分析
如果preHandle 方法返回false, 则不再实行目的方法, 可以在此指定返回页面
postHandle 在目的方法被实行后实行. 可以在方法中访问到目的方法返回的 ModelAndView 对象
若preHandle 返回true, 则afterCompletion 方法在渲染视图之后被实行.
若preHandle 返回false, 则afterCompletion 方法不会被调用
在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效
注意事项
拦截器需要配置才生效,不配置是不生效的.
如果preHandler() 方法返回了false, 就不会实行目的方法(前提是你的目的方法被拦截了), 程序员可以在这里根据业务需要指定跳转页面.
多个拦截器
注意事项
如果第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会有许多状态
如果想在其他页面看到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实行流程表示图
实行流程-源码剖析
发出请求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("[size=6]404 NOT FOUND[/size]
");<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); }
复制代码
private String 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(":")[1]);<?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 (String pack : 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 void executeAutoWired(){ //遍历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() 获取的名字不是形参真正的名字,而是[arg0,arg1,arg2...]的问题
实现
@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[parameterTypes.length];
复制代码
那么就需要两个数组 一个数组是新创建的数组(大小应与,目的数组的形参个数一致) 将实参放入进去 ;另一个是 反射拿到的目的方法的形参的数组
这两个数组的内容需要一一对应,因为反射需要序次一致
需要获取到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()[0];//参数 值
复制代码
可以将功能具体化到 完成这个新数组的实参填写 【完成新数组之后放入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[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>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[i] = 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[i] = 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[i];<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[requestParamterIndex] = 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>//而是[arg0,arg1,arg2...]<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[i] = 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() 获取的名字不是形参真正的名字,而是[arg0,arg1,arg2...]的问题
<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("[size=6]404 NOT FOUND![/size]
");<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[parameterTypes.length];<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[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>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[i] = 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[i] = 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()[0];//参数 值<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[requestParamterIndex] = 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[i] = 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(":")[0] 就是进行跳转的方式 forward 或者 redirect
splic(":")[1] 就是进行跳转的页面
如果没有":" ,就分析是默认情况,forward 处置处罚即可
实现
首先 视图解析 它是在分发请求后 在目的方法中进行视图的跳转 forward 或者 redirect,所以这部分的代码应该在 前端处置处罚器的executeDispatch 中 对目的方法进行反射后调用
在对目的方法进行反射 method.invoke() 就会有返回值,根据返回值的类型进行相应业务处置处罚
Object result = zyHandler.getMethod().invoke(zyHandler.getController(), params);
复制代码
当返回的是String类型后 我们就可以根据 splic(":")进行分隔
splic(":")[0] 就是进行跳转的方式 forward 或者 redirect
splic(":")[1] 就是进行跳转的页面
如果没有":" ,就分析是默认情况,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(":")[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>String viewPage = viewName.split(":")[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>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企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4