JavaWeb阶段学习知识点(一)

【参考视频】https://www.bilibili.com/video/BV1m84y1w7Tb?p=167&vd_source=38a16daddd38b4b4d4536e9c389e197f

SpringBoot项目的创建和接口配置

做一个springboot项目,从创建项目到实现浏览器访问localhost:8080/hello返回字符串hello world的全流程

1. 创建项目

  • idea
  • 新建项目
  • Spring initializr->配置选择语言:java类型:maven组:com.jwz包名:com.jwz打包:jar
  • 选择web->spring web
  • finish

创建完成项目后可以把.idea、.mvn、.gitignore、HELP.md、mvnw、mvnw.cmd等无关项目的文件和文件夹删除

2.配置接口

在项目的com.jwz下新建controller包再创建HelloController.java文件,放入以下内容

package com.jwz.sprdemo02.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";
    }
}

然后找到项目默认生成的Application.java的文件,右键运行即可

浏览器访问:http://localhost:8080/hello 即可显示Hello World

获取参数

原始方式

package com.jwz.sprdemo02.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

// 请求处理类
@RestController
public class HelloController {
   
    // 定义接口名
    @RequestMapping("/hello")
    public String hello(HttpServletRequest request){
   
        // 浏览器访问:http://localhost:8080/hello?name=萧寂&age=18
        
        // 获取get请求参数
        String name = request.getParameter("name");
        String age = request.getParameter("age");

        int ageInt = Integer.parseInt(age);
        System.out.println(name+ageInt);
        return name+ageInt;
    }
}

SpringBoot方式

package com.jwz.sprdemo02.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

// 请求处理类
@RestController
public class HelloController {
   
    // 定义接口名
    @RequestMapping("/hello")
    public String hello(@RequestParam("name") String name ,@RequestParam("age") Integer age){
   
        System.out.println(name+":"+age);
        return name+age;
    }
}

// get请求:http://localhost:8080/hello?name=萧寂&age=18
// post请求:http://localhost:8080/hello  在body的x-www-form-urlencoded里面添加对应参数即可
// 上面获取参数方法可以获取get和post参数的,只是请求方法和参数的传递方式有点区别

参数对应不上的情况

// 下面这个方法,比如我请求地址和传参为:http://localhost:8080/hello?name=萧寂&age=18
// 可以发现,参数没有username 只有name,那么RequestParam这个注解就可以指定参数,当匹配到RequestParam指定的属性的值时也默认这个值为username的值,如果匹配不到RequestParam指定的参数,则会抛出400错误,如下所示,第二个参数改为false,代表此参数不是必填的,则不会报错,会将当前参数为null
public String hello(@RequestParam(value = "name",required = false) String username ,@RequestParam("age") Integer age){
   
    // 此时匹配到name="萧寂" 也就相当于username="萧寂"
        System.out.println(username+":"+age);
        return username+age;
    }

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

参数接收

实体参数

package com.jwz.sprdemo02.user;

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

public class simplePojo {
   
    private String name;
    private Integer age;

    public simplePojo() {
   
    }

    public simplePojo(String name, Integer age) {
   
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
   
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
   
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public Integer getAge() {
   
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(Integer age) {
   
        this.age = age;
    }

    public String toString() {
   
        return "simplePojo{name = " + name + ", age = " + age + "}";
    }
}

@RestController
class ControllerSimplePojo{
   
    // 实体参数
    @RequestMapping("/simplePojo")
    public String simplePojo(simplePojo simplePojo){
   
        // 访问如下地址: http://localhost:8080/simplePojo?name=萧寂&age=18
        System.out.println(simplePojo); // simplePojo{name = 萧寂, age = 18}

        // 访问如下地址: http://localhost:8080/simplePojo?age=18
        // 不传哪个哪个就为null
        System.out.println(simplePojo); // simplePojo{name = null, age = 18}
        return "OK";
    }
}

数组集合参数

    @RequestMapping("/arrayHobby")
    public String arrayHobby(@RequestParam("hobby") String[] hobby){
   
        // 请求方式get,地址为:http://localhost:8080/arrayHobby?hobby=篮球&hobby=跳绳&hobby=足球
        System.out.println(Arrays.toString(hobby)); // [篮球, 跳绳, 足球]
        return "OK";
    }

// 使用集合接收
    @RequestMapping("/listHobby")
    public String listHobby(@RequestParam("hobby") List<String> hobby){
   
        // 请求方式get,地址为:http://localhost:8080/listHobby?hobby=篮球&hobby=跳绳&hobby=足球
        System.out.println(hobby); // [篮球, 跳绳, 足球]
        return "OK";
    }

日期参数

    @RequestMapping("/dateParams")
    public String dateParams(@RequestParam("updateTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
   
        // 请求方式get,地址为:http://localhost:8080/dateParams?updateTime=2024-04-27 10:00:25
        System.out.println(updateTime); // 2024-04-27T10:00:25
        return "OK";
    }

JSON参数

package com.jwz.sprdemo02.json;

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

class Address {
   
    private String province;
    private String city;

    public Address(String province, String city) {
   
        this.province = province;
        this.city = city;
    }

    public Address() {
   
    }

    public String getProvince() {
   
        return province;
    }

    public void setProvince(String province) {
   
        this.province = province;
    }

    public String getCity() {
   
        return city;
    }

    public void setCity(String city) {
   
        this.city = city;
    }

    @Override
    public String toString() {
   
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

class User {
   
    private String name;
    private Integer age;
    private Address address;


    public User() {
   
    }

    public User(String name, Integer age, Address address) {
   
        this.name = name;
        this.age = age;
        this.address = address;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
   
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
   
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public Integer getAge() {
   
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(Integer age) {
   
        this.age = age;
    }

    /**
     * 获取
     * @return address
     */
    public Address getAddress() {
   
        return address;
    }

    /**
     * 设置
     * @param address
     */
    public void setAddress(Address address) {
   
        this.address = address;
    }

    public String toString() {
   
        return "User{name = " + name + ", age = " + age + ", address = " + address + "}";
    }
}



@RestController
class ControllerUser{
   
    @RequestMapping("/jsonParams")
    public String jsonParams(@RequestBody User jsonParams){
    // 接收到的参数交给User去处理
        // 请求方式post,地址为:http://localhost:8080/jsonParams  参数在apifox的body的json里面填写json数据{"name":"萧寂","age":16,"address":{"province":"北京","city":"北京"}}
        // 这里有个小问题,json数据格式和raw的一样,如果在json填写数据后再点击raw然后去发请求,此时参数是raw里面的,我这里返回来了415错误,也就是说在json里面写完参数必须直接发请求,不要切换到其他栏,都会报错
        System.out.println(jsonParams); // User{name = 萧寂, age = 16, address = Address{province='北京', city='北京'}}
        return "OK";
    }
}

路径参数

就是http 😕/localhost:8080/add/1/123 这个1和123就是路径上面携带的参数

    @RequestMapping("/pathParams/{id}/{preId}")
    public String pathParams(@PathVariable("id") Integer id,@PathVariable("preId") Integer preId){
   
        // 请求方式get,地址为:http://localhost:8080/pathParams/1/1234
        System.out.println(id+":"+preId); // 1:1234
        return "OK";
    }

封装统一的返回格式

{
    code:0,
    msg:"成功",
    data:[...]
}

工具类

package com.jwz.sprdemo02.controller;

public class Result {
   
    private Integer code;
    private String msg;
    private Object data;

    public Result() {
   
    }

    public Result(Integer code, String msg, Object data) {
   
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 获取
     * @return code
     */
    public Integer getCode() {
   
        return code;
    }

    /**
     * 设置
     * @param code
     */
    public void setCode(Integer code) {
   
        this.code = code;
    }

    /**
     * 获取
     * @return msg
     */
    public String getMsg() {
   
        return msg;
    }

    /**
     * 设置
     * @param msg
     */
    public void setMsg(String msg) {
   
        this.msg = msg;
    }

    /**
     * 获取
     * @return data
     */
    public Object getData() {
   
        return data;
    }

    /**
     * 设置
     * @param data
     */
    public void setData(Object data) {
   
        this.data = data;
    }

    // 响应成功调用
    // 这里使用了方法重载,成功的情况分为三种(自定义成功后的消息内容和接口返回的数据,使用默认的success文字和接口返回的数据,还有一种情况只响应成功结果但不需要返回数据)
    public static Result success(Object data,String msg){
   
        return new Result(1,msg,data);
    }
    public static Result success(Object data){
   
        return new Result(1,"success",data);
    }
    public static Result success(){
   
        return new Result(1,"success",null);
    }
    // 响应失败调用
    // 失败只会有一种情况(自定义提示失败的消息,数据为null)
    public static Result error(String msg){
   
        return new Result(0,msg,null);
    }

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

三层架构

项目结构

dao daoImpl service serviceImpl controller

dao和service均是接口

daoImpl和serviceImpl和controller是三层架构的核心

daoImpl负责数据访问操作 serviceImpl负责数据的逻辑层处理 controller负责接收数据响应数据

这里我需要实现一个逻辑,运用三层架构的思路实现

浏览器访问参数num为多少,则返回当前传入的num的值+1

1.项目三层架构的结构如下

在这里插入图片描述

2.对各层进行代码编写,从前往后写

dao代码如下

package com.jwz.sprdemo02.dao.service.dao.dao;

public interface dao {
   
    public Integer daoA(Integer num);
}

daoImpl代码如下

package com.jwz.sprdemo02.dao.service.dao.dao;

public class daoImpl implements dao{
   
    @Override
    public Integer daoA(Integer num) {
   
        // 这里用于对数据进行初始化和访问
        // 这里是做demo,我返回的值是传入进来的数据,后期要拿这个传入的参数做数据库查询数据,查询到了返回出去的
        return num;
    }
}

service代码如下

package com.jwz.sprdemo02.dao.service.dao.service;

public interface service {
   
    public String serviceA(Integer num);
}

serviceImpl代码如下

package com.jwz.sprdemo02.dao.service.dao.service;

import com.jwz.sprdemo02.dao.service.dao.dao.daoImpl;

public class serviceImpl implements service{
   
    // 由于这里service和dao未关联,所以拿不到dao的数据,因此要在这里创建daoImpl的对象,用于拿到数据
    private daoImpl dao = new daoImpl();
    @Override
    public String serviceA(Integer num) {
   
        // 这里用于对数据进行业务的处理
        // 例如,调用daoImpl里面的方法,拿到初始化访问到的数据
        
        // 其实这里已经拿到传入的参数值了,我其实可以直接返回这个数据的,但是要演示三层架构功能还是把参数传给dao,让dao返回数据给我们,后期学完数据库后,这些参数传给dao用于进行数据查询,然后会返回查询到的数据,这里就先模拟下,传入num就返回num了,写个注释避免被说多此一举
        Integer i = dao.daoA(num); 
        int sum = i+1;
        return "传入的num+1的值是"+sum;
    }
}

分层解耦

内聚:软件中各个功能模块内部的功能联系。

耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

软件设计原则:高内聚低耦合。

控制反转: Inyersion OfControl,简称I0C。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
依赖注入:DependencyIniection,简称Dl。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
Bean对象:I0C容器中创建、管理的对象,称之为bean。

依赖注入和控制反转

上面的三层架构的案例,如果我们的serviceImpl改了个名字比如叫serviceImpl1则controller层的代码也要改变,当项目架构比较大,项目比较多的话,也就相当于所有依赖serviceImpl的类都要去手动修改,使项目变得难以维护,依赖注入控制反转的思想就是将所有的实现类Impl(daoImpl和serviceImpl)的类上面都加个@Component注解,这样的话相当于把所有的实现类都加入到容器内部了,在我们需要创建这个实现类的时候,只需要在这个代码上面加一个@Autowired即可,这样就实现了自动注入,即即使代码改了名,项目都是去容器内部去自动注入的,而改代码的实现类又被加入到容器内部了,相当于可以自动更新了,这样的话项目维护成本就低了

将上面的三层架构的daoImpl和serviceImpl和controller代码进行小小改造,改造如下

daoimpl

package com.jwz.sprdemo02.dao.service.dao.dao;

import org.springframework.stereotype.Component;

@Component //将当前类交给IOC容器管理,成为IOC容器中的bean
public class daoImpl implements dao{
   
    @Override
    public Integer daoA(Integer num) {
   
        // 这里用于对数据进行初始化和访问
        // 这里是做demo,我返回的值是传入进来的数据
        return num;
    }
}

serviceImpl

package com.jwz.sprdemo02.dao.service.dao.service;
import com.jwz.sprdemo02.dao.service.dao.dao.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

//将当前类交给IOC容器管理,成为IOC容器中的bean
@Component
public class serviceImpl implements service{
   
    // 由于这里service和dao未关联,所以拿不到dao的数据,因此要在这里创建daoImpl的对象,用于拿到数据
    @Autowired //运行时,IOC容器会提供该类型的bean对象,并值给该变依赖注入
    private dao dao; // 类型是接口的类型(多态写法)
    @Override
    public String serviceA(Integer num) {
   
        // 这里用于对数据进行业务的处理
        // 例如,调用daoImpl里面的方法,拿到初始化访问到的数据
        Integer i = dao.daoA(num); // 1234
        int sum = i+1;
        return "传入的num+1的值是"+sum; // 1235
    }
}

controller

package com.jwz.sprdemo02.dao.service.dao.controller;

import com.jwz.sprdemo02.dao.service.dao.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class controller {
   
    // 创建serviceImpl对象
    @Autowired //运行时,IOC容器会提供该类型的bean对象,并赋值给该变量  -- 依赖注入
    private service s; // 类型是接口类型

    // 定义接口,请求和响应数据
    @RequestMapping("/helloNum")
    public String hello(@RequestParam("num") Integer num) {
   
        String i = s.serviceA(num);
        return i;
    }
}

@Component的注解有三个不同的衍生注解,@Repository,标注daoImpl数据访问层,@Service标注业务实现层,@Controller标注在数据响应层,建议不属于这三类的层再使用@Component注解,上面的衍生注解功能和@Component一致,主要为了区分业务

Bean注入存在的问题

  • @Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报出如下错误:
  • 在这里插入图片描述

可以通过以下方案来解决

  • @Primary (想让哪个Bean生效就在哪个Bean上面价格@Primary,如下

    • package com.jwz.sprdemo02.dao.service.dao.service;
      import com.jwz.sprdemo02.dao.service.dao.dao.dao;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      @Primary 
      //将当前类交给IOC容器管理,成为IOC容器中的bean
      @Component
      public class serviceImpl implements service{
             
          // 由于这里service和dao未关联,所以拿不到dao的数据,因此要在这里创建daoImpl的对象,用于拿到数据
          @Autowired //运行时,IOC容器会提供该类型的bean对象,并值给该变依赖注入
          private dao dao; // 类型是接口的类型(多态写法)
          @Override
          public String serviceA(Integer num) {
             
              // 这里用于对数据进行业务的处理
              // 例如,调用daoImpl里面的方法,拿到初始化访问到的数据
              Integer i = dao.daoA(num); // 1234
              int sum = i+1;
              return "传入的num+1的值是"+sum; // 1235
          }
      }
      
  • @Qualifier(在使用bean时上面价格@Qualifier注解,表明使用哪个bean,如下)

    • package com.jwz.sprdemo02.dao.service.dao.controller;
      
      import com.jwz.sprdemo02.dao.service.dao.service.service;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class controller {
             
          // 创建serviceImpl对象
          @Qualifier("serviceImpl") //  bean名字,不指定的话默认类名首字母小写
          @Autowired //运行时,IOC容器会提供该类型的bean对象,并赋值给该变量  -- 依赖注入
          private service s; // 类型是接口类型
      
          // 定义接口,请求和响应数据
          @RequestMapping("/helloNum")
          public String hello(@RequestParam("num") Integer num) {
             
              String i = s.serviceA(num);
              return i;
          }
      }
      
  • @Resource(功跟autowire一样,只是autowire是自动注入,而Resource是根据Bean名称进行注入的)

    • package com.jwz.sprdemo02.dao.service.dao.controller;
      
      import com.jwz.sprdemo02.dao.service.dao.service.service;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class controller {
             
          // 创建serviceImpl对象
          @Resource(name = "serviceImpl") //  bean名字,不指定的话默认类名首字母小写
          private service s; // 类型是接口类型
      
          // 定义接口,请求和响应数据
          @RequestMapping("/helloNum")
          public String hello(@RequestParam("num") Integer num) {
             
              String i = s.serviceA(num);
              return i;
          }
      }
      

Mysql相关

mysql所有相关命令

-- 终端连接远程mysql命令
-- mysql -h远程地址 -P端口号 -u用户名 -p密码
mysql -h139.196.214.124 -P3306 -uceshaiaa -pxtZA8p7xEKBWLd6Wnd

-- 一:DDL部分相关命令(下述语法中的database,也可以替换成schema。如:create schema db01;select schema();)
-- 1:数据库操作
-- 1.1 查询
-- 1.1-1 查询所有的数据库
show databases;
-- 1.1-2 查询当前数据库
select database();
-- 1.2 使用
-- 1.2-1 使用数据库
use 数据库名;
-- 1.3 创建
-- 1.3-1 创建数据库(if not exists这是可选的,如果加上则代表:数据库存在不会报错也不会做任何操作,如果数据库不存在则会去创建)
create database [ if not exists ] 数据库名;
-- 1.4 删除
-- 1.4-1 删除数据库(if exists是可选参数,数据库不存在则不会做任何操作,也不会报错,如果存在就会去执行删除数据库操作)
drop database [ if exists ] 数据库名;
-- 2:表操作(带[]的都是可选参数)
-- 2.1 创建表
create table 表名(字段1 字段类型 [约束] [comment 字段1注释],.....,字段n 字段类型 [约束] [comment 字段n注释])[comment 表注释];
-- 2.1-1 示例(id主键自增,用户名非空且唯一,姓名非空,性别默认为男,都是加了约束的)
create table user(
	id int primary key auto_increment comment 'ID字段,唯一标识',
	username varchar(20) not null unique comment '用户名',
	name varchar(10) not null comment '姓名',
	age int comment '年龄',
	gender char(1) default '男' comment '性别'
) comment '用户表';
-- 2.2 查询表
-- 2.2-1 查询当前数据库的所有表
show tables;
-- 2.2-2 查询表结构
desc 表名;
-- 2.2-3 查询建表语句
show create table 表名;
  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寂173

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值