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 绑定的占位符
- // 我们希望目标方法获取到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
- @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");
复制代码 - 如果我们要修改默认机制自动放入的对象的属性
通过请求的方法参数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 验证时,会根据差别的验证错误, 返回对应的信息
注解组合使用
- <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中的校验注解也应该去掉
中文乱码问题处置处罚
- <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>
复制代码- <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容器配置文件 扫描的路径
实现
- <?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
复制代码- 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 /
复制代码- <?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() 实现分发请求。
实现
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface Controller {
- String value() default "";
- }
复制代码- @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; }
复制代码
- 普通方法参数的 填写 需要插件,使用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 处置处罚即可
@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企服之家,中国第一个企服评测及商务社交产业平台。 |