MyTest 注解:
注解类
package day54.anno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
应用类:
package day54.demo;
import day54.anno.MyTest;
import day54.test.Test01;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
- 让@MyTest注解生效,起作用
*/
public class Demo02 {
public static void main(String[] args) {
//使用反射,扫描Test01类里面有那些方法有@MyTest注解
//如果有@MyTest注解,就将他执行
//如果没有@MyTest注解,不做任何处理
//1.获取Test01类对应的Class对象
Class<Test01> clazz = Test01.class;
//2.获取Test01类下的所有方法对象
Method[] methods = clazz.getMethods();
Arrays.stream(methods).forEach(method -> {
//method 就是单个方法对象
//3.判断方法上是否有@MyTest注解
boolean present = method.isAnnotationPresent(MyTest.class);
if(present){
//方法上有@MyTest注解,执行方法
try {
method.invoke(clazz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}else{
//方法上没有@MyTest注解,不需要执行操作
}
});
}
}
测试类:
package day54.test;
import day54.anno.MyTest;
public class Test01 {
public void test01(){
System.out.println("test01");
}
@MyTest
public void test02(){
System.out.println("test02");
}
@MyTest
public void test03(){
System.out.println("test03");
}
}
运行效果:
利用注解做配置文件
jdbcinfo 注解
注解类:
package day54.anno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface JDBCInfo {
String driverClass() default "com.mysql.jdbc.Driver";
String jdbcurl() default "jdbc:mysql://localhost:3306/companydb";
String user() default "root";
String password() default "123456";
}
JDBCUtils 类
package day54.util;
import day54.anno.JDBCInfo;
import java.sql.*;
/**
-
JDBC工具类
-
使用注解 替换 properties 配置文件
*/
@JDBCInfo
public class JDBCUtils {private static final String DRIVERCLASS;
private static final String JDBCURL;
private static final String USER;
private static final String PASSWORD;static {
Class clazz = JDBCUtils.class;
boolean present = clazz.isAnnotationPresent(JDBCInfo.class);
if(present){
//JDBCUtils 类上有 @JDBCInfo注解, 获取该注解
JDBCInfo jdbcinfo = clazz.getAnnotation(JDBCInfo.class);
//从@JDBCInfo 注解中获取 相对的配置
DRIVERCLASS = jdbcinfo.driverClass();
JDBCURL=jdbcinfo.jdbcurl();
USER = jdbcinfo.user();
PASSWORD =jdbcinfo.password();
}else{
//没有注解的情况 从properties中获取
DRIVERCLASS = “”;
JDBCURL="";
USER = “”;
PASSWORD ="";
}}
public static void loadDriver() throws Exception {
Class.forName(DRIVERCLASS);
}public static Connection getConnection() throws Exception {
return DriverManager.getConnection(JDBCURL,USER,PASSWORD);
}public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;//为了Connection 对象及时被jvm回收
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
statement = null;
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
resultSet = null;}
}
应用类:
package day54.demo;
import day54.util.JDBCUtils;
import sun.applet.AppletResourceLoader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
-
自定义注解 @JDBCInfo
*/
public class Demo03 {public static void main(String[] args) throws Exception {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = JDBCUtils.getConnection();String sql = "select * from emp"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while(resultSet.next()){ int id = resultSet.getInt(1); String name = resultSet.getString(2); String address = resultSet.getString(3); String sex = resultSet.getString(4); System.out.println(id+"\t"+name+"\t"+address+"\t"+sex); } resultSet.close(); preparedStatement.close(); connection.close();
}
}
运行效果:
注解增强方法 SystemLog 注解
利用装饰者模式
UserDao 接口类:
package day54.dao;
import day54.anno.SystemLog;
public interface UserDao {
void addUser() throws Exception;
//带有注解的方法 会进行日志记录!
@SystemLog(className = "day54.dao.UserDao",methodName = "deleteUser")
void deleteUser() throws Exception;
void updateUser() throws Exception;
}
UserDaoWrapper装饰类:
package day54.dao;
import day54.anno.SystemLog;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
public class UserDaoWrapper implements UserDao {
private UserDao userDao;
public UserDaoWrapper(UserDao userDao){
this.userDao=userDao;
}
@Override
public void addUser() throws Exception {
System.out.println("UserDaoImpl addUser");
printLog("addUser");
}
@Override
public void deleteUser() throws Exception {
System.out.println("UserDaoImpl deleteUser");
printLog("deleteUser");
}
@Override
public void updateUser() throws Exception {
System.out.println("UserDaoImpl updateUser");
printLog("updateUser");
}
/**
* 日志记录
*/
private void printLog(String methodName) throws Exception {
// 判断接口上对应方法中是不是有@SystemLog注解
//获取UserDao 接口实现子类的Class对象
Class<? extends UserDao> sonClazz = userDao.getClass();
//获取UserDao接口的Class对象
Class<?>[] interfaces = sonClazz.getInterfaces();
Class<?> fatherClazz = interfaces[0];
//获取接口中对应的方法对象
Method method = fatherClazz.getMethod(methodName);
if(method !=null){
//判断方法上是否有注解
boolean present = method.isAnnotationPresent(SystemLog.class);
if(present){
//方法有注解, 打印日志
SimpleDateFormat format= new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
String currentTimeStr =format.format(new Date());
SystemLog systemLog = method.getAnnotation(SystemLog.class);
String className =systemLog.className();
String methodName1 = systemLog.methodName();
System.out.println( currentTimeStr +"---" + className +"---" + methodName1+"()方法运行了" );
}else{
//方法没有注解,不做处理
}
}
}
}
注解类 SystemLog 类
package day54.anno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLog {
String className(); //记录类名
String methodName(); //记录方法名
}
应用类:
package day54.demo;
import day54.dao.UserDaoImpl;
import day54.dao.UserDaoWrapper;
public class Demo04 {
//需求:
//在UserDao接口中的方法上
// 如果有使用@SystemLog注解,那么就进行日志记录
//如果没有,就不进行日志记录
//日志内容:2020年4月15日
public static void main(String[] args) throws Exception {
UserDaoWrapper userDaoWrapper = new UserDaoWrapper(new UserDaoImpl());
userDaoWrapper.deleteUser();
//存在的问题:
//装饰类中的每个方法都需要调用printLog方法,由装饰者设计模式缺点决定的
}
}
运行效果:
只有deleteUser增强
利用动态代理 解决注解增强方法问题:
应用类:
package day54.demo;
import day54.anno.SystemLog;
import day54.dao.UserDao;
import day54.dao.UserDaoImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
-
反射 注解 设计模式案例之动态代理
*/
public class Demo05 {public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
UserDao userDaoProxy = null;
userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取到接口中方法对象
//装饰者模式步骤
//先获取实现子类的Class对象
//再获取到接口的Class对象 – userDao.getClass().getInterfaces()
//再获取到接口中的方法对象 – Method method//动态模式 : //先获取到接口的Class对象 -- userDao.getClass().getInterfaces() //再获取到接口中的方法对象 -- Method method //method 就是接口中的方法对象 Object returnValue = null; if(method !=null){ //判断注解是不是 参数 的类型 boolean present = method.isAnnotationPresent(SystemLog.class); if(present){ //如果有注解, 执行原有功能 打印日志 returnValue = method.invoke(userDao,args); SimpleDateFormat format= new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss"); String currentTimeStr =format.format(new Date()); //拿到 注解 SystemLog systemLog = method.getAnnotation(SystemLog.class); String className =systemLog.className(); String methodName1 = systemLog.methodName(); System.out.println( currentTimeStr +"---" + className +"---" + methodName1+"()方法运行了" ); }else{ //如果没有注解 只需要原有功能 不需要打印日志 returnValue= method.invoke(userDao,args); } } return returnValue; } }); try { userDaoProxy.deleteUser(); } catch (Exception e) { e.printStackTrace(); }
}
}
运行效果:
Servlet 知识:
response 对象 操作响应头,响应行
重定向:从一个资源跳转到另一个资源
定时跳转: