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 ...
随机推荐
- function [eigf,eigv,dof]=laplaceeig(node,elem,problem)
function [eigf,eigv,dof]=laplaceeig(node,elem,problem) % -boundary eigenvalue problem % problem='0-b ...
- 破解Oracle ERP密码
前提:你有apps的数据库账户,想知道某个用户的密码,因为fnd_user中的密码为加密的,所以无法看懂,你可以尝试用下边的方式来查看用户密码. SQL> desc fnd_user; Name ...
- Win10下安装msi程序包时报2503、2502错误问题及其解决办法
Win10系统下安装TortoiseSvn.Node.js时(.msi后缀的安装文件),在点击安装时老是提示2503,2502错误,因此无法安装上. 搜索了下一般都提到是权限不够引起的该问题.但是右键 ...
- Mongodb 与 SQL 语句对照表
In addition to the charts that follow, you might want to consider the Frequently Asked Questions sec ...
- java 执行sql文件
# 背景 用例执行完毕,期望回滚数据,因此希望执行sql来回滚数据 # 步骤 直接show代码,借助的是mybatis的ScriptRunner /** * 执行xx库下的表备份脚本 * * @par ...
- Java异常处理机制的秘密
一.结论 这些结论你可能从未听说过,但其正确性是毋庸置疑的,不妨先看看: 1.catch中throw不一定能抛回到上一层,因为finally中的return会抑制这个throw 2.finally中t ...
- 队列的实现——java
同样实现方法有两种: 1. 数组的实现,可以存储任意类型的数据(略): 2. Java的 Collection集合 中自带的"队列"(LinkedList)的示例: import ...
- PARSER_JS_PRECISION_RANGE_EXCEEDED 错误
{ [Error: parseLengthCodedNumber: JS precision range exceeded, number is >= 53 bit: "3037620 ...
- RabbitMQ Java实例
引入RabbitMQ的jar包 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amq ...
- java解压缩.gz .zip .tar.gz等格式的压缩包方法总结
1..gz文件是linux下常见的压缩格式.使用 java.util.zip.GZIPInputStream即可,压缩是 java.util.zip.GZIPOutputStream public s ...