1.Servlet生命周期:实例化、初始化、服务、销毁
2.Servlet中的初始化方法有两个:
-
init()
public void init() throws ServletException{ } -
init(ServletConfig config):
public void init(ServletConfig config){ this.config = config; init(); }
3.如果我们想要在Servlet初始化时执行一些自定义的操作,需要重写init()。
4.通过如下步骤去获取初始化设置的数据:
-
获取config对象:
ServletConfig config = getServletConfig();
-
获取初始化参数值:
String initValue = config.getInitParameter("hello");
5.在web.xml文件中配置Servlet
【web.xml】
Demo01Servlet com.javaweb.servlets.Demo01Servlet hello world uname Nancy Demo01Servlet /demo01
6.或者通过注解的方式进行配置:
@WebServlet(urlPatterns = {"/demo01"},
initParams = {
@WebInitParam(name = "hello",value = "world"),
@WebInitParam(name = "uname",value = "Nancy")
}
)
public class Demo01Servlet extends HttpServlet {
@Override
public void init() throws ServletException {
ServletConfig config = getServletConfig();
String initValue = config.getInitParameter("hello");
System.out.println("initValue="+initValue);
ServletContext servletContext = getServletContext();
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
System.out.println("servletContext=" + c);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//req.getSession().getServletContext();
req.getServletContext();
}
}
6.4.2、ServletContext
1.通过ServletContext获取配置的上下文参数
2.获取ServletContext,有很多方法
-
在初始化方法init()中:
ServletContext servletContext = getServletContext();
-
在服务方法中通过request对象获取:
request.getServletContext();
-
通过session对象来获取:
request.getSession().getServletContext();
3.获取初始化值:
String servletContext = servletContext.getInitParameter("contextConfigLocation");
6.5、MVC——引入service
1.什么是业务层?
- MVC:Model(模型)、View(视图)、Controller(控制器)
- 视图层:用于做数据展示以及和用户交互的一个界面
- 控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型来完成
- 模型层:模型分为很多种:
- POJO/VO:值对象模型
- DAO:数据访问模型
- BO:业务逻辑模型(一般命名为Service)
- DTO:数据传输对象
2.区分业务对象和数据访问对象:
-
DAO中的方法都是单精度方法,或者称之为细粒度反方
- 单精度方法:一个方法只考虑一个操作,比如添加、那就是insert操作,查询就是select操作。
-
BO中的方法术语业务方法,实际的业务是比较复杂的,因此业务方法的粒度是比较粗的。
-
例如:
注册这个功能属于业务功能,也就是说注册这个方法术语业务方法。那么这个业务方法中包含了多个DAO方法。也就是说注册这个业务功能需要通过多个DAO方法的组合调用,从而完成注册功能。
注册:
- 检查用户名是否已经被注册 - DAO中的select操作
- 向用户表新增一条新用户记录 - DAO中的insert操作
- 向用户积分表新增一条记录(新用户默认初始化积分为100分) - DAO中的insert操作
- 向系统消息表新增一条记录(某某某新用户注册了,需要根据通讯录信息向他的联系人推送消息)- DAO中的insert操作
- 向系统日志表新增一条记录(某用户在某IP在某年某月某日某时某分某秒某毫秒注册) - DAO中的insert操作
- …
3.在库存系统中添加业务层
【FruitService.java】
public interface FruitService {
//获取指定页面的库存列表信息
List getFruitList(String keyword, Integer pageNum);
//添加库存记录
void addFruit(Fruit fruit);
//根据id查看指定库存记录
Fruit getFruitByFid(Integer fid);
//删除特定库存记录
void delFruit(Integer fid);
//修改特定库存记录
void updateFruit(Fruit fruit);
//获取总页数
Integer getPageCount(String keyword);
}
【FruitServiceImpl.java】
public class FruitServiceImpl implements FruitService {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
public List getFruitList(String keyword, Integer pageNum) {
return fruitDAO.getFruitList(keyword, pageNum);
}
@Override
public void addFruit(Fruit fruit) {
fruitDAO.addFruit(fruit);
}
@Override
public Fruit getFruitByFid(Integer fid) {
return fruitDAO.getFruitByFid(fid);
}
@Override
public void delFruit(Integer fid) {
fruitDAO.delFruit(fid);
}
@Override
public void updateFruit(Fruit fruit) {
fruitDAO.updateFruit(fruit);
}
@Override
public Integer getPageCount(String keyword) {
//总记录条数
int count = fruitDAO.getFruitCount(keyword);
return (count + 5 - 1)/5;
}
}
【FruitController.java】
public class FruitController extends ViewBaseServlet {
private FruitService fruitService = new FruitServiceImpl();
private String update(Integer fid,String fname,Integer price,Integer fcount,String remark){
//3.执行更新
Fruit fruit = new Fruit(fid, fname,price,fcount,remark);
fruitService.updateFruit(fruit);
//4.资源跳转
//response.sendRedirect("fruit.do");
return "redirect:fruit.do";
}
private String edit(Integer fid,HttpServletRequest request) {
if (fid != null) {
Fruit fruit = fruitService.getFruitByFid(fid);
request.setAttribute("fruit", fruit);
return "edit";
}
return "error";
}
private String delete(Integer fid) {
if (fid != null) {
fruitService.delFruit(fid);
return "redirect:fruit.do";
}
return "error";
}
private String add(String fname,Integer price,Integer fcount,String remark) {
Fruit fruit = new Fruit(fname,price,fcount,remark);
System.out.println(fruit);
fruitService.addFruit(fruit);
//response.sendRedirect("fruit.do");
return "redirect:fruit.do";
}
private String index(String operate,String keyword,Integer pageNum,HttpServletRequest request) {
HttpSession session = request.getSession();
if (pageNum == null) {
pageNum = 1;
}
if (StringUtil.isNotEmpty(operate) && "search".equals(operate)) {
pageNum = 1;
if (StringUtil.isEmpty(keyword)) {
keyword = "";
}
//将keyword保存(覆盖)到session中
session.setAttribute("keyword",keyword);
}else {
Object keywordObj = session.getAttribute("keyword");
if (keywordObj != null) {
keyword = (String) keywordObj;
}else {
keyword = "";
}
}
session.setAttribute("pageNum",pageNum);
List fruitList = fruitService.getFruitList(keyword,pageNum);
session.setAttribute("fruitList", fruitList);
//总页数
int pageCount = fruitService.getPageCount(keyword);
session.setAttribute("pageCount", pageCount);
return "index";
}
}
6.6、IOC
1.耦合/依赖:
- 依赖指的是某某某离不开某某某
- 在软件系统中,层与层之间是存在依赖的。我们也称之为耦合。
- 系统架构或者设计的一个原则是:高内聚低耦合。
- 层内部的组成应该是高度耦合的,而层与层之间的关系是低耦合的,最理想的情况零耦合(就是没有耦合)。
2.IOC - 控制反转/IOC - 依赖注入
-
控制反转:
1)之前在Servlet中,创建service对象
FruitService fruitService = new FruitServiceImpl();
这种写法的问题:
- 这句话如果出现在servlet中的某个方法内部,那么这个fruitService的作用域(生命周期)应该就是这个方法级别;
- 这句话如果出现在servlet中的类中,fruitService是一个成员变量,那么这个fruitService的作用域(生命周期)应该就是这个servlet的实例级别;
2)之后在applicationContext.xml中定义fruitService,然后通过解析XML,产生fruitService实例,存放在beanMap中,beanMap存放在BeanFactory。
因此,我们转移(改变)了之前的service实例、dao实例等等的生命周期。控制权从程序员转移到beanfactory。这个现象称之为控制反转。
-
依赖注入:
1)之前在控制层出现代码:
FruitService fruitService = new FruitServiceImpl();
那么,控制层和service层存在耦合。
2)之后,将代码修改成:
FruitService fruitService = null;
然后,在配置文件中配置:
【applicationContext.xml】
【BeanFactory.java】
public interface BeanFactory { Object getBean(String id); }【ClassPathXmlApplicationContext.java】
public class ClassPathXmlApplicationContext implements BeanFactory{ private MapbeanMap = new HashMap<>(); public ClassPathXmlApplicationContext() { try { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml"); //1.创建DocumentBuilderFactory对象 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //2.创建DocumentBuilder对象 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //3.创建Document对象 Document document = documentBuilder.parse(inputStream); //4.获取所有的bean节点 NodeList beanNodeList = document.getElementsByTagName("bean"); for (int i = 0; i < beanNodeList.getLength(); i++) { Node beanNode = beanNodeList.item(i); if (beanNode.getNodeType() == Node.ELEMENT_NODE) { Element beanElement = (Element) beanNode; String beanId = beanElement.getAttribute("id"); String className = beanElement.getAttribute("class"); Class beanClass = Class.forName(className); //创建bean实例 Object beanObj = beanClass.newInstance(); //将bean实例对象保存到map容器中 beanMap.put(beanId, beanObj); //到目前为止,此处需要注意的是:bean和bean之间的依赖关系还没有设置 } } //5.组装bean之间的依赖关系 for (int i = 0; i < beanNodeList.getLength(); i++) { Node beanNode = beanNodeList.item(i); if (beanNode.getNodeType() == Node.ELEMENT_NODE) { Element beanElement = (Element) beanNode; String beanId = beanElement.getAttribute("id"); NodeList beanChildNodeList = beanElement.getChildNodes(); //System.out.println("length:"+beanChildNodeList.getLength()); for (int j = 0; j < beanChildNodeList.getLength(); j++) { Node beanChildNode = beanChildNodeList.item(j); if (beanChildNode.getNodeType() == Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){ Element propertyElement = (Element) beanChildNode; String propertyName = propertyElement.getAttribute("name"); String propertyRef = propertyElement.getAttribute("ref"); //1)找到property对应的实例 Object refObj = beanMap.get(propertyRef); //2)将refObj设置到当前bean对应的实例的property属性上去 Object beanObj = beanMap.get(beanId); Class beanClazz = beanObj.getClass(); Field propertyField = beanClazz.getDeclaredField(propertyName); propertyField.setAccessible(true); propertyField.set(beanObj, refObj); } } } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } @Override public Object getBean(String id) { return beanMap.get(id); } } 【DispatcherServlet.java】
@WebServlet("*.do") public class DispatcherServlet extends ViewBaseServlet { private BeanFactory beanFactory; public DispatcherServlet() { } public void init() throws ServletException { super.init(); beanFactory = new ClassPathXmlApplicationContext(); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码 request.setCharacterEncoding("UTF-8"); //假设URL:http://localhost:8080/03mvcDispatcher/hello.do //那么servletPath是:/hello.do //我的思路: // 第1步: /hello.do -> hello String servletPath = request.getServletPath(); servletPath = servletPath.substring(1); int lastDotIndex = servletPath.lastIndexOf(".do"); servletPath = servletPath.substring(0, lastDotIndex); System.out.println("servletPath=" + servletPath); // 第2步: hello -> HelloController Object controllerBeanObj = beanFactory.getBean(servletPath); String operation = request.getParameter("operation"); if (StringUtil.isEmpty(operation)) { operation = "index"; } // try { Method[] methods = controllerBeanObj.getClass().getDeclaredMethods(); for (Method method : methods) { if (operation.equals(method.getName())){ //1.统一获取请求参数 //1-1.获取当前请求方法的参数,返回参数数组 Parameter[] parameters = method.getParameters(); //1-2.parameterValues用来存放参数的值 Object[] parameterValues = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; //不考虑复选框的值,只考虑单选框的值 String parameterName = parameter.getName(); //如果参数名为request、response、session,那就不是通过请求中获取参数 if ("request".equals(parameterName)) { parameterValues[i] = request; } else if ("response".equals(parameterName)) { parameterValues[i] = response; } else if ("session".equals(parameterName)){ parameterValues[i] = request.getSession(); } else { //从请求中获取参数值 String parameterValue = request.getParameter(parameterName); Object parameterObj = parameterValue; String typeName = parameter.getType().getName(); if (parameterObj != null) { if ("java.lang.Integer".equals(typeName) ) { parameterObj = Integer.parseInt(parameterValue); } } parameterValues[i] = parameterObj; } } //2.controller组件中的方法调用 method.setAccessible(true); Object methodReturnObj = method.invoke(controllerBeanObj,parameterValues); //3.视图处理 String methodReturnStr = (String) methodReturnObj; if (methodReturnStr.startsWith("redirect:")) {//比如 :redirect:fruit.do String redirectStr = methodReturnStr.substring("redirect:".length()); response.sendRedirect(redirectStr); } else { super.processTemplate(methodReturnStr,request,response); } } } } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }【FruitServiceImpl.java】
public class FruitServiceImpl implements FruitService { private FruitDAO fruitDAO = null; @Override public ListgetFruitList(String keyword, Integer pageNum) { return fruitDAO.getFruitList(keyword, pageNum); } @Override public void addFruit(Fruit fruit) { fruitDAO.addFruit(fruit); } @Override public Fruit getFruitByFid(Integer fid) { return fruitDAO.getFruitByFid(fid); } @Override public void delFruit(Integer fid) { fruitDAO.delFruit(fid); } @Override public void updateFruit(Fruit fruit) { fruitDAO.updateFruit(fruit); } @Override public Integer getPageCount(String keyword) { //总记录条数 int count = fruitDAO.getFruitCount(keyword); return (count + 5 - 1)/5; } } 【FruitController.java】
public class FruitController extends ViewBaseServlet { private FruitService fruitService = null; private String update(Integer fid,String fname,Integer price,Integer fcount,String remark){ //3.执行更新 Fruit fruit = new Fruit(fid, fname,price,fcount,remark); fruitService.updateFruit(fruit); //4.资源跳转 //response.sendRedirect("fruit.do"); return "redirect:fruit.do"; } private String edit(Integer fid,HttpServletRequest request) { if (fid != null) { Fruit fruit = fruitService.getFruitByFid(fid); request.setAttribute("fruit", fruit); return "edit"; } return "error"; } private String delete(Integer fid) { if (fid != null) { fruitService.delFruit(fid); return "redirect:fruit.do"; } return "error"; } private String add(String fname,Integer price,Integer fcount,String remark) { Fruit fruit = new Fruit(fname,price,fcount,remark); System.out.println(fruit); fruitService.addFruit(fruit); //response.sendRedirect("fruit.do"); return "redirect:fruit.do"; } private String index(String operate,String keyword,Integer pageNum,HttpServletRequest request) { HttpSession session = request.getSession(); if (pageNum == null) { pageNum = 1; } if (StringUtil.isNotEmpty(operate) && "search".equals(operate)) { pageNum = 1; if (StringUtil.isEmpty(keyword)) { keyword = ""; } //将keyword保存(覆盖)到session中 session.setAttribute("keyword",keyword); }else { Object keywordObj = session.getAttribute("keyword"); if (keywordObj != null) { keyword = (String) keywordObj; }else { keyword = ""; } } session.setAttribute("pageNum",pageNum); ListfruitList = fruitService.getFruitList(keyword,pageNum); session.setAttribute("fruitList", fruitList); //总页数 int pageCount = fruitService.getPageCount(keyword); session.setAttribute("pageCount", pageCount); return "index"; } }



