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引入
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.代码实现
- 配置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>
- 编写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);
}
}