JavaWeb第六天--Servlet初始化、Service引入

245 阅读3分钟

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

一、初始化方法

public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
}

public void init() throws ServletException {
}

二、重写init方法

如果想要在初始化的过程中添加额外操作,可以通过重写init()方法实现。

1.web.xml配置Servlet

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<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>

2.获取初始化值

/*
@WebServlet(urlPatterns = {"/demo01"} ,
        initParams = {
            @WebInitParam(name="hello",value="world"),
            @WebInitParam(name="uname",value="jim")
        }
        )
*/
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("contextConfigLocation = " + contextConfigLocation);
    }

3.获取ServletContext

 @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务方法中,也可以获取context
        //req.getServletContext();
        //req.getSession().getServletContext();
    }

三、Service引入

176B2FCA-8AB1-4C15-8774-2B4E8FCA7514.png

1.什么是业务层

  • MVC:Model(模型)、View(视图)、Controller(控制器)
  • 视图层:数据展示、用户交互的通道
  • 控制层:能够接受客户端的请求,具体的业务需求要借助模型组件来完成
  • 模型层:pojo/vo(value object)(数据载体),有业务模型组件,有数据访问层组件
    • pojo/vo:值对象
    • DAO:数据访问对象,都是单精度方法,一个方法只考虑一个操作
    • BO:业务对象,粗粒度方法
    • BO、DAO区别:例如注册功能,需要多个DAO方法组合调用

四、IOC

1.介绍

1.耦合/依赖

层与层之间存在依赖关系,称之为耦合。软件设计应该高内聚低耦合。

2.控制反转IOC\依赖注入DI

在之前Servlet中,我们创建service对象 FruitService fruitService = new FruitServiceImpl(); 
这句话如果出现在servlet中的某个方法内部,name这个fruitServlet的作用域(生命周期)就是这个方法级别; 
这句话如果出现在servlet类中,也就是说fruitService是一个成员变量,那么这个fruitService的作用域应该就是这个servlet实例级别。

优化后,控制反转

在application.xml中定义了这个fruitService,通过解析XML,产生
fruitService实例,存放在beanMap中,这个beanMap在BeanFactory中
改变了之前的service、dao实例的生命周期,控制权在BeanFactory手上。

依赖注入

1)之前我们在控制层出现FruitService fruitService = new FruitServiceImpl(); 
那么控制层和service层存在耦合
2)代码修改成FruitService fruitService = null;
在配置文件中配置:
<bean id="fruit" class="FruitController">
    <property name="fruitService" ref="fruitService"/>
</bean>

2.代码实现

  1. 配置3个bean,在启动的时候把这三个bean存放在容器中
<beans>
    <bean id="fruitDAO" class="com.atguigu.fruit.dao.impl.FruitDAOImpl">
    </bean>
    <bean id="fruitService" class="com.atguigu.fruit.biz.impl.FruitServiceImpl">
        <property name="fruitDAO" ref="fruitDAO"></property>
    </bean>
    <bean id="fruit" class="com.atguigu.fruit.servlets.FruitController">
        <property name="fruitService" ref="fruitService"></property>
    </bean>
</beans>
  1. 编写XMLApplication
public class ClassPathXmlApplicationContext implements BeanFactory{
    //beanMap 存放 id 和 class的关系
    private Map<String,Object> beanMap = new HashMap<>();
    /**
     * 1.把所有bean元素放在beanMap供调用
     * 2.bean之间的依赖关系组合(可用beanMap调取property中的)
     */
    //Servlet生命周期:实例化、初始化、服务、销毁
    public ClassPathXmlApplicationContext() {
        try {
            //解析配置文件,创建文件流,读取文件信息
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("application.xml");
            //1.创建factory
            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");
                    //创建bean实例
                    Object beanObj = Class.forName(className).newInstance();
                    //将bean实例对象保存在map容器中
                    beanMap.put(beanId,beanObj);
                }
            }
            //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");
                    //读取bean子节点,property
                    NodeList beanChildNodeList = beanElement.getChildNodes();
                    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.找到propertyRef对应的实例
                            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);
    }
}