WEB由浅入深-04篇

222 阅读5分钟

学习插图.jpg

前篇

Servlet的初始化方法

  • Servlet的生命周期:实例化、初始化、服务、销毁

  • Servlet中的初始化方法有两个:init()、init(config)

  • 其中带参数的方法代码如下: public void init(ServletConfig config) throws ServletException { this.config = config ; init(); }

  • 另外一个无参的init方法如下: public void init() throws ServletException{ }

如果我们想要在Servlet初始化时做一些准备工作,那么我们可以重写init方法

我们可以通过如下步骤去获取初始化设置的数据:

  • 获取config对象:ServletConfig config = getServletConfig();
  • 获取初始化参数值: config.getInitParameter(key);

在web.xml文件中配置Servlet

<servlet>
        <servlet-name>Demo01Servlet</servlet-name>
        <servlet-class>com.atguigu.servlet.Demo01Servlet</servlet-class>
        <init-param>
            <param-name>hello</param-name>
            <param-value>world</param-value>
        </init-param>
        <init-param>
            <param-name>uname</param-name>
            <param-value>jim</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo01Servlet</servlet-name>
        <url-pattern>/demo01</url-pattern>
    </servlet-mapping>

也可以通过注解的方式进行配置

@WebServlet(urlPatterns = {"/demo01"} , initParams = { @WebInitParam(name="hello",value="world"), @WebInitParam(name="uname",value="jim") })

Servlet中的ServletContext和context-param

获取ServletContext,有很多方法:

  • 在初始化方法中: ServletContxt servletContext = getServletContext();
  • 在服务方法中也可以通过request对象获取,也可以通过session获取: request.getServletContext(); session.getServletContext()

获取初始化值:

  • servletContext.getInitParameter();

什么是业务层

  • Model1和Model2

  • MVC : Model(模型)、View(视图)、Controller(控制器)

  • 视图层:用于做数据展示以及和用户交互的一个界面

  • 控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成

  • 模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件。

  • pojo/vo : 值对象

  • DAO : 数据访问对象

  • BO : 业务对象

区分业务对象和数据访问对象

1) DAO中的方法都是单精度方法或者称之为细粒度方法。什么叫单精度?一个方法只考虑一个操作,比如添加,那就是insert操作、查询那就是select操作....
2) BO中的方法属于业务方法,也实际的业务是比较复杂的,因此业务方法的粒度是比较粗的    

注册这个功能属于业务功能,也就是说注册这个方法属于业务方法。

      那么这个业务方法中包含了多个DAO方法。也就是说注册这个业务功能需要通过多个DAO方法的组合调用,从而完成注册功能的开发。
      注册:
            1. 检查用户名是否已经被注册 - DAO中的select操作
            2. 向用户表新增一条新用户记录 - DAO中的insert操作
            3. 向用户积分表新增一条记录(新用户默认初始化积分100分) - DAO中的insert操作
            4. 向系统消息表新增一条记录(某某某新用户注册了,需要根据通讯录信息向他的联系人推送消息) - DAO中的insert操作
            5. 向系统日志表新增一条记录(某用户在某IP在某年某月某日某时某分某秒某毫秒注册) - DAO中的insert操作
            6. ....

在库存系统中添加业务层组件

package com.crystal.service;

import com.crystal.pojo.Fruit;

import java.util.List;

/**
 * @author crystal
 * @create 2023-02-06 11:55
 */
public interface FruitService {
//    获取所有的信息
    List<Fruit> getAll(String keyword,Integer pageNo);
//    添加
    void addFruit(Fruit fruit);
//    删除
    void delFruit(Integer fid);
//    获取页面的总页数
    Integer getCount(String keyword);
//    根据id获取
    Fruit getFruitById(Integer fid);

}
package com.crystal.service;

import com.crystal.dao.FruitDAO;
import com.crystal.dao.impl.FruitDAOImpl;
import com.crystal.pojo.Fruit;

import java.util.List;

/**
 * @author crystal
 * @create 2023-02-06 12:00
 */
public class FruitServiceImpl implements FruitService{
    private FruitDAO fruitDAO = new FruitDAOImpl();
    @Override
    public List<Fruit> getAll(String keyword, Integer pageNo) {
        List<Fruit> fruitList = fruitDAO.getAll(keyword, pageNo);
        return fruitList;
    }

    @Override
    public void addFruit(Fruit fruit) {
        fruitDAO.addFruit(fruit);
    }

    @Override
    public void delFruit(Integer fid) {
        fruitDAO.delFruit(fid);
    }

    @Override
    public Integer getCount(String keyword) {
        Integer count = fruitDAO.getCount(keyword);
        Integer pageCount = (count + 5 - 1) / 5;
        return pageCount;
    }

    @Override
    public Fruit getFruitById(Integer fid) {
        Fruit fruit = fruitDAO.getFruitByFid(fid);
        return fruit;
    }
}
package com.crystal.servlet;

import com.crystal.dao.FruitDAO;
import com.crystal.dao.impl.FruitDAOImpl;
import com.crystal.myssm.StringUtil;
import com.crystal.pojo.Fruit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * @author crystal
 * @create 2023-02-04 13:11
 */
public class FruitServlet {

    private  FruitDAO fruitDAO = new FruitDAOImpl();

    private String del(Integer fid) {
        if (fid != null){
            fruitDAO.delFruit(fid);
            return "redirect:fruit";
        }
        return null;
    }

    private String  add(String fname,Integer price,Integer fcount,String remark)  {
        fruitDAO.addFruit(new Fruit(null,fname,price,fcount,remark));
        return "redirect:fruit";
    }

    private String index(String oper,String keyword,Integer pageNo,HttpServletRequest request){

        HttpSession session = request.getSession();
        if (StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//            将页码设置为1,keyword从请求中获取
            pageNo = 1;
            if (StringUtil.isEmpty(keyword)){
                keyword = "";
            }
            session.setAttribute("keyword",keyword);
        }else{
            Object keywordObj = session.getAttribute("keyword");
            if (keywordObj != null){
                keyword = (String) keywordObj;
            }else {
                keyword = "";
            }
        }
        session.setAttribute("pageNo",pageNo);
        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getAll(keyword,pageNo);
        session.setAttribute("fruitList",fruitList);

//        获取所有的条数
        Integer count = fruitDAO.getCount(keyword);
        Integer pageCount = (count + 5 - 1) / 5;
        session.setAttribute("pageCount",pageCount);
//        转发至index.html页面
//        super.processTemplate("index",request,response);
        return "index";
    }
}

IOC

  • 耦合/依赖

    依赖指的是某某某离不开某某某

    在软件系统中,层与层之间是存在依赖的。我们也称之为耦合。

    我们系统架构或者是设计的一个原则是: 高内聚低耦合。

    层内部的组成应该是高度聚合的,而层与层之间的关系应该是低耦合的,最理想的情况0耦合(就是没有耦合)

IOC - 控制反转 / DI - 依赖注入

public interface BeanFactory {
    Object getBean(String id);
}
public class ClassPathXmlApplicationContext implements BeanFactory{

    private Map<String,Object> beanMap = new HashMap<>();


    public ClassPathXmlApplicationContext(){
        try {
//        读取配置文件,将实例装进map集合
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(inputStream);
            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 id = beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");
                    Class<?> clazz = Class.forName(className);
                    Object beanClass = clazz.newInstance();
                    beanMap.put(id,beanClass);
                }
            }
//            组装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 id = beanElement.getAttribute("id");
                    NodeList childNodes = beanElement.getChildNodes();
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node childNode = childNodes.item(j);
                        Element child = (Element) childNode;
                        String childName = child.getAttribute("name");
                        String childRef = child.getAttribute("ref");
//                        根据id获取类
                        Object beanObj = beanMap.get(id);
                        Field field = beanObj.getClass().getDeclaredField(childName);
                        Object refObj = beanMap.get(childRef);
                        field.setAccessible(true);
                        field.set(beanObj,refObj);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<beans>
    <bean id="fruitDao" class="com.crystal.dao.impl.FruitDAOImpl"></bean>
    <bean id="fruitService" class="com.crystal.service.FruitServiceImpl">
        <property name="fruitDao" ref="fruitDao"></property>
    </bean>
    <bean id = "fruitController" class = "com.crystal.controller.FruitServlet">
        <property name="fruitService" ref="fruitService"></property>
    </bean>
</beans>
package com.crystal.myssm;

import com.crystal.io.BeanFactory;
import com.crystal.io.ClassPathXmlApplicationContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author crystal
 * @create 2023-02-05 15:16
 */
@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/pro/hello.do
//        第一步:getServletPath()   获取/hello.do
        String servletPath = request.getServletPath();
//        第二步:从/hello.do获取hello.do
        servletPath = servletPath.substring(1);
//        获取.do的索引
        int lastDotIndexOf = servletPath.lastIndexOf(".do");
        servletPath = servletPath.substring(0,lastDotIndexOf);
//        第三步:将获取到的hello ——> HelloController

        Object beanObj = beanFactory.getBean(servletPath);

//        获取前端的参数operate
        String operate = request.getParameter("operate");
        if (operate == null){
            operate = "index";
        }

//        根据反射调用方法
        try {
//           获取方法的参数列表
            Method[] methods = beanObj.getClass().getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                if (operate.equals(method.getName())){
                    Parameter[] parameters = method.getParameters();
                    Object[] parameterVals = new Object[parameters.length];
                    for (int j = 0; j < parameters.length; j++) {
                        Parameter parameter = parameters[j];
                        String parameterName = parameter.getName();
                        if ("request".equals(parameterName)){
                            parameterVals[j] = "request";
                        }else if ("response".equals(parameterName)){
                            parameterVals[j] = "response";
                        }else if ("session".equals(parameterName)){
                            parameterVals[j] = request.getSession();
                        }else{
                            String parameterval = request.getParameter(parameterName);
                            parameterVals[j] = parameterval;
                            Class<?> parameterType = parameter.getType();
                            Object parameterObj = parameterVals[j];
                            if (parameterObj != null){
                                if ("java.lang.Integer".equals(parameterType)){
                                    parameterObj = Integer.parseInt(parameterval);
                                }
                                parameterVals[j] = parameterObj;
                            }
                        }
                    }
             if (method != null){
//                调用controller中对应的方法
                method.setAccessible(true);
                Object ObjStr = method.invoke(beanObj,parameterVals);

//                视图处理
                String returnStr = (String) ObjStr;
                if (returnStr.startsWith("redirect:")){
                    String redirectVal = returnStr.substring("redirect:".length());
                    response.sendRedirect(redirectVal);
                }else{
                    super.processTemplate(returnStr,request,response);
                }
            }else{
                throw new RuntimeException("operate的值非法!");
            }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.crystal.controller;

import com.crystal.dao.FruitDAO;
import com.crystal.dao.impl.FruitDAOImpl;
import com.crystal.myssm.StringUtil;
import com.crystal.pojo.Fruit;
import com.crystal.service.FruitService;
import com.crystal.service.FruitServiceImpl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * @author crystal
 * @create 2023-02-04 13:11
 */
public class FruitServlet {

    private FruitService fruitService = null;

    private String del(Integer fid) {
        if (fid != null){
            fruitService.delFruit(fid);
            return "redirect:fruit";
        }
        return null;
    }

    private String  add(String fname,Integer price,Integer fcount,String remark)  {
        fruitService.addFruit(new Fruit(null,fname,price,fcount,remark));
        return "redirect:fruit";
    }

    private String index(String oper,String keyword,Integer pageNo,HttpServletRequest request){

        HttpSession session = request.getSession();
        if (StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//            将页码设置为1,keyword从请求中获取
            pageNo = 1;
            if (StringUtil.isEmpty(keyword)){
                keyword = "";
            }
            session.setAttribute("keyword",keyword);
        }else{
            Object keywordObj = session.getAttribute("keyword");
            if (keywordObj != null){
                keyword = (String) keywordObj;
            }else {
                keyword = "";
            }
        }
        session.setAttribute("pageNo",pageNo);
        List<Fruit> fruitList = fruitService.getAll(keyword,pageNo);
        session.setAttribute("fruitList",fruitList);

//        获取所有的条数
        Integer pageCount = fruitService.getCount(keyword);
        session.setAttribute("pageCount",pageCount);
//        转发至index.html页面
//        super.processTemplate("index",request,response);
        return "index";
    }
}