业务层与获取初始化数据

servlet拥有四个声明周期:实例化,初始化,服务,销毁

init初始化

有参数

1
2
3
4
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}

无参数

1
2
public void init() throws ServletException {
}

在servlet初始化时做一些工作,我们重写init方法,并且可以获得初始化的数据

首先获取config对象,其次再后去初始化值

1
2
3
4
5
6
7
8
9
10
11
public class Demo01Servlet extends HttpServlet {

@Override
public void init(){
//获取config对象
ServletConfig servletConfig=getServletConfig();
String initStr=servletConfig.getInitParameter("参数");
System.out.println(initStr);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
<servlet>
<servlet-name>Demo01</servlet-name>
<servlet-class>com.zss.servlets.Demo01Servlet</servlet-class>
<init-param>
<param-name>参数</param-name>
<param-value>我是初始化参数</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>Demo01</servlet-name>
<url-pattern>/Demo01</url-pattern>
</servlet-mapping>

image-20220408172332726

下面的这种方式亦可以进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@WebServlet(urlPatterns = {"/Demo01"},
initParams = {
@WebInitParam(name = "参数",value = "我是参数")
}
)
public class Demo01Servlet extends HttpServlet {

@Override
public void init(){
//获取config对象
ServletConfig servletConfig=getServletConfig();
String initStr=servletConfig.getInitParameter("参数");
System.out.println(initStr);
}

}

而同样我们也可以获取到上下文的配置

1
2
3
4
<context-param>
<param-name>参数1</param-name>
<param-value>我是参数1</param-value>
</context-param>

image-20220408173417402

1
2
3
ServletContext servletContext=getServletContext();
String text=servletContext.getInitParameter("参数1");
System.out.println(text);

业务层

MVC

MVC=Model(模型)+View(视图)+Controller(控制器)

视图层:御用做数据展示和用户交互的界面

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

模型层:包括pojo,业务模型组件,数据访问层组件

​ opjo:值对象

​ DAO:数据访问对象,是一个单精度对象,一个方法只考虑一个操作,比如添加,修改等等

​ BO:业务对象,实际业务方法是比较复杂的,因此业务方法的粒度是比较粗的

比如:注册属于业务功能,属于业务方法,而这个业务方法中包含了多个DAO方法

IOC

IoC 容器

Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans,我们将在下一章中进行讨论。

通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。下图是 Spring 如何工作的高级视图。 Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。

IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而”控制反转”是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者

  • 耦合/依赖:层层之间存在相互的依赖,但是我们的设计规则是:高内聚,低耦合,层内部的组成应该是高度聚合的,而层层之间的关系应该是低耦合的。

    而我们为了降低耦合度,比如controller于serviceimpl之间的关系,这两层之间是相互影响的,而为了使我们下一层的改动不会影响到上一层,

    控制反转:FruitServiceImpl fruitService=new FruitServiceImpl();如果在方法中,属于方法级别(结束之后会被销毁),如果属于成员变量,则其属于servlet的作用域(整个生命周期)但是在后面在spplicationContext中.xml中,通过解析xml文件,产生实例,存放在beanMap中,而beanMap在一个BeanFactory之中,也就是说其实例的生命周期放在容器中了,控制权交给容器,这个现象为控制反转

    **依赖注入:**FruitServiceImpl fruitService=new FruitServiceImpl();存在耦合,而后面该为null,在xml文件中进行配置

1
FruitServiceImpl fruitService=new FruitServiceImpl();

这一层重新定义实例化了一个FruitServiceImpl();,而我们为了使其之间没有相互影响,我们应该

1
FruitServiceImpl fruitService=null;

但是这样会出现空指针错误,那么我们可以在xml文件进行设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--比如说通过fruit进行init初始化,同时调用了ClassPathXmlApplicationContext() 构造器
在map中存储了键值对,而检测到property,比如fruitServiceImpl,则去寻找
com.zss.myssm.BaseDAO.impl.FruitServiceImpl并且利用反射将fruitServiceImpl赋值
其余也相同
-->
<beans>
<bean id="baseDAO" class="com.zss.myssm.BaseDAO.dao.BaseDAO"/>
<bean id="fruitServiceImpl" class="com.zss.myssm.BaseDAO.impl.FruitServiceImpl">
<!--说明含有那些依赖关系,property表示属性,name表示属性名字,而ref表示引用那个的属性名-->
<property name="baseDAO" ref="baseDAO"/>
</bean>
<bean id="fruit" class="com.zss.myssm.myspringmvc.controller.FruitController">
<property name="fruitServiceImpl" ref="fruitServiceImpl"/></bean>

<bean id="fruitServiceImpl" class="com.zss.myssm.BaseDAO.impl.FruitServiceImpl"/>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class ClassPathXmlApplicationContext implements BeanFactory{
private Map<String ,Object> beanMap=new HashMap<>();

public ClassPathXmlApplicationContext() {
try {

InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//获取document对象
Document document = documentBuilder.parse(inputStream);
//获取所有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 beamId = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
Class<?> clas = Class.forName(className);
Object beanObj = clas.newInstance();
beanMap.put(beamId, beanObj);

}

}
//组装bean之间的依赖关系
/*Node节点包含:
* Element:元素节点
* Text:文本节点
* 其实下面还是拥有三个子节点,拥有两个空白的节点(或者说换行节点)
*
* */
for (int i = 0; i < beanNodeList.getLength(); i++) {
Node beanNode = beanNodeList.item(i);
if (beanNode.getNodeType() == Node.ELEMENT_NODE) {
Element beanElement = (Element) beanNode;
NodeList beanChildNodeList=beanElement.getChildNodes();
for (int j=0;j<beanChildNodeList.getLength();j++){
Node beanChildNode=beanChildNodeList.item(j);
if (beanNode.getNodeType() == Node.ELEMENT_NODE&& "property".equals(beanChildNode.getNodeName())) {
String beamId = beanElement.getAttribute("id");
Element propertyElement=(Element) beanChildNode;
String propertyName=propertyElement.getAttribute("name");
String propertyRef=propertyElement.getAttribute("ref");
Object refObj=beanMap.get(propertyRef);
Object beanObj=beanMap.get(beamId);
//设置到对应的实例中
Class<?> beanCla=beanObj.getClass();
Field propertyFiled=beanCla.getDeclaredField(propertyName);
propertyFiled.setAccessible(true);
//通过反射设置值
propertyFiled.set(beanObj, refObj);
}
}
}
}


} catch (ParserConfigurationException | ClassNotFoundException | InstantiationException | IllegalAccessException | SAXException | IOException | NoSuchFieldException e) {
e.printStackTrace();
}

}

@Override
public Object getBean(String id) {
return beanMap.get(id);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
private BeanFactory beanFactory;

@Override
public void init() {
super.init();
beanFactory=new ClassPathXmlApplicationContext();
}

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
//如果说url是:http://localhost:8080/fruit/fruit.do
//servletPath是: /fruit.do
String servletPath = req.getServletPath();
//而我接下来需要得到fruit/fruit.do中第二个fruit
//先找到最后一个/的索引位置
int lastslash = servletPath.lastIndexOf("/") + 1;
//获得最后一个点的位置
int lastpoint = servletPath.lastIndexOf(".");
servletPath = servletPath.substring(lastslash, lastpoint);

//使fruit与fruitcontroller对应,先得到controller
Object controllerObj = beanFactory.getBean(servletPath);
String operate = req.getParameter("operate");
if (operate == null | Objects.equals(operate, "")) {
operate = "inquire";
}
try {
Method[] methods = controllerObj.getClass().getDeclaredMethods();
for (Method method : methods) {

if (method.getName().equals(operate)) {
//获取所有的参数
Parameter[] parameters = method.getParameters();
//设计一个用于存放参数值的数组
Object []objectParameters=new Object[parameters.length];
for (int i=0;i<objectParameters.length;i++ ){
Parameter parameter=parameters[i];
if ("req".equals(parameter.getName())){
objectParameters[i]=req;
continue;
}
String parameValue=req.getParameter(parameter.getName());
objectParameters[i]=parameValue;
}
method.setAccessible(true);
Object obj = method.invoke(controllerObj, objectParameters);
String meth = (String) obj;
if (meth.startsWith("sendRedirect")) {
String sendRedStr = meth.substring("sendRedirect".length());
resp.sendRedirect(sendRedStr);
} else {
super.processTemplate(servletPath + "/" + meth, req, resp);
}
}

}
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}