今日内容
零、 复习昨日
一、注解
二、改造项目
三、请求转发
四、重定向
零、 复习昨日
一、注解(Annotation)
注解,又称为注释.它是给程序看的注释.
JDK1.5后才出现的,作用是为了提高开发效率的,如何做到?(一个注解可以简化很多很多代码…)
常见注解: @Override
1.1 自定义注解
1.1.1 新建注解文件
public @interface MyLog {
}
1.1.2 注解加元注解
- 元注解是给注解加的注解
- @Target @Retention @Documented @Inherited
@Target
定义自定义注解目标,即注解能作用哪些地方
@Retention
指定注解的保留策略,即注解在什么时期生效.
1.1.3 设置参数
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
/**
* 注解的参数,写法是
* 数据类型 参数名();
* 参数名设置成value的话,用注解时可以省略
* @注解(值)
* 如果设置成别的名字,使用时参数名不能省略必须是
* @注解(参数名1=值)
* 一旦注解参数超过2个,使用时全部都有加上参数名
* @注解(参数名1=值,参数名2=值)
*/
int value();
String m2() default "";
double m3() default 0.0;
}
1.1.4 使用注解
在需要的地方之间加注解即可
1.2 利用反射读取注解内容
模拟UserDao
public class UserDao {
@MyLog("查询用户")
@MyAnno
public void selectOne() {}
@MyLog("查询全部用户")
public void selectAll() {}
@MyLog("删除用户")
public void deleteOne() {}
}
测试,反射读取注解
public class TestReflact {
public static void main(String[] args) throws Exception {
Class<?> userDaoClass = Class.forName("com.qf.annotation.UserDao");
Method[] methods = userDaoClass.getDeclaredMethods( );
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
// 获得方法上的注解
MyLog log = method.getAnnotation(MyLog.class);
String value = log.value( );
System.out.println("log = "+value );
/**
* 将来可以再获得请求ip,用户名,等信息,配合日志信息插入到数据库
* 记录到日志表中
*/
}
}
}
二、注解改造项目
问题:
每个请求映射,都需要写web.xml的映射
解决:
提供了注解方案
实现:
ps: 同一映射,web.xml配置和注解不能共存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1g4CjAjD-1685257229055)(C:/Users/qiush/AppData/Roaming/Typora/typora-user-images/image-20230524111411581.png)]
三、idea配置热部署
换句话就是,可以实现修改代码不重启服务器.
设置idea的Tomcat为这样
设置完之后,修改前端页面,只需要鼠标离开代码,idea就会自动更新前端代码
设置完之后,修改后端代码,只需要点击下面地方,就可以更新服务器中的代码
四、请求转发
3.1 现有问题
- 响应的代码与接收请求代码在一起
- 查询全部的代码与登录的代码在一起
- 这也没有遵循单一职责,不便于后期维护
3.2 解决
- 将代码拆开
- 登录请求完之后,再单独设计个Servlet去做查询全部
- 查询全部之后再单独的做响应
- 这就是请求转发
3.3 演示
3.3.1 请求转发跳转servlet
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("1 接收请求" );
System.out.println("2 调用业务层处理数据" );
// 查询全部
/**
* 请求转发,
* 是服务器内部动作
*/
// RequestDispatcher rd = req.getRequestDispatcher("/list");
// rd.forward(req,resp);
// 一般会简写
req.getRequestDispatcher("/list").forward(req,resp);
System.out.println("5 登录结束...." );
}
}
@WebServlet("/list")
public class ListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("3查询全部数据..." );
System.out.println("4 查询全部响应" );
}
}
3.3.2 请求转发跳转页面
@WebServlet("/page")
public class PageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 请求转发是服务器动作,从服务器根路径出发
* 服务器资源的根路径:/webapp/
* a.html b.jsp 都定义在/webapp/下
* c.jsp在 /webapp/WEB-INF/下,所以请求转发时需要加上WEB-INF
*/
// req.getRequestDispatcher("/a.html").forward(req,resp);
// req.getRequestDispatcher("/b.jsp").forward(req,resp);
req.getRequestDispatcher("/WEB-INF/c.jsp").forward(req,resp);
}
}
3.4 请求域
- 在两个servlet请求转发时,会存在A类的数据需要传递给B类
- 此时就需要使用请求对象的请求域功能
- req.setAttribute(key,value),这样就可以将数据存储在请求对象
- 再另外一个servlet使用请求对象取出值req.getAttribute(“key”)
3.5 特点
- 请求转发地址栏不变,这是一次请求
- 请求转发是服务器内部行为
- 当做域对象使用,即相当于容器,可以装载数据
- 两个servlet中请求域数据在一次请求转发中共享
回忆政府办公场景…
五、重定向
重定向也可以使用Servlet直接的跳转,以及跳转页面.
resp.sendRedirect("路径");
演示:
- 特点
- 重定向是响应重定向,是浏览器行为
- 两次请求
- 地址栏会变化
- 请求域数据无法共享
六、路径问题
请求转发是服务器行为,服务器根路径是项目名,
所以发请求,从/开始,不会丢失项目名
重定向是浏览器行为,浏览器根路径是端口
所以发请求,从/开始,就会丢项目名
// req.getContextPath(); // 获得项目名 ,例如 /day40
resp.sendRedirect(req.getContextPath()+"/redirect2"); // 拼接项目名
享
[外链图片转存中…(img-r55gqFJu-1685257229058)]
六、路径问题
请求转发是服务器行为,服务器根路径是项目名,
所以发请求,从/开始,不会丢失项目名
重定向是浏览器行为,浏览器根路径是端口
所以发请求,从/开始,就会丢项目名
// req.getContextPath(); // 获得项目名 ,例如 /day40
resp.sendRedirect(req.getContextPath()+"/redirect2"); // 拼接项目名