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 ...
随机推荐
- 一个CSV文件解析类
import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import java.ut ...
- dotNet core 应用部署centos
---恢复内容开始--- 阅读目录 需要安装的插件以及支撑架构 安装dotnetSDK 安装jexus 安装supervisord 遇到问题汇总 注意事项.扩展延伸 需要安装的插件以及支撑架构 1.d ...
- ABP框架入门踩坑-添加实体
添加实体 ABP踩坑记录-目录 这里我以问答模块为例,记录一下我在创建实体类过程中碰到的一些坑. 审计属性 具体什么是审计属性我这里就不再介绍了,大家可以参考官方文档. 这里我是通过继承定义好的基类来 ...
- Vue 进阶之路(十)
之前的文章介绍了 vue 的组件化,本章我们来看一下 vue 中组件的原生事件. <!DOCTYPE html> <html lang="en"> < ...
- 2017 NAIPC A:Pieces of Parentheses
my team solve the problem in the contest with similar ideathis is a more deep analysis The main idea ...
- 四,memcached的机制
memcached机制: 1,基于c/s架构,协议简单. (1)c/s架构,此时memcached为服务端,我们可以使用如PHP,c/c++等程序连接memcached服务器. (2)memcache ...
- Educational Codeforces Round 25 B. Five-In-a-Row
题目链接:http://codeforces.com/contest/825/problem/B B. Five-In-a-Row time limit per test 1 second memor ...
- win8 下 intellij idea 13 中文输入覆盖的问题
网上的解决方案好啰嗦,精简下如下: 设置环境变量 64位:IDEA_JDK_64 32位:IDEA_JDK 设置的value必须是JDK1.6(IDEA自带1.7版本有问题),和平时设置的JAVA_H ...
- 读DEDECMS找后台目录有感
本文作者:红日安全团队——Mochazz 早上看了先知论坛的这篇文章:解决DEDECMS历史难题–找后台目录 不得不说作者思路确实巧妙,作者巧妙的利用了Windows FindFirstFile和织梦 ...
- canvas 绘制圆形进度条
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...