SSM框架(四)模仿sping-mvc自定义一个框架

一、自定义框架demo

(一)主要目录结构

DispatcherServlet:路径转发,controller:控制类)
在这里插入图片描述

(二)web.xml配置我们的路径

在这里插入图片描述

  • web.xml完整代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app 
           xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
           version="3.1" metadata-complete="true">
        <display-name>Archetype Created Web Application</display-name>
        <!-- 声明Spring的主配置文件 -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:config/*.xml</param-value>
    	</context-param>
    	<!-- 配置Spring的监听器 -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	<!-- 解析乱码 -->
    	<filter>
    		<filter-name>characterEncodingFilter</filter-name>
    		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    		<init-param>
    			<param-name>encoding</param-name>
    			<param-value>UTF-8</param-value>
    		</init-param>
    		<init-param>
    			<param-name>forceEncoding</param-name>
    			<param-value>true</param-value>
    		</init-param>
    	</filter>
    	<filter-mapping>
    		<filter-name>characterEncodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    	
    	<!-- 配置SpringMVC后台 .do -->
    	<!-- servlet>
    		<servlet-name>SpringMVC</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:config/spring-mvc.xml</param-value>
    		</init-param>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>SpringMVC</servlet-name>
    		<url-pattern>*.do</url-pattern>
    	</servlet-mapping-->
    	<!-- 配置MyMVC *.do -->
    	<servlet>
    		<servlet-name>mymvc</servlet-name>
    		<servlet-class>com.cungudafa.mymvc.servlet.MyDispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>basePackage</param-name>
    			<param-value>com.cungudafa.mymvc.controller</param-value>
    		</init-param>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>mymvc</servlet-name>
    		<url-pattern>*.do</url-pattern>
    	</servlet-mapping>
    	
    </web-app>
    
  • 自定义转发器MyDispatcherServlet.java:

    package com.cungudafa.mymvc.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * MyMVC框架的核心Servlet
     * @author Administrator
     *
     */
    public class MyDispatcherServlet extends HttpServlet{
    	
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		doPost(req, resp);//使用同一套业务代码处理请求
    	}
    	
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//测试 
    		System.out.println("MyDispatcherServlet doPost……");
    	}
    }
    

(三)主要代码

  • 主要目录
    运行期间通过动态代理获得接口的代理对象,这里定义了三个接口:MyController、MyRequestMapping、MyResponseBody
    在这里插入图片描述在这里插入图片描述

  • 1 MyController.java:

    package com.cungudafa.mymvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * Controller注解,定义某个类为控制器
     * @author Administrator
     *
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyController {
    
    }
    
    

    2 MyRequestMapping.java:

    package com.cungudafa.mymvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * RequestMapping注解,映射请求到某个类/方法
     * @author Administrator
     *
     */
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyRequestMapping {
    	public String value();
    }
    

    3 MyResponseBody.java

    package com.cungudafa.mymvc.annotation;
    
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * RequestMapping注解,映射请求到某个类/方法
     * @author Administrator
     *
     */
    @Target({ElementType.TYPE_PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyResponseBody {
    	public String value();
    }
    

(四)测试结果

1、在之前的基础上任意输入一个 .do : http://localhost:8080/SpingMVC01/files.do
在这里插入图片描述
2、控制台返回
在这里插入图片描述
配置成功!



二、JavaSE 高级部分之注解

(一)什么是注解(Annotation )?

Annotation :注解、标释Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 JDK5 开始添加到 Java 的。

在这里插入图片描述 在这里插入图片描述
在这里插入图片描述

(二) 常见注解

(1)java类常用注解

在这里插入图片描述在这里插入图片描述

(2)Sping中最常用注解

常用注解Part1:
@Controller & @RequestMapping

  • @Controller : 获得类名、方法名
  • @RequestMapping :获得参数
    -》 下面用一个test示例演示以上两个注解功能:
    在这里插入图片描述
    -》 定义一个father类和一个son类,写main函数测试结果如下:
    在这里插入图片描述在这里插入图片描述
    通过controller可以获得son中里面包含的类名以及方法名
    在这里插入图片描述
    通过son中定义的@RequestMapping(value="/xxxxxxxxxx")可以获得value
    在这里插入图片描述

常用注解Part2:
@Retention&@Target&@Inherited

  • @Retention : 元注解 --生命周期在运行时
  • @Target :注解可以用在类/接口,方法、字段上
  • @Inherited :子类继承注解
    -》 下面用一个myannotation示例演示以上三种功能:
    在这里插入图片描述
    -》public @interface MyAnnotation接口里定义了三类注解:
    在这里插入图片描述
    -》 定义一个father类和一个son类,写main函数测试结果如下:
    (父类:每个元素都引用了MyAnnotation接口、son类:仅仅继承)
    在这里插入图片描述在这里插入图片描述
    通过@Retention 运行时判断有MyAnnotation标签、@Target注解可以用在类/接口,方法、字段
    在这里插入图片描述
    判断@Inherited子类是否继承注解
    在这里插入图片描述

(3)Sping框架通用SQLGenerator.java

目的:获得sql查询语句:

select * from user_info where 1=1 and user_name = 'zhangsan' and user_id = 10001
在这里插入图片描述
-》 下面用一个demo示例演示以上三种功能:
在这里插入图片描述
-》ColumnTable两个接口里定义了2类注解:

  • @Retention : 元注解 --生命周期在运行时
  • @Target :注解可以用在类/接口,方法、字段上
    在这里插入图片描述在这里插入图片描述

-》 定义一个UserInfo类和一个student类,写main函数测试结果如下:
(运行时类引用了Table接口、每个元素与(数据库)这里我们与Column相联系)在这里插入图片描述在这里插入图片描述
-》 定义SQLGenerator.java

  • 模拟数据库请求操作时,对sql语句变量的控制
    select * from user_info where 1=1 and user_name = 'zhangsan' and user_id = 10001
    select * from 表名 where 直接写入条件 and 查询关键词1 = '字符串' and 查询关键词2 = 数字
    package com.cungudafa.annotation.demo;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 生成SQL
     * @author Administrator
     *
     */
    public class SQLGenerator {
    	
    	public static String createInsertSql(Object o){
    		return null;//待补充
    	}
    	
    	public static String createDeleteSql(Object o){
    		return null;
    	}
    	
    	public static String createUpdateSql(Object o){
    		return null;
    	}
    	
    	/**
    	 * 
    	 * @param o->UserInfo(id,name)
    	 * @return select * from user_info where user_id = ? and user_name = ?;
    	 * @throws InvocationTargetException 
    	 * @throws IllegalArgumentException 
    	 * @throws IllegalAccessException 
    	 * @throws SecurityException 
    	 * @throws NoSuchFieldException 
    	 */
    	public static String createSelectSql(Object o) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException, SecurityException{
    		
    		//获取传入对象的运行时类
    		Class c = o.getClass();
    		//判断该类是否有@Table注解
    		if(c.isAnnotationPresent(Table.class)){
    			String sql = "select * from ";
    			Table t = (Table) c.getAnnotation(Table.class);
    			String tableName = t.value();
    			sql = sql + tableName + " where 1=1 ";
    			//获取所有的get方法
    			Method[] methods = c.getDeclaredMethods();
    			List<Method> getMethods = new ArrayList<>();
    			for(Method method : methods){
    				if(method.getName().startsWith("get")){
    					getMethods.add(method);
    				}
    			}
    			
    			//遍历get方法
    			for(Method method : getMethods){
    				Object value = method.invoke(o);
    				if(value != null){
    					String methodName = method.getName();//getUserId/getUserName
    					System.out.println("methodName = " + methodName);
    					//getUserId-->userId
    					String fieldName = methodName.replaceAll("get", "");//UserId
    					fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);//UserId->userId
    					System.out.println("fieldName = " + fieldName);
    					//获得字段
    					Field field = c.getDeclaredField(fieldName);
    					System.out.println("field = " + field);
    					//判断字段上是否有Column注解
    					if(field.isAnnotationPresent(Column.class)){
    						//获得字段上的Column注解
    						Column col = field.getAnnotation(Column.class);
    						//获得注解的value值,作为列名
    						String columnName = col.value();
    						if(value instanceof Integer){//区分id学号String转int(数据库为int)
    							sql = sql + "and " + columnName + " = " + String.valueOf(value) + " ";
    						}else{
    							sql = sql + "and " + columnName + " = '" + String.valueOf(value) + "' ";
    						}
    					}
    				}
    			}
    			return sql;
    		}else{
    			return null;
    		}
    	}
    }
    

-》 测试结果:(两张表都可以通用SQLGenerator框架)

sql = select * from user_info where 1=1 and user_name = ‘zhangsan’ and user_id = 10001
sql = select * from t_student where 1=1 and t_stuid = 10002 and t_stuname = ‘李四’ and t_stunumber = ‘102001203103’

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值