目录
SpringMVC注解
@RestController
/*相当于:控制器类上@Controller + 方法上@ResponseBody
* 如果这个控制器类中的所有方法返回的都是json对象,则可选择此注解
* */
@RestController
public class StudentController {
@Autowired
StudentService studentService;
@RequestMapping(value = "/student")
public Object studetn(Integer id){
Student student = studentService.queryStudentById(id);
return student;
}
}
@GetMapping
// @RequestMapping(value = "/student", method = RequestMethod.GET)
/*@GetMapping就相当于上面这一个注解中把请求方式设置为get
该注解通常在查询时使用*/
@GetMapping(value = "/student")
public Object studetn(Integer id){
Student student = studentService.queryStudentById(id);
return student;
}
同理,还有一个@PostMapping
通常在新增数据时使用
此外还有@DeleteMapping
:常在删除时使用。@PutMapping
:常在修改时使用
但是,在没有特殊要求时,post请求使用居多。
RESTFul风格接口
概述
RESTFul是一种风格,而非标准,使用任何技术都可以实现这种理念。
如:一个地址为http://localhost:8080/order?id=1&age=12
则其RESTFul风格的地址为:http://localhost:8080/order/1/12
实现
@Controller
public class StudentController {
@RequestMapping(value = "/student/{id}/{age}")
@ResponseBody
public Object student(@PathVariable(value = "id") Integer id,
@PathVariable(value = "age") Integer age){
HashMap<Object, Object> map = new HashMap<>();
map.put("id", id);
map.put("age", age);
return map;
}
}
restful风格,因为地址栏中无法区分变量名,所以有时会出现路径冲突问题,此时可以根据功能“增删改查”的功能不同,使用不同的注解。或者修改变量在地址栏中的位置:/student/{id}/detail/{age}
和/student/detail/{id}/{age}
另外:restFul请求风格要求地址中的单词全部是名词,最好不要出现动词
集成Redis
依赖
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置
springboot主配置文件中添加:
spring.redis.port=6379
spring.redis.host=127.0.0.1
#密码默认为空
spring.redis.password=
使用
javaWeb笔记中有redis的使用
@Service
public class StudentServiceImpl implements StudentService {
//操作redis的对象,key和value都设置成object
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Override
public void put(String key, String value) {
//opsForValue()是操作String数据类型的,还有其他的set、hash等
redisTemplate.opsForValue().set(key, value);
}
@Override
public String get(String key) {
String value = (String) redisTemplate.opsForValue().get(key);
return value;
}
集成dubbo
安装zookeeper
下载apache-zookeeper-3.5.8-bin.tar.gz
解压
配置文件添加:
admin.serverPort=8888
修改data文件夹
dataDir=F:/apache-zookeeper-3.5.8-bin/tmp/zookeeper
创建
创建三个工程,一个空maven工程、两个springboot工程
接口工程
存放实体bean和业务接口
接口类
package com.wm.service;
public interface StudentService {
Integer queryAllStudentCount();
}
提供者
springboot框架项目,需要集成mybatis、redis
依赖:
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--注册中心-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!--接口工程-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>04-dubbo-interface</artifactId>
<version>1.0.0</version>
</dependency>
配置文件:
server.port=8081
server.servlet.context-path=/
#设置dubbo配置
spring.application.name=05-dubbo-provider
#设置当前工程是一个服务提供者
spring.dubbo.server=true
#设置注册中心
spring.dubbo.registry=zookeeper://localhost:2181
实现接口类:
package com.wm.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.wm.service.StudentService;
import org.springframework.stereotype.Component;
/*@Service这个疏解是dubbo的注解,而非spring的
* interfaceClass:暴露的接口类名
* version:服务提供者版本(我也不知道是什么的版本)
* */
@Component
@Service(interfaceClass = StudentService.class, version = "1.0.0", timeout = 15000)
public class StudentServiceImpl implements StudentService {
@Override
public Integer queryAllStudentCount() {
//假设这里已经调用持久层从数据库中查询处数据了
return 100;
}
}
dubbo注解的属性解释:
一、启动时检查(check)
默认情况下dubbo是开启自动检查的,即当项目启动时会自动检查其依赖的服务是否开启,如果没开是会阻止spring的初始化的,即check=true;我们可以将check置为false来关闭启动时检查,如我们在测试或者对其他服务没有依赖的时候可以关闭检查;在springboot中我们可以进行如下配置来关闭启动时检查:
1、关闭某个服务的启动检查
在引用该服务的@Reference注解上添加check=false,即@Reference(check = false)
2、关闭所有服务的启动时检查
在application.properties中添加dubbo.consumer.check=false
二、超时(timeout,默认为1000),重试次数(retries)
超时:当消费者调用提供者时由于网络等原因有可能会造成长时间拿不到响应,而请求还在不断的发过来这就有可能造成线程阻塞,使用timeout设置超时时间当超过该时间就会抛出异常;设置如下:
当只针对某个服务时:@Reference(timeout=XXX)
当针对所有服务时:dubbo.consumer.timeout=XXX
重试次数:当调用失败或超时后重新尝试调用的次数,其值不包含第一次
当只针对某个服务时:@Reference(retries=XXX)
当针对所有服务时:dubbo.consumer.retries=XXX
三、多版本(灰色发布)
当出现系统版本升级时,新版本有可能不够稳定,这时候可以通过设置version来进行平滑的过渡,下面是dubbo官网的版本迁移步骤:
在低压力时间段,先升级一半提供者为新版本,再将所有消费者升级为新版本,然后将剩下的一半提供者升级为新版本
而新旧版本我们可以通过version来定义,假设老版本的version=1.0.0新版本的version=2.0.0;
老版本服务提供者:@Service(version='1.0.0')
新版本服务提供者:@Service(version='2.0.0')
老版本服务消费者:@Reference(version='1.0.0')
新版本服务消费者:@Reference(version='2.0.0')
这样新旧版本就完美错开,只会调用version对应的服务,如果调用的时候不需要区分版本号,则进行如下配置:@Reference(version='*'),这样dubbo会默认在新老版本中随机调用
springboot启动类:
package com.wm;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication//开启springboot注解配置
@EnableDubboConfiguration//开启dubbo配置
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
消费者
依赖:
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--注册中心-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!--接口工程-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>04-dubbo-interface</artifactId>
<version>1.0.0</version>
</dependency>
配置文件:
server.port=8080
server.servlet.context-path=/
#dubbo配置
spring.application.name=06-dubbo-consumer
#设置注册中心
spring.dubbo.registry=zookeeper://localhost:2181
调用服务层
package com.wm.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.wm.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class StudentController {
//这里的注解属性可以参考上面提供者的
@Reference(interfaceClass = StudentService.class,
version = "1.0.0",
check = false)
private StudentService studentService;
@RequestMapping(value = "/student/queryCount")
@ResponseBody
public Object queryCount(){
Integer count = studentService.queryAllStudentCount();
return "学生总数为:"+ count;
}
}
springboot启动类
package com.wm;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication//开启springboot注解配置
@EnableDubboConfiguration//开启dubbo配置
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
运行
运行zookeeper
,再依次启动服务提供者、服务消费者即可
集成ssm-redis-dubbo
搭建
使用mybatis逆向工程生成实体类、dao接口、mapper映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- <properties resource="mybatis.properties" />
-->
<classPathEntry location="F:\Context\apache-maven-3.6.1-bin\apache-maven-3.6.1\maven_repo\mysql\mysql-connector-java\5.1.47\mysql-connector-java-5.1.47.jar" />
<context id="msqlTables" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>
<!--阻止生成注释-->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection connectionURL="jdbc:mysql://localhost:3306/spring"
driverClass="com.mysql.jdbc.Driver" password="root" userId="root" >
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="com.wm.model"
targetProject="F:\wmjava\SpringBootStudy\04-dubbo-interface\src\main\java">
<property name="enableSubPackages" value="true"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.wm.mapper" targetProject="src\main\java">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成dao接口的-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.wm.mapper" targetProject="src\main\java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--数据库表-->
<table tableName="student" domainObjectName="Student"
enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false" >
<property name="useActualColumnNames" value="false"/>
</table>
</context>
</generatorConfiguration>
需要注意的是:此文件放在服务提供者目录下,实体类生成在接口工程下,所以需要在javaModelGenerator
标签中修改目录
接口工程
package com.wm.model;
import java.io.Serializable;
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private static final long serialVersionUID = 1L;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
package com.wm.service;
import com.wm.model.Student;
public interface StudentService {
Student queryStudent(Integer id);
Integer queryAllStudentCount();
}
提供者
依赖
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--注册中心-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!--接口工程-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>04-dubbo-interface</artifactId>
<version>1.0.0</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
springboot配置文件
server.port=8081
server.servlet.context-path=/
#连接数据库
#设置连接数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
#设置dubbo配置
spring.application.name=05-dubbo-provider
#设置当前工程是一个服务提供者
spring.dubbo.server=true
#设置注册中心
spring.dubbo.registry=zookeeper://localhost:2181
#设置redis
spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=
插件
<build>
<!--映射文件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--逆向工程插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<configurationFile>generatorConfig.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
dao接口
package com.wm.mapper;
import com.wm.model.Student;
public interface StudentMapper {
int deleteByPrimaryKey(Integer id);
int insert(Student record);
int insertSelective(Student record);
Student selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Student record);
int updateByPrimaryKey(Student record);
//此方法为自己添加,其余是逆向工程生成的
Integer queryAllStudentCount();
}
mapper文件
其余为自动生成
<select id="queryAllStudentCount" resultType="java.lang.Integer">
select count(id) from student
</select>
sercice实现类
package com.wm.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.wm.mapper.StudentMapper;
import com.wm.model.Student;
import com.wm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
@Service(interfaceName = "com.wm.service.StudentService",
version = "1.0.0", timeout = 15000)
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
//redis
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Override
public Student queryStudent(Integer id) {
return studentMapper.selectByPrimaryKey(id);
}
@Override
public Integer queryAllStudentCount() {
//查询redis,如果有就直接使用,如果没有则去数据库查询存入redis
Integer count = (Integer) redisTemplate.opsForValue().get("allStudentCount");
if (null == count){
//去数据库查
count = studentMapper.queryAllStudentCount();
redisTemplate.opsForValue().set("allStudentCount", count, 15, TimeUnit.SECONDS);
}
return count;
}
}
springboot启动类
package com.wm;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication//开启springboot注解配置
@EnableDubboConfiguration//开启dubbo配置
@MapperScan(basePackages = "com.wm.mapper")//扫描mapper包下的所有类
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
消费者
依赖
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--注册中心-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!--接口工程-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>04-dubbo-interface</artifactId>
<version>1.0.0</version>
</dependency>
<!--jsp-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
插件
打包jsp文件,和打包mapper文件同理
<resources>
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>*.*</include>
</includes>
</resource>
</resources>
配置文件
server.port=8080
server.servlet.context-path=/
#dubbo配置
spring.application.name=06-dubbo-consumer
#设置注册中心
spring.dubbo.registry=zookeeper://localhost:2181
#视图解析器
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
controller类
package com.wm.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.wm.model.Student;
import com.wm.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class StudentController {
@Reference(interfaceName = "com.wm.service.StudentService",
version = "1.0.0",
check = false)
private StudentService studentService;
@RequestMapping(value = "/student/detail/{id}")
public String studentDetail(Model model,
@PathVariable("id") Integer id){
Student student = studentService.queryStudent(id);
model.addAttribute("student", student);
return "studentDetail";
}
@RequestMapping(value = "/student/count")
@ResponseBody
public Object queryAllStudentCount(){
Integer count = studentService.queryAllStudentCount();
return "学生总人数为:"+count;
}
}
jsp
首先创建一个webapp文件夹,然后将其设置为webapp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>学生详情</title>
</head>
<body>
<h3>编号:${student.id}</h3>
<h3>姓名:${student.name}</h3>
<h3>年龄:${student.age}</h3>
</body>
</html>
启动类
package com.wm;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication//开启springboot注解配置
@EnableDubboConfiguration//开启dubbo配置
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
运行
启动redis服务器端、启动zookeeper、再依次启动服务提供者、服务消费者。
在浏览器上输入http://localhost:8080/student/detail/2
http://localhost:8080/student/count