SpringMvc注解开发
1.四大注解的定义
(1)Controller注解:该注解使用在一个类上面,参数为value,值为访问该controller的名称,默认为空,如果为空
则值为该controller类名的首字母小写的值。代码如下:
@Documented
@Target(ElementType.TYPE)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
String value() default "";
}
(2)Service注解:该注解使用在一个类上面(使用在接口的实现类上面),参数为value,值为该service的名称。默认为空,
如果为空则值为该service的类名的首字母小写的值。代码如下:
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
String value() default "";
}
(3)RequestMapping注解:该注解定义使用在一个方法上面,参数为value,值为该方法的访问名称,默认为空,如果
为空,则值为该方法的方法名首字母小写的值。代码如下:
@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value() default "";
}
(4)Autowired注解:该注解定义使用到类的成员变量上面,没有参数,表示该变量字段注入值。代码如下:
@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired { }
2.包扫描方法说明
当我们获取到一个指定的包名时,我们要去获取该包路径下面的所有文件,如果该文件为文件夹,在递归调用该方法,直到
获取到指定包路径下面的所有文件,判读文件是否以class结尾,如果文件以class结尾,则将该文件的完整路径(包名+文件名)
保存到list中。
(1)先将包名中的所以有"."替换为"/",得到包的路径。
private String replacePackageName(String packageName){
return packageName.replaceAll("\\.", "/");
}
(2)递归调用扫描方法,获取所有文件。
private void scanPackage(String packageName){
//替换包名中的 .
String packageName1 = replacePackageName(packageName);
//获取当前的统一资源定位符
URL url = this.getClass().getClassLoader().getResource(packageName1);
//获取此URL的文件名
String pathFile= url.getFile();
//通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例
File file = new File(pathFile);
//返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。
String[] files = file.list();
for(String filePath : files){
//根据目录名称和文件名称创建新的File对象
File eachFile = new File(pathFile+"/"+filePath);
if(eachFile.isDirectory()){
//如果为文件夹,则将新的名称作为包名,再次调用该方法。
scanPackage(packageName+"."+eachFile.getName());
}else{
//判断文件的扩展名是否为class,如果是,则将该文件的包名和文件名一起保存到集合中。
if(getFileExtendName(eachFile.getName()).equals("class"))
packageNames.add(packageName+"."+eachFile.getName());
continue;
}
}
}
private String getFileExtendName(String fileName){
//判断传入的文件名是否为空,或者长度是否小于等于0
if(fileName == null ||fileName.length() <=0)
return null;
//获取文件中最后一个 . 出现的地方的下标
int lastIndex = fileName.lastIndexOf(".");
//判断下标是否为正常的值
if(lastIndex > -1 && lastIndex <(fileName.length()-1))
//截取文件的扩展名
return fileName.substring(lastIndex+1);
return fileName;
}
3.实例化第二步扫描到的所有类中配有controller和service注解的类
private void saveClass() throws Exception{
//判断集合是否为空
if(packageNames.size() <=0){
return;
}
for(String pkn:packageNames){
//根据类的全限定名通过反射获取指定类的class对象
Class<?> object = Class.forName(pkn.replace(".class", "").trim());
//判断该类是否有controller注解
if(object.isAnnotationPresent(Controller.class)){
//实例化该class的类对象
Object instance = object.newInstance();
//获取controller注解的对象
Controller controller = object.getAnnotation(Controller.class);
//获取该注解的参数的值
String key = controller.value();
//判断注解的值是否为空
if(key.equals("")){
//获取该类的类名首字母小写作为值。
key=object.getSimpleName().substring(0, 1).toLowerCase()+object.getSimpleName().substring(1);
}
//将类的名称和类的实例放到map对象中
classMap.put(key, instance);
//判断该对象是否有service注解
}else if(object.isAnnotationPresent(Service.class)){
//获取该类的实例
Object instance = object.newInstance();
//获取service的对象实例
Service service = object.getAnnotation(Service.class);
//获取注解的值
String key = service.value();
//判断注解的值是否为空
if(key.equals("")){
//获取该类的类名首字母小写作为值。
key=object.getSimpleName().substring(0, 1).toLowerCase()+object.getSimpleName().substring(1);
}
//将类的名称和类的实例放到map对象中
classMap.put(key, instance);
}else{
continue;
}
}
}
4.根据所有的类对象获取方法
private void handlerMap(){
//判断类的集合是否为空
if(classMap.size() <=0){
return;
}
//遍历该map对象
for (Map.Entry<String,Object> entry : classMap.entrySet()) {
//获取该类是否有controller注解
if(entry.getValue().getClass().isAnnotationPresent(Controller.class)){
//获取controller注解对象
Controller controller = entry.getValue().getClass().getAnnotation(Controller.class);
//获取controller注解的值
String value = controller.value();
//判断注解的值是否为空
if(value.equals("")){
//获取该类的类名首字母小写作为值。
value=entry.getValue().getClass().getSimpleName().substring(0, 1).toLowerCase()+entry.getValue().getClass().getSimpleName().substring(1);
}
//反射获取该类下面的所有方法
Method[] methods = entry.getValue().getClass().getMethods();
for (Method method : methods) {
//判断该方法是否有RequestMapping注解
if(method.isAnnotationPresent(RequestMapping.class)){
//获取RequestMapping对象
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
//获取注解的值
String rvalue = requestMapping.value();
//判断注解的值是否为空
if(rvalue.equals("")){
//获取该类的类名首字母小写作为值。
rvalue=method.getClass().getSimpleName().substring(0, 1).toLowerCase()+method.getClass().getSimpleName().substring(1);
}
//将controller的名称和方法的名称保存到集合中
methodMap.put("/"+value+rvalue, method);
}else{
continue;
}
}
}else{
continue;
}
}
}
5.实例化类中的有Autowired注解的成员变量
private void ioc(){
//判断集合是否为空
if(classMap.size() <=0){
return;
}
//变量所有的类
for (Map.Entry<String, Object> entry : classMap.entrySet()) {
//获取本类下面所有的成员变量
Field[] fileds =entry.getValue().getClass().getDeclaredFields();
for (Field field : fileds) {
//设置该成员变量可以编辑
field.setAccessible(true);
//判断该成员对象是否有Autowired注解
if(field.isAnnotationPresent(Autowired.class)){
try {
//设置该成员变量可以编辑
field.setAccessible(true);
//获取包名
String packString= field.getType().getPackage().getName();
//获取实现类的类名
String className= field.getType().getSimpleName()+"Impl";
//反射该类对象
Class<?> obj = Class.forName(packString+".impl."+className);
String value="";
//判断该类是否有controller注解
if(obj.isAnnotationPresent(Controller.class)){
//获取controller的值
value= obj.getAnnotation(Controller.class).value();
if(value.equals("")){
//获取该类的类名首字母小写作为值。
value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
}
//判断该类是否有service注解
}else if(obj.isAnnotationPresent(Service.class)){
//获取service的值
value= obj.getAnnotation(Service.class).value();
if(value.equals("")){
//获取该类的类名首字母小写作为值。
value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
}
}
//给成员变量赋值实例
field.set(entry.getValue(), classMap.get(value));
} catch (IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
6.写前端控制器
前端控制器是一个servlet,所有的路径访问都提交到该servlet,由该servlet负责转发。在该servlet的初始化init方法中执行上面步骤。
然后在post方法中拦截请求。获取地址,进行转发。
private void ioc(){
//判断集合是否为空
if(classMap.size() <=0){
return;
}
//变量所有的类
for (Map.Entry<String, Object> entry : classMap.entrySet()) {
//获取本类下面所有的成员变量
Field[] fileds =entry.getValue().getClass().getDeclaredFields();
for (Field field : fileds) {
//设置该成员变量可以编辑
field.setAccessible(true);
//判断该成员对象是否有Autowired注解
if(field.isAnnotationPresent(Autowired.class)){
try {
//设置该成员变量可以编辑
field.setAccessible(true);
//获取包名
String packString= field.getType().getPackage().getName();
//获取实现类的类名
String className= field.getType().getSimpleName()+"Impl";
//反射该类对象
Class<?> obj = Class.forName(packString+".impl."+className);
String value="";
//判断该类是否有controller注解
if(obj.isAnnotationPresent(Controller.class)){
//获取controller的值
value= obj.getAnnotation(Controller.class).value();
if(value.equals("")){
//获取该类的类名首字母小写作为值。
value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
}
//判断该类是否有service注解
}else if(obj.isAnnotationPresent(Service.class)){
//获取service的值
value= obj.getAnnotation(Service.class).value();
if(value.equals("")){
//获取该类的类名首字母小写作为值。
value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
}
}
//给成员变量赋值实例
field.set(entry.getValue(), classMap.get(value));
} catch (IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
7.配置web.xml文件
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>com.jack.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>configxml</param-name>
<param-value>com/jack/test/minimvc.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
SpringMvc注解开发的更多相关文章
- SpringMVC注解开发初步
一.(补充)视图解析器---XmlViewResolver 作用:分离配置信息. 在视图解析器---BeanNameViewResolver的基础之上进行扩充,新建一个myView.xml分离信息 在 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——S ...
- springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定
springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...
- springmvc学习笔记(12)-springmvc注解开发之包装类型參数绑定
springmvc学习笔记(12)-springmvc注解开发之包装类型參数绑定 标签: springmvc springmvc学习笔记12-springmvc注解开发之包装类型參数绑定 需求 实现方 ...
- springmvc学习笔记(10)-springmvc注解开发之商品改动功能
springmvc学习笔记(10)-springmvc注解开发之商品改动功能 标签: springmvc springmvc学习笔记10-springmvc注解开发之商品改动功能 需求 开发mappe ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇)
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7065294.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十四)--S ...
- 2.SpringMVC注解开发
1.创建SpringMVC项目 配置web.xml <?xml version="1.0" encoding="UTF-8"?> <web-a ...
- springMVC注解初步
一.(补充)视图解析器---XmlViewResolver 作用:分离配置信息. 在视图解析器---BeanNameViewResolver的基础之上进行扩充,新建一个myView.xml分离信息 在 ...
- SpringMVC-Mybatis整合和注解开发
SpringMVC-Mybatis整合和注解开发SpringMVC-Mybatis整合整合的思路在mybatis和spring整合的基础上 添加springmvc.spring要管理springmvc ...
随机推荐
- UniGui之锱铢积累(仔细看这个文件)
http://www.doc88.com/p-4022977294324.html 这个是Word文档
- c3p0----获取不到链接
最近别人的项目,因为经常获取不到链接出错,我好奇也就跟着摆弄了一把,使用的插件是:c3p0+spring+ibatiS,当然事务管理部分也配置上了配置如下: <bean id="dat ...
- VS2012 中不能安装ARCGIS 10.0 SDK的解决方法
问题描述 在ARCGIS 安装SDK时 就会出错 原因是ARCGIS SDK 10.0只能在VS2010中安装,因为我本机是安的VS2012所以安装不成功. 解决方法 一,在注册表中HKE ...
- vsftpd 常见问题
一.vsftp服务能开启却连接不上的解决办法: 用虚拟机装了centos,vsftp是用centos自带的.启动vsftd服务后却一直连不上,原因是被防火墙给挡了. 查看防火墙状态:/etc/init ...
- SignalR简单封装
需求:Asp.Net MVC 开发客户端,实现与服务器端实时通信. 众所周知,Web开发是基于http的请求响应模型,每次刷新都需要客户端(浏览器)主动发起请求,那么,这个问题怎么解?Asp.Net ...
- [转载]未能从程序集“System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”中加载类型“System.Web.WebPages.DisplayModeProvider”
转载于http://bkcoding.cn/post_1210.html 使用vs2010开发asp.net mvc程序时,出现 未能从程序集“System.Web.WebPages, Version ...
- NetCore入门篇:(十二)在IIS中部署Net Core程序
一.简介 微软已经为net在iis中的部署提供了良好的支持,在IIS中部署NetCore是一件很容易的事. 二.在IIS中部署Net Core程序 1.微软官方文档有详细说明.进入 2.如果你已经熟悉 ...
- reids 安装
第一步:在VMware中安装CentOS(参考Linux教程中的安装虚拟机) 第二步:在Linux下安装gcc环境 [root@hadoop ~]#yum install gcc-c++ 第三步:将下 ...
- 如何把OpenWrt安装到PC?
前言 什么是openwrt? 它是一个适用于路由器的Linux发行版.和其他Linux发行版一样,它也内置了包管理工具,你可以从一个软件仓库里直接安装软件.OpenWrt可以用在所有需要嵌入式Linu ...
- Python爬虫入门教程 65-100 爬虫与反爬虫的修罗场,点评网站,字体反爬之三
爬虫与反爬虫的修罗场 哪种平台最吸引爬虫爱好者,当然是社区类的,那里容易产生原生态,高质量的数据啊, 你看微博,知乎,豆瓣爬的不亦乐乎. 评论也是产生内容的好地方 生活类点评网站 旅游类点评网站 音乐 ...