小编给大家分享一下如何使用springMVC,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.配置阶段根据WEB.xml ,先定义DispatcherServle
小编给大家分享一下如何使用springMVC,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
根据WEB.xml ,先定义DispatcherServlet并且定义该sevlet传入的参数和路径。
(1)IOC:初始化配置文件和ioC容器,扫描配置的包下的类,通过反射机制将需要实例化的类放入IOC容器,既将带有spring注解的类进行实例化后存放到 IOC 容器中。IOC容器的实质就是一个集合;
(2)DI:DI阶段(其实就是依赖注入)。对需要赋值的实例属性进行赋值(一般较多都是处理带有注解的@Autowrized的属性)
(3)MVC:构造出HandlerMapping集合,主要作用就是用于存放对外公开的api和Method之间的关系,一个API一般会对应一个可执行的Method.
运行阶段中,当接受到一个url后,会到HandleMapping集合中,找到对应Method、通过反射机制去执行invoker,再返回结果给调用方。
这样就大体完成了springmvc整个运行阶段,所描述的都仅为个人观点,如果有误请在评论中指出。
其整体流程可以参照下图:
接下来就来尝试手写一个类似springmvc的框架了,这个手写的过程还是相当有成就感的!
创建一个空的javaweb工程,引入依赖,其实因为我们是要手写spring,所以基本不需要什么外部的依赖工具,只需要导入servlet-api即可,如下:
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency>
根据上述的流程描述,接下来就是对web.xml进行配置:
<servlet> <servlet-name>appServlet</servlet-name> <servlet-class>com.wanGCw.cwframework.sevlet.CwDispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>application.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern> import java.lang.annotation.*; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface CwController { String value() default "";}
import java.lang.annotation.*; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface CwAutowried { String value() default "";}
import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface CwRequestMapping { String value() default "";}
import java.lang.annotation.*; @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface CwRequestParam { String value() default "";}
import java.lang.annotation.*; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface CwService { String value() default "";}
创建一个简单的控制层和业务层交互 Demo,加上自定的注解,具体注解的功能,后面赘述。
Controller.java
@CwController @CwRequestMapping("/demo")public class Controller { @CwAutowried private Service service; @CwRequestMapping("/query") public void query(httpservletRequest req, HttpServletResponse resp,@CwRequestParam("name") String name) throws IOException { resp.getWriter().write(service.query(name)); } @CwRequestMapping("/add") public void add(HttpServletRequest req, HttpServletResponse resp, @CwRequestParam("a") Integer a, @CwRequestParam("b") Integer b) throws IOException { resp.getWriter().write("a+b="+(a+b)); } }
Service.java
public interface Service { String query(String name); }
ServiceImpl.java
@CwServicepublic class ServiceImpl implements Service{ @Override public String query(String name) { return "I am "+name; } }
上面的controller层和service层已经把我们上述的自定注解都使用上去了,接下来我们开始手写spring的核心功能了,也就是实现CwDispatcherServlet.java这个HttpServlet的子类。
首先需要重写父类中的init方法,因为我们要在Init过程中实现出跟spring一样的效果。
理一理init()过程中都需要做哪些事情呢?整理了一下init()中主要需要以下几步操作
@Override public void init(ServletConfig config) { doLoadConfig(config.getInitParameter("contextConfigLocation")); doScanner(contextConfig.getProperty("scanPackage")); doInstance(); doAutowired(); initHandlerMapping(); }
第一步很简单,在类中定义一个Properties实例,用于存放Servlet初始化的配置文件。导入配置代码略过,IO常规读写即可。
private Properties contextConfig = new Properties();
第二步通过上面获取到的配置,取到需要扫描的包路径,然后在根据路径找到对应文件夹,做一个递归扫描即可。将扫描到的文件名去除后缀,保存到一个集合中,那么该集合就存放了包下所有类的类名。
String scanFileDir = contextConfig.getProperty("scanPackage"); private List<String> classNames = new ArrayList<String>(); String className = scanPackage + "." + file.getName().replace(".class", ""); classNames.add(className);
第三步就是IOC阶段,简而言之就是对上面集合中所有的类进行遍历,并且创建一个IOC容器,将带有@CwController和@CwService的类置于容器内。
private Map<String, Object> IOC = new HashMap<String, Object>(); for (String classNme : classNames){ if( 对加了 @CwController 注解的类进行初始化){ String beanName = toLowerFirstCase(clazz.getSimpleName()); IOC.put(beanName, clazz.newInstance()); } else if (对加了 @CwService 注解的类进行初始化){ IOC.put(beanName, instance); } else { //对于扫描到的没有注解的类,忽略初始化行为 continue; } }
第四步是DI操作,将IOC容器中需要赋值的实例属性进行赋值,即带有Autowired注解的实例属性。伪代码如下:
for(Map.Entry<String, Object> entry : IOC.entrySet()){ Field [] fields = entry.getValue().getClass().getDeclaredFields(); for (Field field : fields){ .... field.setAccessible(true); field.set(entry.getValue(), IOC.get(beanName)); } }
第五步要处理Controller层的Method与请求url的匹配关系,让请求能准确的请求到对应的url。篇幅问题,此处还是上传伪代码。
private List<Handler> handlerMapping = new ArrayList<Handler>(); for (Map.Entry<String, Object> entry : IOC.entrySet()){ Class<?> clazz = entry.getValue().getClass(); 定义一个url,由带有CwController的实例类上的@CwRequestMapping注解的值和Method上@CwRequestMapping注解的值组成 String regex = (url); Pattern pattern = Pattern.compile(regex); handlerMapping.add(new Handler(pattern,method)); }
到这里就基本完成了springmvc的初始化阶段,之后的工作就是重写一下CwDispatcherServlet.java父类的doGet()/doPost()方法。根据request中的URI和参数来执行对应的Method,并且响应结果。
handler.method.invoke(handler.controller, paramValues);
到此整个步骤就完成了,此时可以愉快的启动项目,并访问对应的url进行测试了。
根据上面Controller定义的方法可以知道其匹配的url为 : /demo/query 和 /demo/add,并且有使用@CwRequestParam注解定义了其各个参数的名称。
测试结果如下:
http://localhost:8080/spring/demo/query?name=James
http://localhost:8080/spring/demo/add?a=222222&b=444444
再来测试个url,是controller中没有声明出@CwRequestMapping注解的,看看结果。
http://localhost:8080/spring/demo/testNoUrl
SpringMVC是一个实现了MVC设计模式的轻量级web层框架,使用起来简单方便。
清晰的角色划分:
前端控制器(DispatcherServlet)
请求到处理器映射(HandlerMapping)
处理器适配器(HandlerAdapter)
视图解析器(ViewResolver)
处理器或页面控制器(Controller)
验证器( Validator)
命令对象(Command 请求参数绑定到的对象就叫命令对象)
表单对象(FORM Object 提供给表单展示和提交到的对象就叫表单对象)。
分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
可定制性, HandlerMapping、 ViewResolver 等能够非常简单的定制。
功能强大的数据验证、格式化、绑定机制。
利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
强大的 jsP 标签库,使 JSP 编写更容易。
还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。
与Struts2的对比:
共同点:都是基于MVC设计模式的表现层框架,底层实现都离不开原始的Servlet,处理请求的机制都是一个核心控制器;
区别:Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
Spring MVC 是基于方法设计的,而 Struts2 是基于类, Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
相比来说,SpringMVC已经全面超越了Struts2。
执行流程:
DispatcherServlet: 是整个springmvc框架的核心。
前端控制器/核心控制器:所有的请求和响应都由此控制器进行分配。
前端控制器的所有工作都是基于组件完成的:
三大组件:
HandlerMapping
: 它负责根据客户端的请求寻找对应的hadler,找到以后把寻找的handler返回给DispatcherServlet;
HandlerAdapter
:它负责执行寻找到的Handler的方法,方法执行完后将返回值给HandlerAdapter, HandlerAdapter将返回值传给DispatcherServlet;
ViewResolver
:它根据DispatcherServlet指定的返回结果寻找对应的页面,找到后将结果返回给DispatcherServlet。
DispatcherServlet
负责最终的响应,默认是转发的操作。
执行流程图:
以上是“如何使用springmvc”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!
--结束END--
本文标题: 如何使用springmvc
本文链接: https://www.lsjlt.com/news/304422.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0