JaveWeb02-Maven和web入门(初)

目录

前言

一、Maven(Maven官网)

1.1 Maven作用

1.2 Maven安装 

1.3 配置Maven环境

 1.4 创建Maven项目

 1.5 导入Maven项目

二、依赖管理

 2.1 依赖配置

2.2 依赖传递

 2.3 依赖范围

2.4 生命周期

三、web后端开发入门

3.1 SpringBootWeb入门

3.2 http

3.2.1 概述

 3.2.2 请求协议

3.2.3 响应协议

3.2.4 协议解析(略)

3.3 Tomcat

 3.4 请求响应

3.4.1 请求项目创建

3.4.2 请求入门 

 3.4.2 简单参数

3.4.3 实体参数

3.4.4 数组集合参数

 3.4.5 日期时间参数

 3.4.6  Json参数

3.4.7 路径参数

 3.4.8 响应数据

3.5 分层解耦

3.5.1 三层架构

 3.5.2 分层解耦

 3.5.3 IOC与DI

3.5.3.1 入门

3.5.3.2 IOC详解

3.5.3.3 DI详解


前言

自用笔记复盘,后续更新在javeweb03-mysql中

一、Maven(Maven官网

Maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。

1.1 Maven作用

  • 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题
  • 统一项目结构:提供标准、统一的项目结构
  • 项目构建:标准跨平台(Linux、Windows、MacOs)的自动化项目构建方式

1.2 Maven安装 

 注:在第2步中=》配置本地仓库可以自己指定一个文件里放入maven仓库,具体根据自己的存放路径有关。在写到conf里面的setting.xml文件里面

1.3 配置Maven环境

配置Maven环境(当前工程)

  • 选择 IDEA中 File -->Settings --> Build,Execution,Deployment --> Build Tools --> Maven
  • 设置 IDEA 使用本地安装的 Maven,并修改配置文件及本地仓库路径 

注:建议使用下列的方法配置全局的maven

配置Maven环境(全局)

具体的做法跟上述图片中设置的大相径庭 

 1.4 创建Maven项目

  • 创建模块,选择Maven,点击Next
  • 填写模块名称,坐标信息,点击finish,创建完成
  • 编写 HelloWorld,并运行

 Maven坐标

什么是坐标?

  • Maven 中的坐标是资源的唯一标识,通过该坐标可以唯一定位资源位置
  • 使用坐标来定义项目或引入项目中需要的依赖。

Maven 坐标主要组成

  • groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)
  • artifactld:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
  • version:定义当前项目版本号

 1.5 导入Maven项目

方式一:打开IDEA,选择右侧Maven面板,点击+号,选中对应项目的pom.xml文件,双击即可

 方式二:打开IDEA,选择右侧Maven面板,点击+号,选中对应项目的pom.xml文件,双击即可

二、依赖管理

 2.1 依赖配置

依赖:指当前项目运行所需要的jar包,一个项目中可以引入多个依赖。

配置:

  • 在 pom.xml中编写<dependencies>标签
  • <dependencies>标签中 使用<dependency>引入坐标
  • 定义坐标的 groupld,artifactld,version点击刷新按钮,引入最新加入的坐标

注意事项
如果引入的依赖,在本地仓库不存在,将会连接远程仓库/中央仓库,然后下载依赖。(这个过程会比较耗时,耐心等待)

2.2 依赖传递

依赖具有传递性

  • 直接依赖:在当前项目中通过依赖配置建立的依赖关系
  • 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源

排除依赖
排除依赖指主动断开依赖的资源,被排除的资源无需指定版本。 

 2.3 依赖范围

依赖的jar包,默认情况下,可以在任何地方使用。可以通过<scope>..</ scope>设置其作用范围。

作用范围:

  • (main文件夹范围内)主程序范围有效。
  • 测试程序范围有效。(test文件夹范围内)
  • 是否参与打包运行。(package指令范围内)
  • scope值主程序测试程序打包(运行)范例
    compile(默认)YYYlog4j
    test-Y-junit
    providedYY-servlet-api
    runtime-YYjdbc驱动

2.4 生命周期

Maven的生命周期就是为了对所有的maven项目构建过程进行抽象和统一

Maven中有3套相互独立的生命周期:

  • clean:清理工作。
  • default:核心工作,如:编译、测试、打包、安装、部署等。
  • site:生成报告、发布站点等。

clean:

  • pre-clean
  • clen
  • post-clean

default:

  • validate
  • initialize
  • generate-sources
  • process-sources
  • generate-resources
  • process-resources
  • compile
  • process-classes
  • generate-test-sources
  • process-test-sources
  • generate-test-resources
  • process-test-resources
  • test-compile
  • process-test-classes
  • test
  • prepare-package
  • package
  • verify
  • install
  • deploy

site:

  • pre-site
  • site
  • post-site
  • site-deploy

=====================================================================

  • clean:移除上一次构建生成的文件
  • compile:编译项目源代码
  • test:使用合适的单元测试框架运行测试(junit)
  • package:将编译后的文件打包,如:jar、war等
  • install:安装项目到本地仓库

执行指定生命周期的两种方式

  • 在idea中,右侧的maven工具栏,选中对应的生命周期,双击执行。
  • 在命令行中,通过命令执行。 (具体的命令可以到网上自行查阅,这里就不放了)

三、web后端开发入门

3.1 SpringBootWeb入门

需求:使用 SpringBoot开发一个web应用,浏览器发起请求 /hello后,给浏览器返回字符串"Helo Word ~"

 HelloController.class 

package com.itheima.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//请求处理类
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hello world~");
        return "hello world";
    }
}

 在到主程序的spring自动创建的类中执行

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootWebQuickstartApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebQuickstartApplication.class, args);
    }

}

3.2 http

3.2.1 概述

概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。

特点:
基于TCP协议:面向连接,安全
基于请求-响应模型的:一次请求对应一次响应
HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的

  • 缺点:多次请求间不能共享数据,
  • 优点:速度快 

 3.2.2 请求协议

  • 请求行:请求数据第一行(请求方式、资源路径、协议)
  • 请求头:第二行开始,格式key:value
  • 请求体:POST请求,存放请求参数
Host请求的主机名
User-Agent浏览器版本,例如Chrome浏览器的标识类似Mozila/5.0.. Chrome/79,IE浏览器的标识类似Mozila/5.0(Windows
NT ...) like Gecko
Accept表示浏览器能接收的资源类型,如text/*,image/*或者*/*表示所有;
Accept-Language表示浏览器偏好的语言,服务器可以据此返回不同语言的网页
Accept-Encoding表示浏览器可以支持的压缩类型,例如gzip,deflate等
Content-Type请求主体的数据类型
Content-Length请求主体的大小(单位:字节)

 请求方式-GET:请求参数在请求行中,没有请求体如:/brand/findA11?name=oppo&status=1。GET请求大小是有限制的

请求方式-POST:请求参数在请求体中,POST请求大小是没有限制的。

3.2.3 响应协议

  • 响应行:响应数据第一行(协议、状态码、描述)
  • 响应头:第二行开始,格式key:value
  • 响应体:最后一部分,存放响应数据 

响应状态码:

1XX响应中-临时状态码,表示请求已经接收,告诉客户端应该继续请求或者如果它已经完成则忽略它
2XX成功-表示请求已经被成功接收,处理已完成。
3XX重定向-重定向到其他地方;让客户端再发起一次请求以完成整个处理
4XX客户端错误-处理发生错误,责任在客户端。如:请求了不存在的资源、客户端未被授权、禁止访问等
5XX服务器错误-处理发生错误,责任在服务端。如:程序抛出异常等。

常见的状态响应码:

状态码英文描述解释
200OK客户端请求成功,即处理成功,这是我们最想看到的状态码
302Found指示所请求的资源已移动到由Location响应头给定的URL,浏览器会自动重新访问到这个页面
304Not Modified告诉客户端,你请求的资源至上次取得后,服务端并未更改,你直接用你本地缓存吧。隐式重定向
400Bad Request客户端请求有语法错误,不能被服务器所理解
403Forbidden服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源
404Not Found请求资源不存在,一般是URL输入有误,或者网站资源被删除了
425Method Not Allowed请求方式有误,比如应该用GET请求方式的资源,用了POST
428Precondition Required服务器要求有条件的请求。告诉客户端要想访问该资源,必须携带特定的请求头
429Too Many Requests指示用户在给定时间内发送了太多请求(“限速”),配合 Retry-Ater(多长时间后可以请求)响应头一起使用
431Request Header Fields TooLarge请求头太大,服务器不愿意处理请求,因为它的头部字段太大。请求可以在减少请求头域的大小后重新提交。
500Internal server Error服务器发生不可预期的错误。服务器出异常了,赶紧看日志去吧
503service unavailable服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好

附:状态码大全icon-default.png?t=N7T8https://cloud.tencent.com/developer/chapter/13553


Content-Type
 
表示该响应内容的类型,例如text/html,application/json。
Content-Length
 
表示该响应内容的长度(字节数)
Content-Encoding
 
表示该响应压缩算法,例如gzip。
Cache-Control
 
指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒。
Set-Cookie告诉浏览器为当前页面所在的域设置cookie。

3.2.4 协议解析(略)

3.3 Tomcat

  • 概念: Tomcat是Apache 软件基金会一个核心项目,是一个开源免费的轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。
  • JavaEE:Java Enterprise Edition,Java企业版。指lava企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、EJBRMl、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF
  • Tomcat 也被称为 Web容器、Servlet容器。Servlet程序需要依赖于Tomcat才能运行

 如何修改一些乱码问题:

  常见的启动问题:

启动窗口一闪而过:检查JAVA HOME环境变量是否正确配置
端口号冲突:找到对应程序,将其关闭掉

 HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号。

Tomcat 部署项目:
将项目放置到 webapps 目录下,即部署完成

入门程序解析

创建后自动下载一个压缩包,然后解压压缩包

 3.4 请求响应

请求响应:

  • 请求(HttpServletRequest):获取请求数据。
  • 响应(HttpServletResponse):设置响应数据
  • BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。
  • CS架构:Client/Server,客户端/服务器架构模式。

3.4.1 请求项目创建

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。

作用:常用于进行接口测试

登录进来选择创建工作空间;注意:如果没有workspace请选注册并登录账户才可以看到

3.4.2 请求入门 

保存请求的集合:

 点击右上角的save按钮或者使用快捷键:ctrl+s

 3.4.2 简单参数

@RequestParam中的reguired属性默认为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,以将required属性设置为false。

1. 原始方式获取请求参数(了解)

  • Controller方法形参中声明HttpServletRequest对象调用对象的getParameter(参数名)

2. SpringBoot中接收简单参数

  • 请求参数名与方法形参变量名相同
  • 会自动进行类型转换

3. @RequestParam注解

  • 方法形参名称与请求参数名称不匹配,通过该注解完成映射该注解的required属性默认是true,代表请求参数必须传递 

RequestController.class

package com.itheima.controller;

import com.itheima.pojo.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 测试请求参数接收
 */
@RestController
//@Controller
//@ResponseBody
public class RequestController {

//     
//     原始方式
//    @RequestMapping("/simpleParam")
//    public String simpleParam(HttpServletRequest request){
//        //获取请求参数
//        String name = request.getParameter("name");
//        String ageStr = request.getParameter("age");
//
//        int age = Integer.parseInt(ageStr);
//        System.out.println(name+ ":" + age);
//        return "OK";
//    }
//
//    springboot方式
    @RequestMapping("/simpleParam")
//    public String simpleParam(String name, Integer age){
        System.out.println(name+ ":" + age);
        return "OK";
    }

//名称与请求名称不同
    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name = "name", required = false) String username, Integer age){
        System.out.println(username+ ":" + age);
        return "OK";
    }


}

3.4.3 实体参数

  • 简单实体对象:请求参数名与形参对象属性名相同,定义POJ0接收即可
  • 复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJ0属性参数

简单实体

 复杂实体

 //2. 简单实体参数
    @RequestMapping("/simplePojo")
    public String simplePojo(User user){
        System.out.println(user);
        return "OK";
    }
    //复杂实体参数
    @RequestMapping("/complexPojo")
    public String complexPojo(User user){
        System.out.println(user);
        return "OK";
    }

3.4.4 数组集合参数

  • 数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数

  • 集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关系

    //3. 数组集合参数
    @RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }

    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }

 3.4.5 日期时间参数

日期参数:使用 @DateTimeFormat 注解完成日期参数格式转换

    //4. 日期时间参数
    @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
        System.out.println(updateTime);
        return "OK";
   

 3.4.6  Json参数

JSON参数:JSON数据键名与形参对象属性名相同,定义POJ0类型形参即可接收参数,需要使用 @RequestBody标识

{
    "name":"张三",
    "age":18,
    "address":{
        "province":"北京",
        "city":"北京"
    }
}

 //5. json参数
    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }

3.4.7 路径参数

 路径参数:通过请求URL直接传递参数,使用!.1来标识该路径参数,需要使用 @PathVariable 获取路径参数

    @RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id , @PathVariable String name){
        System.out.println(id);
        System.out.println(name);
        return "OK";
    }

 多个参数


    @RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id , @PathVariable String name){
        System.out.println(id);
        System.out.println(name);
        return "OK";
    }

 3.4.8 响应数据

@ResponseBody

  • 类型:方法注解、类注解
  • 位置:Controller方法上/类上
  • 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合,将会转换为JSON格式响应说明:@RestController = @Controller + @ResponseBody ;

响应字符串 

  @RequestMapping("/hello")
    public String hello() {
        System.out.println("Hello World ~");
        return "Hello World ~";
    }

响应对象json 


    @RequestMapping("/getAddr")
    public Address getAddr() {
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        return addr;
    }

响应集合

 @RequestMapping("/listAddr")
    public List<Address> listAddr() {
        List<Address> list = new ArrayList<>();

        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");

        Address addr2 = new Address();
        addr2.setProvince("陕西");
        addr2.setCity("西安");

        list.add(addr);
        list.add(addr2);
        return list;
    }

Result.class

package com.itheima.pojo;

/**
 * 统一响应结果封装类
 */
public class Result {
    private Integer code ;//1 成功 , 0 失败
    private String msg; //提示信息
    private Object data; //数据 date

    public Result() {
    }
    public Result(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }

    public static Result success(Object data){
        return new Result(1, "success", data);
    }
    public static Result success(){
        return new Result(1, "success", null);
    }
    public static Result error(String msg){
        return new Result(0, msg, null);
    }

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

 对应响应代码:

  @RequestMapping("/hello")
    public Result hello() {
        System.out.println("Hello World ~");
        //return new Result(1,"success","Hello World ~");
        return Result.success("Hello World ~");
    }

    @RequestMapping("/getAddr")
    public Result getAddr() {
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        return Result.success(addr);
    }

    @RequestMapping("/listAddr")
    public Result listAddr() {
        List<Address> list = new ArrayList<>();

        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");

        Address addr2 = new Address();
        addr2.setProvince("陕西");
        addr2.setCity("西安");

        list.add(addr);
        list.add(addr2);
        return Result.success(list);
    }

 Springboot项目的静态资源(html,css,js等前端资源)默认存放目录为:classpath:/static、classpath:/public、classpath:/resou

 EmpController.class

package com.itheima.controller;

import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class EmpController {

    @RequestMapping("/listEmp")
    public Result list(){
        //1. 加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);

        //2. 对数据进行转换处理 - gender, job
        empList.stream().forEach(emp -> {
            //处理 gender 1: 男, 2: 女
            String gender = emp.getGender();
            if("1".equals(gender)){
                emp.setGender("男");
            }else if("2".equals(gender)){
                emp.setGender("女");
            }

            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
            String job = emp.getJob();
            if("1".equals(job)){
                emp.setJob("讲师");
            }else if("2".equals(job)){
                emp.setJob("班主任");
            }else if("3".equals(job)){
                emp.setJob("就业指导");
            }
        });

        //3. 响应数据
        return Result.success(empList);
    }

}
XmlParserUtils.class
package com.itheima.utils;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class XmlParserUtils {

    public static <T> List<T> parse(String file , Class<T> targetClass)  {
        ArrayList<T> list = new ArrayList<T>(); //封装解析出来的数据
        try {
            //1.获取一个解析器对象
            SAXReader saxReader = new SAXReader();
            //2.利用解析器把xml文件加载到内存中,并返回一个文档对象
            Document document = saxReader.read(new File(file));
            //3.获取到根标签
            Element rootElement = document.getRootElement();
            //4.通过根标签来获取 user 标签
            List<Element> elements = rootElement.elements("emp");

            //5.遍历集合,得到每一个 user 标签
            for (Element element : elements) {
                //获取 name 属性
                String name = element.element("name").getText();
                //获取 age 属性
                String age = element.element("age").getText();
                //获取 image 属性
                String image = element.element("image").getText();
                //获取 gender 属性
                String gender = element.element("gender").getText();
                //获取 job 属性
                String job = element.element("job").getText();

                //组装数据
                Constructor<T> constructor = targetClass.getDeclaredConstructor(String.class, Integer.class, String.class, String.class, String.class);
                constructor.setAccessible(true);
                T object = constructor.newInstance(name, Integer.parseInt(age), image, gender, job);

                list.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}

emp.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>员工信息</title>
</head>

<link rel="stylesheet" href="element-ui/index.css">
<script src="./js/vue.js"></script>
<script src="./element-ui/index.js"></script>
<script src="./js/axios-0.18.0.js"></script>

<body>
    <h1 align="center">员工信息列表展示</h1>
    <div id="app">
        <el-table :data="tableData" style="width: 100%"  stripe border >
            <el-table-column prop="name" label="姓名" align="center" min-width="20%"></el-table-column>
            <el-table-column prop="age" label="年龄" align="center" min-width="20%"></el-table-column>
            <el-table-column label="图像" align="center"  min-width="20%">
                <template slot-scope="scope">
                    <el-image :src="scope.row.image" style="width: 80px; height: 50px;"></el-image>
                </template>
            </el-table-column>
            <el-table-column prop="gender" label="性别" align="center"  min-width="20%"></el-table-column>
            <el-table-column prop="job" label="职位" align="center"  min-width="20%"></el-table-column>
        </el-table>
    </div>
</body>

<style>
    .el-table .warning-row {
        background: oldlace;
    }
    .el-table .success-row {
        background: #f0f9eb;
    }
</style>

<script>
    new Vue({
        el: "#app",
        data() {
            return {
                tableData: []
            }
        },
        mounted(){
            axios.get('/listEmp').then(res=>{
                if(res.data.code){
                    this.tableData = res.data.data;
                }
            });
        },
        methods: {
        }
    });
</script>
</html>

emp.xml

<?xml version="1.0" encoding="UTF-8" ?>
<emps>
    <emp>
        <name>金毛狮王</name>
        <age>55</age>
        <image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/1.jpg</image>
        <!-- 1: 男, 2: 女 -->
        <gender>1</gender>
        <!-- 1: 讲师, 2: 班主任 , 3: 就业指导 -->
        <job>1</job>
    </emp>

    <emp>
        <name>白眉鹰王</name>
        <age>65</age>
        <image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/2.jpg</image>
        <gender>1</gender>
        <job>1</job>
    </emp>

    <emp>
        <name>青翼蝠王</name>
        <age>45</age>
        <image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/3.jpg</image>
        <gender>1</gender>
        <job>2</job>
    </emp>

    <emp>
        <name>紫衫龙王</name>
        <age>38</age>
        <image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/4.jpg</image>
        <gender>2</gender>
        <job>3</job>
    </emp>
</emps>

3.5 分层解耦

3.5.1 三层架构

  • controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据
  • service:业务逻辑层,处理具体的业务逻辑。
  • dao:数据访问层(Data Access 0bject)(持久层),负责数据访问操作,包括数据的增、删、改、查。

EmpController.class

package com.itheima.controller;

import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.service.impl.EmpServiceA;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class EmpController {
    private EmpService empService = new EmpServiceA();
    @RequestMapping("/listEmp")
    public Result list(){
        //1. 调用service, 获取数据
        List<Emp> empList = empService.listEmp();
        //3. 响应数据
        return Result.success(empList);
    }


//    @RequestMapping("/listEmp")
//    public Result list(){
//        //1. 加载并解析emp.xml
//        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
//        System.out.println(file);
//        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
//
//        //2. 对数据进行转换处理 - gender, job
//        empList.stream().forEach(emp -> {
//            //处理 gender 1: 男, 2: 女
//            String gender = emp.getGender();
//            if("1".equals(gender)){
//                emp.setGender("男");
//            }else if("2".equals(gender)){
//                emp.setGender("女");
//            }
//
//            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
//            String job = emp.getJob();
//            if("1".equals(job)){
//                emp.setJob("讲师");
//            }else if("2".equals(job)){
//                emp.setJob("班主任");
//            }else if("3".equals(job)){
//                emp.setJob("就业指导");
//            }
//        });
//
//        //3. 响应数据
//        return Result.success(empList);
//    }

}

EmpDao.interface

package com.itheima.dao;

import com.itheima.pojo.Emp;

import java.util.List;

public interface EmpDao {
    //获取员工列表数据
    public List<Emp> listEmp();
}

EmpDaoA.class

package com.itheima.dao.ipml;

import com.itheima.dao.EmpDao;
import com.itheima.pojo.Emp;
import com.itheima.utils.XmlParserUtils;

import java.util.List;

public class EmpDaoA implements EmpDao {

    @Override
    public List<Emp> listEmp() {
        //1. 加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
        return empList;
    }
}

EmpService.interface

package com.itheima.service;

import com.itheima.pojo.Emp;

import java.util.List;

public interface EmpService {
    //获取员工列表
    public List<Emp> listEmp();
}

EmpServiceA.class

package com.itheima.service.impl;

import com.itheima.dao.EmpDao;
import com.itheima.dao.ipml.EmpDaoA;
import com.itheima.pojo.Emp;
import com.itheima.service.EmpService;

import java.util.List;

public class EmpServiceA implements EmpService {
    private EmpDao empDao = new EmpDaoA();

    @Override
    public List<Emp> listEmp() {
        //1. 调用dao, 获取数据
        List<Emp> empList = empDao.listEmp();
        //2. 对数据进行转换处理 - gender, job
        empList.stream().forEach(emp -> {
            //处理 gender 1: 男, 2: 女
            String gender = emp.getGender();
            if ("1".equals(gender)) {
                emp.setGender("男");
            } else if ("2".equals(gender)) {
                emp.setGender("女");
            }

            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
            String job = emp.getJob();
            if ("1".equals(job)) {
                emp.setJob("讲师");
            } else if ("2".equals(job)) {
                emp.setJob("班主任");
            } else if ("3".equals(job)) {
                emp.setJob("就业指导");
            }
        });
        return empList;
    }
}

 3.5.2 分层解耦

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
  • 软件设计原则:高内聚低耦合。

控制反转:

  • Inversion Of Control,简称I0C。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转

依赖注入:

  • DependencyInjection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

Bean对象:IOC容器中创建、管理的对象,称之为bean

 3.5.3 IOC与DI

3.5.3.1 入门

3.5.3.2 IOC详解

要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一

注解说明位置
@Component声明bean的基础注解不属于以下三类时,用此注解
@Controller@Component的衍生注解标注在控制器类上
@Service@Component的行生注解标注在业务类上
@Repository@Component的行生注解标注在数据访问类上(由于与mybatis整合,用的少)

 这里我自己总结了一下:就是controller(加@controller)层《=service(加@service)层中的数据《=dao层(加@repository),同时需要

在对应赋值的属性上添加@autowired

一层一层的套用,这就是内聚和解耦的合并


注意事项:

  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写(一般不用)
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。

Bean组件扫描
前面声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描。

  • @Componentscan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解
  • @SpringBootApplication中,默认扫描的范围是启动类所在包及其子包。
3.5.3.3 DI详解

Bean注入
@Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报出如下错误

通过以下几种方案来解决:

  • @Primary
  • @Qualifier
  • @Resource 

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值