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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/529459.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows中如何将已安装的node.js版本进行更换

第一步&#xff1a;先清除已经安装好的node.js版本 1.按健winR弹出窗口&#xff0c;键盘输入cmd,然后敲回车&#xff08;或者鼠标直接点击电脑桌面最左下角的win窗口图标弹出&#xff0c;输入cmd再点击回车键&#xff09; 然后进入命令控制行窗口&#xff0c;并输入where node…

camunda7多租户技术架构和测试验证

多租户考虑的是单个 Camunda 安装应该为多个租户提供服务的情况&#xff0c;是实现SaaS化的重要技术手段。对于每个租户&#xff0c;应做出一定的隔离保证。例如&#xff0c;一个租户的流程实例不应干扰另一租户的流程实例。 多租户可以通过两种不同的方式实现。一种方法是每个…

php导出excel文件

环境 php7.4hyperf3composer require phpoffice/phpspreadsheet代码 class IndexController extends AbstractController { /*** Inject* var Picture*/private $picture;public function index(){$res_data[]["robot" > 哈哈机器人,"order" > TES…

深入理解Java中的线程安全List:CopyOnWriteArrayList原理和应用

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java并发编程中&#xff0c;线程安全的数据结构是至关重要的。其中&#xff0c;CopyOnWriteArrayList是一个线程安全的ArrayLis…

JDK的下载

Oracle官网下载链接&#xff1a; Java Archive | Oracle 选中指定版本&#xff0c;进行下载即可&#xff1a;

STM32CubeMX学习笔记18——SD卡(SDIO接口)

1、简介 1.1 SD卡简介 很多单片机系统都需要大容量存储设备&#xff0c;以存储数据&#xff08;常用的有U盘、FLASH芯片、SD卡等&#xff09;&#xff0c;比较而言SD卡是单片机大容量外部存储的首选&#xff0c;只需要少数几个IO口即可外扩一个容量从几十M到几十G的&#xff…

操作系统(1)——学习导论(Ⅲ)

目录 小程一言专栏链接: [link](http://t.csdnimg.cn/6grrU)本篇文章因内容需要&#xff0c;且依靠书中内容达不到小程想要的效果&#xff0c;so部分内容依赖其他网络资源 学习导论&#xff08;Ⅲ&#xff09;操作系统相关概念进程——Process线程——Thread调度——Scheduling…

超越DragGAN和DragDiffusion!StableDrag:基于点的图像编辑新框架(南大腾讯) 原创 Yutao Cui等 AI生成未来

超越DragGAN和DragDiffusion&#xff01;StableDrag:基于点的图像编辑新框架(南大&腾讯) 原创 Yutao Cui等 AI生成未来 文章链接&#xff1a;https://arxiv.org/pdf/2403.04437 开源地址&#xff1a;https://stabledrag.github.io/ 基于点的图像编辑自DragGAN出现以来就引…

qemu快速入门

前提&#xff1a; 我们做嵌入式软件的时候&#xff0c;往往可能会缺少嵌入式的硬件&#xff0c;那我们希望提前开始准备代码的话&#xff0c;就需要qemu这个开源软件&#xff0c;它可以模拟各种型号的芯片 。那么我们可以提前在这个模拟器上面去开发代码、验证、调试。 正片开始…

MySQL临时表创建出错(OS errno 13 - Permission denied)

一个客户向我抱怨&#xff1a;在MySQL查询小表没有问题&#xff0c;查询大表出错&#xff0c;下面是他发给我的出错的部分截屏&#xff08;客户的表名被我隐藏了&#xff09;。 这里的给出的信息已经比较明显了&#xff0c;是向/tmp目录中创建临时表失败&#xff08;临时表的路…

多核多cluster多系统之间缓存一致性概述

目录 1.思考和质疑2.怎样去维护多核多系统缓存的一致性2.1多核缓存一致性2.2多Master之间的缓存一致性2.3dynamIQ架构同一个core中的L1和L2 cache 3.MESI协议的介绍4.ACE维护的缓存一致性5.软件定义的缓存和替换策略6.动图示例 本文转自 周贺贺&#xff0c;baron&#xff0c;代…

基于4G的水质参数远程监测系统研究

基于4G的水质参数远程监测系统研究 摘 要 近年来随着我国经济飞速的发展&#xff0c;对水资源的破坏也日益严重。无论是生活需求用水还是工业废水的处理都存在这严重问题&#xff0c;由于水质净化技术的不成熟&#xff0c;对水质监测的实时性存在着很大的缺陷&#xff0c;水污…