用静态包含替换,每个页面都要替换,
注意,替换后页面跳转参照地址变为Base标签中的url
ii. 每个页面的页脚
用静态包含替换
iii. 登录成功后的页面
用静态包含替换
iv. manager模块的菜单
用静态包含替换
问题一:
固定写入了访问css和jQuery的页面base参考路径,用户访问时,只有book路径为服务器的,其他文件路径为自己电脑
book和css访问路径不同,用户访问时,会在自己的电脑中找css
因为在head.jsp中,修改了引用css的页面的参考路径为base中的localhost
解决办法:Base标签根路径动态获取
给访问的参考路径,设置动态获取端口号、ip、访问路径
表单提交失败的错误回写
将需要回显的参数,在request域中设置,
req.setAttribute("username",username);
在需要回显的jsp位置使用表达式脚本,返回request域中输入的参数<%=request.getAttribute("username")==null?"":request.getAttribute("username")%>
登录时
在登录的web程序中request域中设置需要返回的字符串和参数键值对 (后面可以用参数注入WebUtils的方法)
在页面上通过表达式脚本返回requset域中的错误提示及输入参数值
注册时同理
在注册的web程序中request域中设置需要返回的字符串和参数键值对
在页面上在页面上通过表达式脚本返回requset域中的错误提示及输入参数值
LoginServlet和RegistServlet,是两个单独的响应程序,分别对应登录和注册两个Post响应,现在需要将两个Post请求方法,抽取到一个类中。通过判断隐藏域值,来执行不同的响应操作(后面不需要判断,且doPost和操作方法分离)
新建一个Servlet程序实现类,将登录和注册两个post请求放在一个 doPost()中,
实现:
1. UserServlet类---创建userService业务对象----重写doPost(并创建业务对象) ------ 创建Servlet程序
2. login.jsp和 regist.jsp中表单中创建隐藏域hidden(action=regist/login),并修改请求地址userServlet
通过隐藏域的value标记login.jps和regist.jsp的表单
3. 获取当前请求的表单隐藏域的value值,通过value值判断执行登录还是注册操作(隐藏域的value为对应操作方法名)
doPost和操作方法分离---(新增操作方法,添加else if再判断即可----显得冗余)
doPost方法中:只获取请求表单隐藏域值,和判断调用登录还是注册方法
实际的登录和注册方法分别在login()和regist()中执行
这种方式,判断请求的隐藏域的action,当更多功能需要时,就在doPost中添加 了else if 继续判断,会显得冗余
通过反射,直接通过获取的value获取本类this的方法名执行,不必单独一个一个写else if
本类实例对象----getClass()------获取方法对象(方法名,参数.class)-------invoke(对象,参数)调用方法
解决:不用每次添加一个功能请求,就添加一次else if
所有大的功能模块程序,都继承BaseServlet抽象类,在Baseervlet的doPost用反射、value、this得到对应子类中的方法执行
关键是,利用this调用子类对象class----反射---调用子类特有方法
优点:新添加的大的功能模块只需继承BaseServlet,doPost请求获取执行方法不需要管,只需关心自己的具体操作方法
-------只要继承了BaseServlet,当要请求具体方法时,到doPost时,就会自动到BaseServlet中,根据获取的隐藏域value,反射获取含有该方法的子类中的方法名,并invoke执行,就又执行回到具体功能模块类中。
注意:BaseServlet必须是抽象类,否则this就是调用的自己的对象,没办法调用子类对象
共性抽取doPost方法,将反射获取方法实现独立出来,之后的模块类,如果需要获取请求,增加功能,只需创建功能类继承BaseServlet类,就能根据BaseServlet中获取的表单隐藏域action定位this.方法名,执行方法,只需关注,增加功能类的功能方法
将所有的操作方法(登录/注册等)放入到一个统一的类UserServlet中,根据action传递的值通过反射调用出方法名,invoke()使用对应方法
将doPost方法单独抽取出来为BaseServlet,UserServlet继承BaseServlet,就可以只关注UserServlet类中的业务方法了
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
实验:抽象父类,子类(包含特有方法)
this:在父类方法中,表示实例化对象(子类对象) ,能调用子类父类共有的方法(子类重写的方法),不能调用子类特有方法
想要调用子类特有方法:使用反射:this.getClass().getDeclaredMethod("特有的方法名").invoke(this,参数)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
在具体的操作类中,如regist/login中
Map存的是参数键值对
优化注入:直接创建WebUtils 参数注入工具类
在UserServlet类中的操作方法(login()/regist())中,直接创建对象,使用参数注入类方法,传入请求和User对象,进行User的参数注入
为什么就能直接植入到user对象?
遍历req得到的map集合,得到请求参数的键值对
核心就是使用User对象的set方法,将得到的键值对的key封装成 setKey(value)
----username封装成 setUsername("wwwwww")
----------------------
修改User类的某个属性的set方法后就,注入不了了
优化:只需传入一个Map给WebUtils工具类
----- ---------------- 最少知道原则:被调用方尽量少依赖调用方
WebUtils的自定义注入方法中,参数传入,代码耦合度高---Dao、Service层没有req,就无法使用该注入方法
而传入req目的就是通过req获取参数Map集合,那就可以在Web层就获取该参数Map,在传入Map,Dao、Service层就能用了
实参就需要传入req获取Map的方法 ----------------- 实参尽可能的传入执行结果,而不是传入调用方的属性进入执行---减少依赖
可以提高工具类的复用性,就只需要一个Map,而不一定需要req
参数注入优化:方法返回值修改,使得参数注入,返回值直接赋值给user对象
二次优化:注入方法添加泛型,传入什么类型,返回什么类型,不用类型转换了