当前位置: 首页 > news >正文

Day16:HTTP协议、Spring MVC、Thymeleaf模版引擎、Spring处理浏览器请求实例(传入和传出)、MyBatis

HTTP

  • HyperText Transfer Protocol:超文本传输协议
  • 规定了浏览器和服务器之间如何通信,以及通信时的数据格式。

image

  • 为什么有这么多?浏览器先收到html,再根据html内容接受图片、css、js等文件。

Spring MVC

  • 三层架构:表现层、业务层、数据访问层

image

  • MVC设计模式:M:model(模型,用来封装数据), V:view(视图,用来渲染展现), C:controller(控制,用于控制行为)
  • 核心组件:前端控制器:DispatcherServlet

image

Thymeleaf模版引擎

  • 模版引擎的作用:生成动态的html
  • Thymeleaf:模版引擎的一种,倡导自然模板,即以HTML文件为模板。
  • 原理:

image

Spring处理浏览器请求实例(繁琐方式)

  1. 开发时在application.properties将Thymeleaf的缓存关闭(不然界面刷新慢,上线要打开):
server.port=8888
server.servlet.context-path=/communityspring.thymeleaf.cache=false
  1. 明确三个层(表现层、业务层、数据层)和表现层M和V和C的代码之后会写在哪里。
  • Model:spring自带 。

image

  1. 在controller->alphaController类中添加http方法,包含一些常见的获取请求/设置响应的方法:
@RequestMapping("/http")public void http(HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println(request.getMethod());//获取请求方式System.out.println(request.getServletPath());//获取请求路径Enumeration<String> enumeration = request.getHeaderNames();while(enumeration.hasMoreElements()){String name = enumeration.nextElement();String value = request.getHeader(name);System.out.println(name + ':' + value);}System.out.println(request.getParameter("code"));//response给浏览器返回响应数据response.setContentType("text/html; charset=utf-8");PrintWriter writer = response.getWriter();writer.write("<h1>gmz</h1>");writer.close();}
  • @RequestMapping(“/http”):映射路径到localhost:8080/community中
  • HttpServletRequest request请求对象,HttpServletResponse response响应对象;
  • Enumeration enumeration = request.getHeaderNames();获取header名字,是一个迭代器,用Enumeration接;
  • request.getHeader(name);获取特定名字的header的值。
  • response.setContentType(“text/html; charset=utf-8”);设置响应类型是html,字符集是utf-8
  • PrintWriter writer = response.getWriter();用PrintWriter写。

运行结果:

image

(这里把code传进来了,通过http://localhost:8888/community/alpha/http?code=123的?)

Spring处理浏览器请求实例(简便方式)

通过?获取参数值:(GET)

   //GET//查询所有的学生:路径/students?current=1&limit=20@RequestMapping(path = "/students", method = RequestMethod.GET)@ResponseBodypublic String getStudents(@RequestParam(name = "current", required = false, defaultValue = "1") int current,@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) {System.out.println(current);System.out.println(limit);return "some students";}
  • @RequestMapping(path = “/students”, method = RequestMethod.GET)拓展了注解,说明路径是/students,且请求方式是GET
  • @RequestParam(name = “current”, required = false, defaultValue = “1”)这是一个注解, 表明通过current识别对应参数,不是必须要通过?传过来的参数,默认值是1

通过/路径获取参数值:(GET)

    @RequestMapping(path = "student/{id}", method = RequestMethod.GET)@ResponseBodypublic String getStudent(@PathVariable(name = "id") int id) {System.out.println(id);return "A student";}
  • @PathVariable(name = “id”) int id注解表示把/{id}中的内容赋值给id变量。

通过绑定参数名获取参数:(POST)

  • 为什么用POST?
    • GET传参用明文,不安全;
    • GET传的数据有限(URL长度有限)
  • 编写示例html:(static/html/student.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>增加学生</title>
</head>
<body><form method="post" action="/community/alpha/student"><label>姓名:</label><input type="text" id="name" name="name"><br><label>年龄:</label><input type="text" id="age" name="age"><br><input type = "submit" value = "提交"></form></body>
</html>
  • 在controller中:
    @RequestMapping(path = "/student", method = RequestMethod.POST)@ResponseBodypublic String saveStudent(String name, int age){System.out.println(name);System.out.println(age);return "success";}
  • @RequestMapping(path = “/student”, method = RequestMethod.POST)设置请求类型为POST。
  • POST获取参数很简单,之间表明参数名和html中设置的表单的参数名一样即可。

在HTML表单中,所有的输入都是作为字符串处理的。当你在表单中输入年龄并提交时,这个年龄值会作为字符串发送到服务器。在你的Spring Boot应用中,Spring MVC会尝试将这个字符串转换为你在处理方法中指定的类型,也就是int。 在你的例子中,public String saveStudent(String name, int age),Spring MVC会尝试将age参数从字符串转换为int。如果转换成功,那么这个方法就可以正常工作。如果转换失败(例如,如果用户输入的不是一个数字),那么Spring MVC会抛出一个类型转换异常。 这就是为什么你可以在HTML表单中将年龄设置为文本输入,然后在服务器端将其处理为int的原因。Spring MVC在背后处理了类型转换。

向浏览器响应数据(HTML):GET

之前都适用 @ResponseBody + return str的形式返回简单的字符串,现在考虑返回完成的html。

  1. 构建要返回的教师变量(参数):
   //响应HTML@RequestMapping(path = "/teacher", method = RequestMethod.GET)public ModelAndView getTeacher(){ModelAndView modelAndView = new ModelAndView();modelAndView.addObject("name", "张三");modelAndView.addObject("age", "30");modelAndView.setViewName("demo/view");//实际是view.htmlreturn modelAndView;
  • ModelAndView:要返回的数据封装出的对象;
  • modelAndView.addObject(name,value):添加对象对;
  • modelAndView.setViewName(“demo/view”):把封装了数据的model封装到对应的动态template的路径去。这里的view其实省略了.html。
  1. 在templates中编写网页html:
<!DOCTYPE html>
<html lang="en", xmlns:th="http://www.thymeleaf.org">
<!--当前网页是一个模版-->
<head><meta charset="UTF-8"><title>Teacher</title>
</head>
<body>
<p th:text="${name}"></p>
<p th:text="${age}"></p></body>
</html>
  • 假如xmlns:th="http://www.thymeleaf.org"说明是一个thymeleaf的模版。

向浏览器响应数据(HTML)简便:GET

    @RequestMapping(path = "/school", method = RequestMethod.GET)public String getSchool(Model model){model.addAttribute("name", "北京大学");model.addAttribute("age", "100");return "/demo/view";}
  • 更加简单,这里传入一个Model参数,是dispatcherServlet管理的,我们只需要把model中的信息填进去。
  • return的字符串是路径

向浏览器响应json数据(异步请求):

  • 异步请求:比如注册时填入用户名并移动鼠标时就会判断用户名是否符合要求(查数据库),但页面没有刷新
  • 需要转换:Java对象 -> JSON字符串 -> JS对象
//Json数据(异步请求)
//需要转换:Java对象 -> JSON字符串 -> JS对象
@RequestMapping(path = "/emp", method = RequestMethod.GET)
@ResponseBody//加上这个注解,返回的数据不会被解析为html,而是直接返回为json
public Map<String, Object> getEmp(){Map<String, Object> emp = new HashMap<>();emp.put("name", "张三");emp.put("age", 23);emp.put("salary", 8000.00);return emp;
}

image

返回多个json:

@RequestMapping(path = "/emps", method = RequestMethod.GET)@ResponseBody//加上这个注解,返回的数据不会被解析为html,而是直接返回为jsonpublic List<Map<String, Object>> getEmps(){List<Map<String, Object>> list = new ArrayList<>();Map<String, Object> emp = new HashMap<>();emp.put("name", "张三");emp.put("age", 23);emp.put("salary", 8000.00);list.add(emp);Map<String, Object> emp2 = new HashMap<>();emp2.put("name", "李四");emp2.put("age", 24);emp2.put("salary", 9000.00);list.add(emp2);return list;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MySQL

安装MySQL server

brew install mysql
  • 启动服务:
brew services start mysql
  • 客户端连接本地:
mysql -u root -p
  • 修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
FLUSH PRIVILEGES;
  • 导入相关的sql建表语句:
source /Users/iris/Desktop/community-init-sql-1.5/init_schema.sql;

安装MySQL WorkBench客户端

  • 之前的命令行不好看,搞个可视化的。
  • 安装地址:https://dev.mysql.com/downloads/file/?id=525970
  • 界面张这个样子:

image

MyBatis

  • 核心组件
    • SqlSessionFactory:用于创建SqlSession的工厂类。(Spring自动)
    • SqlSession:MyBatis的核心组件,用于向数据库执行SQL。(Spring自动)
    • 主配置文件:XML配置文件,可以对MyBatis的底层行为做出详细的配置。(Spring自动)
    • Mapper接口:就是DAO接口,在MyBatis中习惯性的称之为Mapper。
    • Mapper映射器:用于编写SQL,并将SQL和实体类映射的组件,采用XML、注解均可实现。

示例:使用MyBatis对user表进行CRUD(增删改查)操作

  1. 导入MySQL(Maven)
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.2.0</version>
</dependency>
  1. 导入MyBatis
  <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency>
  1. 在application.properties中配置mysql:
# DataSourceProperties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/community?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=lihonghe
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000//超时多久才关空闲 
  1. 在application.properties中配置mybatis:
# MybatisProperties
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.nowcoder.community.entity
mybatis.configuration.useGeneratedKeys=true//自动生成主键
mybatis.configuration.mapUnderscoreToCamelCase=true//不区分下划线和驼峰,互相匹配
  1. 创建User的实体类:entity.User:
public class User {private int id;private String username;private String password;private String salt;private String email;private int type;private int status;private String activationCode;private String headerUrl;private java.util.Date createTime;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getSalt() {return salt;}public void setSalt(String salt) {this.salt = salt;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public int getType() {return type;}public void setType(int type) {this.type = type;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public String getActivationCode() {return activationCode;}
  • 根据sql表中的属性一一对应;
  • 添加getter和setter
  • 重写to_string()方法方便打印;
  1. 创建UserMapper接口:dao.UserMapper
@Mapper
public interface UserMapper {User selectById(int id);User selectByName(String username);User selectByEmail(String email);int insertUser(User user);int updateStatus(int id, int status);int updateHeader(int id, String headerUrl);int updatePassword(int id, String password);}
  • 只要接口,Mapper会自动生成SQL语句的实现类;

  • 使用Mapper注解表明这是一个与Mapper相关的Bean;

    1. 创建user-mapper.xml的配置文件:resources/mapper/user-mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newcoder.community.dao.UserMapper"><sql id="insertFields">username, password, salt, email, type, status, activation_code, header_url, create_time</sql><sql id="selectFields">id, username, password, salt, email, type, status, activation_code, header_url, create_time</sql><select id="selectById" resultType="User">select<include refid="selectFields"></include>from userwhere id = #{id}</select><select id="selectByName" resultType="User">select<include refid="selectFields"></include>from userwhere username = #{username}</select><select id="selectByEmail" resultType="User">select<include refid="selectFields"></include>from userwhere email = #{email}</select><insert id="insertUser" parameterType="User" keyProperty="id">insert into user (<include refid="insertFields"></include>)values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl},#{createTime})</insert><update id="updateStatus">update userset status = #{status}where id = #{id}</update><update id="updateHeader">update userset header_url = #{headerUrl}where id = #{id}</update><update id="updatePassword">update userset password = #{password}where id = #{id}</update></mapper>
  • namespace注明是为哪个Mapper Bean服务的(全名)

  • 各种各样的标签表明增删查改方法;

  • resultType:返回的类型——实体类User;

  • parameterType:传入的参数类型——实体类User

  • keyProperty:主键

  • #{username}:User中要用的值的占位值

  • 可以使用标签服用一些字段,使用插入。

  1. 编写测试类和测试函数:
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MapperTests {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectUser() {User user = userMapper.selectById(101);System.out.println(user);user = userMapper.selectByName("liubei");System.out.println(user);user = userMapper.selectByEmail("nowcoder101@sina.com");System.out.println(user);}@Testpublic void testInsertUser() {User user = new User();user.setUsername("test");user.setPassword("lala");user.setSalt("abc");user.setEmail("adsd@mail.ustc.edu.cn");user.setHeaderUrl("http://www.nowcoder.com/101.png");user.setCreateTime(new java.util.Date());int rows = userMapper.insertUser(user);System.out.println(rows);System.out.println(user.getId());}@Testpublic void testUpdateUser() {int rows = userMapper.updateStatus(150, 1);System.out.println(rows);rows = userMapper.updateHeader(150, "http://www.nowcoder.com/102.png");System.out.println(rows);rows = userMapper.updatePassword(150, "hello");System.out.println(rows);}
}
  • @Autowired:依赖注入;
  • Test: Junit的注解;
  1. 调试方便,把日志级别定义为DEBUG:applications.properties
# logger
logging.level.com.newcoder.community=debug

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spring Boot中Excel数据导入导出的高效实现
  • Linux--基础命令
  • 在linux上部署yolov5和安装miniconda3
  • Nestjs与Vue实现多人聊天[简易版]
  • Java中的常见类“Math”(一)用法详解
  • 项目中spring security与jwt.腾讯面试分享
  • ARM GNU 汇编 “每日读书“
  • 2.1基本算法之枚举1978:生理周期
  • opencv人脸识别实战2:刷脸功能(PyCharm实现)
  • 测试开发(6)软件测试教程——自动化测试selenium(自动化测试介绍、如何实施、Selenium介绍 、Selenium相关的API)
  • python INI文件操作与configparser内置库
  • 零难度!台式电脑如何连接蓝牙耳机?简单几步完成
  • 推特API(Twitter API)V2 查询用户信息
  • vscode的c++开发环境配置
  • SDK集群模式数据库中,ETCD起什么作用?
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Android 架构优化~MVP 架构改造
  • C语言笔记(第一章:C语言编程)
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • leetcode讲解--894. All Possible Full Binary Trees
  • MD5加密原理解析及OC版原理实现
  • mockjs让前端开发独立于后端
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 看域名解析域名安全对SEO的影响
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 突破自己的技术思维
  • 走向全栈之MongoDB的使用
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 数据可视化之下发图实践
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​决定德拉瓦州地区版图的关键历史事件
  • # windows 安装 mysql 显示 no packages found 解决方法
  • #微信小程序:微信小程序常见的配置传旨
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (1)SpringCloud 整合Python
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (第一天)包装对象、作用域、创建对象
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET 指南:抽象化实现的基类
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】