本项目目标是开发一个社区网站,拥有发帖、讨论、搜索、登陆等一个正常社区拥有的功能。涉及到的版本参数为:html
- JDK1.8
- Maven3.8.1(直接集成到IDEA)
- Springboot 2.5.1
- tomcat
参考网站(在使用框架过程当中可能会看的开发文档):前端
https://mvnrepository.com/ 查找maven依赖java
https://mybatis.org/mybatis-3/zh/index.html mybatis的官方文档,配置等都有说明mysql
项目代码已发布到github https://github.com/GaoYuan-1/web-projectgit
关于数据库文件,该篇博客中已有提到,可去文中github获取数据 MySQL基础篇(一)github
本文第一篇只介绍了基础,在(二)中将会介绍如何实现登陆界面等后续内容。最终将会把完整项目经历发布出来。web
本系列主要介绍的是实战内容,对于理论知识介绍较少,适合有必定基础的人。spring
首先建立一个项目,可利用Spring Initializrsql
本人配置以下:数据库
maven项目的
pom.xml
中初始依赖以下,后面会增长更多依赖。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
记录一些基本概念,Spring的知识可能说的比较少,本篇关注于如何对网站进行实现。
Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。
Spring 容器会自动完成@bean对象的实例化。
建立应用对象之间的协做关系的行为称为:装配(wiring),这就是依赖注入的本质。
在使用 Spring Initializr
以后,第一个接触的注解为:
@SpringBootApplication
咱们能够把 @SpringBootApplication
看做是 @Configuration
、@EnableAutoConfiguration
、@ComponentScan
注解的集合。
根据 SpringBoot
官网,这三个注解的做用分别是:
@EnableAutoConfiguration
:启用 SpringBoot 的自动配置机制@ComponentScan
: 扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下全部的类。@Configuration
:容许在 Spring 上下文中注册额外的 bean 或导入其余配置类(表示该类是配置类)Spring经过识别一些注解可让容器自动装填bean:
关于@Scope,负责声明Bean的做用域:
@Scope("singleton") //惟一 bean 实例,Spring 中的 bean 默认都是单例的。 @Scope("prototype") //每次请求都会建立一个新的 bean 实例。 @Scope("request") //每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。 @Scope("session") //每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
关于@Autowired:
自动导入对象到类中,被注入进的类一样要被 Spring 容器管理。从构造器,到方法,到参数、属性、注解,均可以加上@Autowired注解。
能够先了解一些HTTP流的相关知识:(参考自MDN Web Docs)
当客户端想要和服务端进行信息交互时(服务端是指最终服务器,或者是一个中间代理),过程表现为下面几步:
打开一个TCP链接:TCP链接被用来发送一条或多条请求,以及接受响应消息。客户端可能打开一条新的链接,或重用一个已经存在的链接,或者也可能开几个新的TCP链接连向服务端。
发送一个HTTP报文:HTTP报文(在HTTP/2以前)是语义可读的。在HTTP/2中,这些简单的消息被封装在了帧中,这使得报文不能被直接读取,可是原理还是相同的。
GET / HTTP/1.1 Host: developer.mozilla.org Accept-Language: fr
读取服务端返回的报文信息:
HTTP/1.1 200 OK Date: Sat, 09 Oct 2010 14:28:02 GMT Server: Apache Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT ETag: "51142bc1-7449-479b075b2891b" Accept-Ranges: bytes Content-Length: 29769 Content-Type: text/html <!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
关闭链接或者为后续请求重用链接。
当HTTP流水线启动时,后续请求均可以不用等待第一个请求的成功响应就被发送。然而HTTP流水线已被证实很难在现有的网络中实现,由于现有网络中有不少老旧的软件与现代版本的软件共存。所以,HTTP流水线已被在有多请求下表现得更稳健的HTTP/2的帧所取代。
HTTP请求的例子:
响应的例子:
三层架构:表现层,业务层和数据访问层。
MVC:Model(模型层),View(视图层),Controller(控制层)
核心组件: DispatcherServlet
若是想给浏览器返回一个动态网页,则须要一个工具支持,例如:Thymeleaf(模板引擎,生成动态的HTML)。
该引擎须要学习的有:标准表达式,判断与循环,模板的布局。
学习建议参考官方文档 https://www.thymeleaf.org/index.html
@RequestMapping支持Servlet的request和response做为参数,如下为一个简单示例:
@Controller @RequestMapping("/alpha") public class AlphaController { @RequestMapping("/hello") @ResponseBody public String sayHello(){ return "Hello Spring Boot."; } @RequestMapping("/http") public void http(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取请求数据 System.out.println(request.getMethod()); System.out.println(request.getServletPath());//请求路径 Enumeration<String> enumeration = request.getHeaderNames();//获得请求行的key while(enumeration.hasMoreElements()) { String name = enumeration.nextElement(); //当前值(key) String value = request.getHeader(name);//获得value System.out.println(name + ":" + value); } System.out.println(request.getParameter("code")); // 返回响应数据 response.setContentType("text/html;charset=utf-8");//返回网页类型的文本 PrintWriter writer = response.getWriter(); writer.write("<h1>牛客网</h1>");//这里只进行简单输出 writer.close(); } }
在项目Controller层加入代码,以response体返回一个html的文本。
这是经过底层对象处理请求的方式,便于理解。
更简单的方式为:
// GET请求,用于获取某些数据 // /students?current=1&limit=20 假设查询学生数据,第一页,每页20条 @RequestMapping(path = "/students", method = RequestMethod.GET) @ResponseBody // public String getStudents(int current,int limit) { //直接使用Int类型,前端控制器会自动识别匹配 // System.out.println(current); // System.out.println(limit); // return "some students"; // } // 也可加上注解 public String getStudents( @RequestParam(name = "current", required = false, defaultValue = "1") int current, @RequestParam(name = "limit", required = false, defaultValue = "1") int limit) { System.out.println(current); System.out.println(limit); return "some students"; }
利用@ResponseBody注解,实现效果为:
控制台返回结果:
利用这种方式,不管是返回数据仍是获取数据都很方便。
另外,经过路径方式传参查询的话:(注意,路径长度并非无限的,并不能够传不少参数)
// /student/123 查询某个学生,直接放在路径中 @RequestMapping(path = "/student/{id}", method = RequestMethod.GET) @ResponseBody public String getStudent(@PathVariable("id") int id) { System.out.println(id); return "a student"; }
注意以上传参时使用的两个注解。
如何向浏览器提交数据?
在项目静态文件中添加html文件,action指示路径
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>增长学生</title> </head> <body> <form method="post" action="/community/alpha/student"> <p> 姓名:<input type="text" name="name"> </p> <p> 年龄:<input type="text" name="age"> </p> <p> <input type="submit" value="保存"> </p> </form> </body> </html>
//POST请求 @RequestMapping(path = "/student", method = RequestMethod.POST) @ResponseBody public String saveStudent(String name, int age) { System.out.println(name); System.out.println(age); return "success"; }
在Controller中代码以下,展现效果:
控制台:
从程序内部响应到HTML
//响应HTML数据 @RequestMapping(path = "/teacher", method = RequestMethod.GET) public ModelAndView getTeacher() { //这个对象就是向前端控制器返回的moder和view ModelAndView mav = new ModelAndView(); mav.addObject("name", "张三"); mav.addObject("age", 30); mav.setViewName("/demo/view");//这个view实际上指的是view.html return mav; }
Controller代码
此外,还须要一个动态网页,利用thymeleaf模板引擎(resource/templates)。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <!--声明这不是html文件,而是一个thymeleaf模板--> <head> <meta charset="UTF-8"> <title>Teacher</title> </head> <body> <p th:text="${name}"></p> <p th:text="${age}"></p> </body> </html>
实现效果,程序已经设定初始值。
模板引擎会自动进行处理。
另外一种方式:
@RequestMapping(path = "/school", method = RequestMethod.GET) public String getSchool(Model model) { //前端控制器会建立一个model model.addAttribute("name","大学"); model.addAttribute("age",80); return "/demo/view"; //这里return的是view的路径 }
这两种方式是model和view的对象使用方式不一样。效果仍是一致的,第二种要更加简便一些。
异步请求能够理解为:当前网页不刷新,可是进行了数据交互,好比注册帐号时,常常会检测用户名是否重复,这时候网页并无刷新,可是访问了数据库进行查询。
//响应JSON数据(异步请求) // Java对象传给浏览器:须要转为JS对象,这时候就能够经过JSON进行转化 // Java对象-> JSON字符串 -> JS对象等等 @RequestMapping(path = "/emp", method = RequestMethod.GET) @ResponseBody public Map<String,Object> getEmp() { //自动会将map转为JSON字符串 Map<String,Object> emp = new HashMap<>(); emp.put("name","张三"); emp.put("age",23); emp.put("salary",8000.00); return emp; }
注意,这里并无返回html。
这里只是简单介绍了响应方式,之后的博客中会介绍具体应用及代码。
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎全部的 JDBC 代码以及设置参数和获取结果集的工做。MyBatis 能够经过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
在maven项目pom.xml中添加依赖
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency>
在SpringBoot框架下,只须要对application.properties进行配置,增长以下:
# 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=Ss6215615 #设置链接池,这个比较好 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 # MybatisProperties mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.nowcoder.community.entity mybatis.configuration.useGeneratedKeys=true #自动匹配 a_b == aB mybatis.configuration.mapUnderscoreToCamelCase=true # logger,设置日志,方便在控制台查看信息 logging.level.com.nowcoder.community=debug
mybatis.type-aliases-package=com.nowcoder.community.entity
这行代码声明了SQL中记录在Java中的对象位置,根据SQL中的属性创建对象。
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 Date createTime; //等等,还有set,get,toString
创建对象以后,在项目中的dao文件,创建UserMapper(对于User的操做)接口,Mybatis只须要经过xml文件对操做进行声明。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.nowcoder.community.dao.UserMapper"> <!-- 这里写UserMapper的全限定名 --> <sql id="selectFields"> id, username, password, salt, email, type, status, activation_code, header_url, create_time </sql> <sql id="insertFields"> username, password, salt, email, type, status, activation_code, header_url, create_time </sql> <select id="selectById" resultType="User"> <!-- 配置里进行过设置package,不然须要写全限定名 --> select <include refid="selectFields"></include> from user where id = #{id} <!-- 这里的意思是要引用方法的参数 --> </select> <select id="selectByName" resultType="User"> <!-- 配置里进行过设置package,不然须要写全限定名 --> select <include refid="selectFields"></include> from user where username = #{username} <!-- 这里的意思是要引用方法的参数 --> </select> <select id="selectByEmail" resultType="User"> <!-- 配置里进行过设置package,不然须要写全限定名 --> select id, username, password, salt, email, type, status, activation_code, header_url, create_time from user where 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 user set status = #{status} where id = #{id} </update> <update id="updateHeader"> update user set header_url = #{headerUrl} where id = #{id} </update> <update id="updatePassword"> update user set password = #{password} where id = #{id} </update> </mapper>
这里创建了增删改的操做。
mybatis.mapper-locations=classpath:mapper/*.xml
根据已有的配置在resource文件夹中创建mapper目录和.xml文件。
因为.xml文件不会自动检测编译,建议在test中依次测试相应功能,以避免出现错误。
本项目计划使用SpringBoot框架进行一个社交网站的开发,首先使用Spring Initializr对maven项目进行创建,以后对Spring的基本概念进行了必定阐述,IOC和AOP均没有讲到,将会在后续开放的Spring学习篇中,对SpringMVC的基本使用(GET,POST请求和响应数据)进行了代码示范,方便理解后续代码。另外,介绍了Mybatis的使用,以及公布了部分示范代码。
上手起来是很是快的,本系列的目的在于,重点讲解实战部分,理论部分将在其余博客中展开。
下篇博客将会对网站的登录界面等如何实现进行阐述。