02-springcloud实践案例-新闻案例

项目结构图

在这里插入图片描述

Eureka 注册中心

在这里插入图片描述

CloudNewEurekaApplication

@SpringBootApplication
@EnableEurekaServer
public class CloudNewEurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudNewEurekaApplication.class, args);
    }

}

application.yml

spring:
  application:
    name: cloud-news-eureka

server:
  port: 8899

eureka:
  instance:
    hostname: eurekaDemo
  client:
    service-url:
      defaultZone: http://127.0.0.1:${server.port}/eureka
    register-with-eureka: false
    fetch-registry: false

网关

在这里插入图片描述

CloudNewsZuulApplication

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class CloudNewsZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudNewsZuulApplication.class, args);
    }

}

application.yml

spring:
  application:
    name: cloud-news-zuul
server:
  port: 8877

eureka:
  client:
    registry-fatch-interval-seconds: 5 # 获取服务列表的周期
    service-url:
      defaultZone: http://127.0.0.1:8899/eureka

zuul:
  routes:
    springCloudDemoService: #路由名称 通常是微服务的名称
      path: /cloud-news-query/**  #映射路径
      serviceId: cloud-news-query #微服务id

utlis工具模块

在这里插入图片描述

CodeEnum

public enum CodeEnum {
    SUCCESS(200, "success"),
    FAil(400, "active error"),
    UNFOUNDED(404, "not found"),
    ERROR(500, "error");
    public Integer code;
    public String message;

    CodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

ResultDTO

public class ResultDTO<T> {
    private Integer code;
    private String message;
    private T data;

    public ResultDTO(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public ResultDTO() {
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResultDTO{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data.toString() +
                '}';
    }
}

ResultUtil

public class ResultUtil {
    public static <T> ResultDTO<T> success(T data) {
        return new ResultDTO<T>(CodeEnum.SUCCESS.code, CodeEnum.SUCCESS.message, data);
    }

    public static <T> ResultDTO<T> success() {
        return new ResultDTO<T>(CodeEnum.SUCCESS.code, CodeEnum.SUCCESS.message, null);
    }

    public static <T> ResultDTO<T> success(String message, T data) {
        return new ResultDTO<T>(CodeEnum.SUCCESS.code, message, data);
    }

    public static <T> ResultDTO<T> error(Integer code, String message) {
        return new ResultDTO<T>(code, message, null);
    }

    public static <T> ResultDTO<T> error(Integer code, String message, T data) {
        return new ResultDTO<T>(code, message, data);
    }
}

pojo模块

在这里插入图片描述

Category

public class Category {
    private int id;
    private String cname;

    public Category() {
    }

    public Category(int id, String cname) {
        this.id = id;
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", cname='" + cname + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}

News

public class News {
    private  int id;
    private int categoryid;
    private String title;
    private String summary;
    private String author;
    private Date createDate;

    public News() {
    }

    public News(int id, int categoryid, String title, String summary, String author, Date createDate) {
        this.id = id;
        this.categoryid = categoryid;
        this.title = title;
        this.summary = summary;
        this.author = author;
        this.createDate = createDate;
    }

    @Override
    public String toString() {
        return "News{" +
                "id=" + id +
                ", categoryid=" + categoryid +
                ", title='" + title + '\'' +
                ", summary='" + summary + '\'' +
                ", author='" + author + '\'' +
                ", createDate=" + createDate +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getCategoryid() {
        return categoryid;
    }

    public void setCategoryid(int categoryid) {
        this.categoryid = categoryid;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }
}

mapper模块

在这里插入图片描述

CategoryMapper

@Mapper
@Repository
public interface CategoryMapper {
    @Select("select * from category")
    List<Category> findCategoryAll();

}

CategoryMapper.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">
<!-- namespace;命名空间 -->
<mapper namespace="pre.cg.cloudnewsmapper.mapper.CategoryMapper">

</mapper>

NewsMapper

@Mapper
@Repository
public interface NewsMapper {
    @Select("select * from news")
    List<News> findNewsAll();


    @Select("select * from news where id = #{id}")
    News findNewsById(@Param("id") Integer id);

    @Update("update news set title=#{title},summary=#{summary},author=#{author} where id=#{id}")
    int updateNewsById(News news);

    @Select("select *  from news where categoryid = #{categoryid} and title like concat('%',#{title},'%') ")
    List<News> findByCategoryIdTitle(News news);

    @Select("select *  from news where title like concat('%',#{title},'%') ")
    List<News> findByCategoryTitle(News news);
}

NewsMapper.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">
<!-- namespace;命名空间 -->
<mapper namespace="pre.cg.cloudnewsmapper.mapper.NewsMapper">

</mapper>

查询query模块

在这里插入图片描述

application.yml

spring:
  application:
    name: cloud-news-query
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    name: defaultDataSource
    url: jdbc:mysql://localhost:3306/cgmybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: root
server:
  port: 8081


eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8899/eureka

CloudNewsQueryApplication

@SpringBootApplication
@EnableEurekaClient
@MapperScan("pre.cg.cloudnewsmapper.mapper")
public class CloudNewsQueryApplication {
    public static void main(String[] args) {
        SpringApplication.run(CloudNewsQueryApplication.class, args);
    }

}

CategoryController

@RestController
public class CategoryController {
    @Autowired
    CategoryService categoryService;

    @GetMapping("/queryCategory")
    public ResultDTO<List<Category>> queryCategory() {
        List<Category> categoryAll = categoryService.findCategoryAll();
        ResultDTO<List<Category>> success = ResultUtil.success(categoryAll);
        return success;
    }
}

NewsQueryController

@RestController
public class NewsQueryController {

    @Autowired
    NewsService newsService;


    @GetMapping("/queryNews")
    public ResultDTO<List<News>> queryNews() {
        List<News> newsAll = newsService.findNewsAll();
        ResultDTO<List<News>> success = ResultUtil.success(newsAll);
        return success;
    }

    @GetMapping("/queryNewById")
    public ResultDTO<News> queryNewById(@RequestParam(name = "id") Integer id) {
        News newsById = newsService.findNewsById(id);
        return ResultUtil.success(newsById);
    }

    @PostMapping("/findByCategoryIdTitle")
    public ResultDTO<List<News>> findByCategoryIdTitle(@RequestBody News news) {
        List<News> newsList = null;
        if (news.getCategoryid() == 0) {
            newsList = newsService.findByCategoryTitle(news);
        } else {
            newsList = newsService.findByCategoryIdTitle(news);
        }
        return ResultUtil.success(newsList);
    }`public interface NewsService {
    List<News> findNewsAll();

    News findNewsById(Integer id);

    List<News> findByCategoryIdTitle(News news);

    List<News> findByCategoryTitle(News news);
}`

}

CategoryService

public interface CategoryService {
    List<Category> findCategoryAll();
}

CategoryServiceImpl

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Override
    public List<Category> findCategoryAll() {
        return categoryMapper.findCategoryAll();
    }
}

NewsServiceImpl

@Service
public class NewsServiceImpl implements NewsService {

    @Autowired
    NewsMapper newsMapper;

    @Override
    public List<News> findNewsAll() {
        return newsMapper.findNewsAll();
    }

    @Override
    public News findNewsById(Integer id) {
        return newsMapper.findNewsById(id);
    }

    @Override
    public List<News> findByCategoryIdTitle(News news) {
        return newsMapper.findByCategoryIdTitle(news);
    }

    @Override
    public List<News> findByCategoryTitle(News news) {
        return newsMapper.findByCategoryTitle(news);
    }
}

Edit模块

在这里插入图片描述

application.yml

spring:
  application:
    name: cloud-news-edit
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    name: defaultDataSource
    url: jdbc:mysql://localhost:3306/cgmybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: root
server:
  port: 8082

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8899/eureka

CloudNewsEditApplication

@SpringBootApplication
@EnableEurekaClient
@MapperScan("pre.cg.cloudnewsmapper.mapper")
public class CloudNewsEditApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudNewsEditApplication.class, args);
    }

}

NewsEditController

@RestController
public class NewsEditController {
    @Autowired
    NewsEditService newsEditService;

    @PostMapping("/updateNewsById")
    public ResultDTO<Integer> updateNewsById(@RequestBody News news) {
        int i = newsEditService.updateNewsById(news);
        return ResultUtil.success(i);
    }
}

NewsEditService

public interface NewsEditService {
    int updateNewsById(News news);
}

NewsEditServiceImpl

@Service
public class NewsEditServiceImpl implements NewsEditService {
    @Autowired
    NewsMapper newsMapper;

    @Override
    public int updateNewsById(News news) {
        return newsMapper.updateNewsById(news);
    }
}

web模块

在这里插入图片描述

application.yml

spring:
  application:
    name: cloud-news-web
  thymeleaf:
    cache: false
    encoding: UTF-8
    suffix: .html
    mode: HTML
server:
  port: 9090

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8899/eureka

#cloud-news-query:
#  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule


hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000

#feign 开启熔断器
feign:
  hystrix:
    enabled: true

CloudNewsWebApplication

@SpringBootApplication
feign
@EnableFeignClients
熔断的注解
@EnableCircuitBreaker
//@SpringCloudApplication
//注册中心
@EnableEurekaServer
public class CloudNewsWebApplication {


    public static void main(String[] args) {
        SpringApplication.run(CloudNewsWebApplication.class, args);
    }

}

NewsFeignClient

@FeignClient(value = "cloud-news-query", qualifier = "cloud-news-query", fallback = NewsClientFallback.class)
public interface NewsFeignClient {

    @LoadBalanced
    @GetMapping("/queryNews")
    ResultDTO<List<News>> queryNews();

    @LoadBalanced
    @GetMapping("/queryCategory")
    ResultDTO<List<Category>> queryCategory();


    @LoadBalanced
    @GetMapping("/queryNewById")
    ResultDTO<News> queryNewById(@RequestParam(name = "id") Integer id);

    @LoadBalanced
    @PostMapping("/findByCategoryIdTitle")
    ResultDTO<List<News>> findByCategoryIdTitle(@RequestBody News news);
}

NewsEditFeignClient

@FeignClient(value = "cloud-news-edit",qualifier = "cloud-news-edit",fallback = NewsClientFallback.class)
public interface NewsEditFeignClient {
    @LoadBalanced
    @PostMapping("/updateNewsById")
    ResultDTO<Integer> updateNewsById(@RequestBody News news);
}

NewsEditFeignClient

@Component
public class NewsClientFallback implements NewsFeignClient,NewsEditFeignClient{
    @Override
    public ResultDTO<List<News>> queryNews() {
        return ResultUtil.error(CodeEnum.FAil.code,"请求超时");
    }

    @Override
    public ResultDTO<List<Category>> queryCategory() {
        return ResultUtil.error(CodeEnum.FAil.code,"请求超时");
    }

    @Override
    public ResultDTO<News> queryNewById(Integer id) {
        return ResultUtil.error(CodeEnum.FAil.code,"请求超时");
    }

    @Override
    public ResultDTO<List<News>> findByCategoryIdTitle(News news) {
        return ResultUtil.error(CodeEnum.FAil.code,"请求超时");
    }

    @Override
    public ResultDTO<Integer> updateNewsById(News news) {
        return ResultUtil.error(CodeEnum.FAil.code,"请求超时");
    }
}

NewsController

@Controller
public class NewsController {


    @Qualifier("cloud-news-query")
    @Autowired
    NewsFeignClient newsFeignClient;

    @Qualifier("cloud-news-edit")
    @Autowired
    NewsEditFeignClient newsEditFeignClient;

    @GetMapping("/queryNews")
    public ModelAndView queryNews(@ModelAttribute("newsCondition") News news) {
        ModelAndView modelAndView = new ModelAndView();
        ResultDTO<List<News>> newsResultDTO = newsFeignClient.queryNews();
        ResultDTO<List<Category>> categoryResultDTO = newsFeignClient.queryCategory();
        modelAndView.addObject("newsList", newsResultDTO.getData());
        modelAndView.addObject("cateList", categoryResultDTO.getData());
        modelAndView.setViewName("index");
        return modelAndView;
    }


    @GetMapping("/toUpdate/{id}")
    public ModelAndView toupdate(@PathVariable int id) {
        ModelAndView modelAndView = new ModelAndView();

        ResultDTO<News> newsResultDTO = newsFeignClient.queryNewById(id);
        ResultDTO<List<Category>> categoryResultDTO = newsFeignClient.queryCategory();

        modelAndView.addObject("newsDetail", newsResultDTO.getData());
        modelAndView.addObject("categoryList", categoryResultDTO.getData());
        modelAndView.setViewName("updateNews");
        return modelAndView;
    }

    @PostMapping("/doUpdateSubmit")
    public String doUpdateSubmit(News news) {
        ResultDTO<Integer> integerResultDTO = newsEditFeignClient.updateNewsById(news);
        return "redirect:/queryNews";
    }


    @PostMapping("/queryByCondition")
    public ModelAndView queryByCondition(@ModelAttribute("newsCondition") News news) {
        ModelAndView modelAndView = new ModelAndView();
        ResultDTO<List<News>> newsResultDTO = newsFeignClient.findByCategoryIdTitle(news);
        ResultDTO<List<Category>> categoryResultDTO = newsFeignClient.queryCategory();
        modelAndView.addObject("newsList", newsResultDTO.getData());
        modelAndView.addObject("cateList", categoryResultDTO.getData());
        modelAndView.setViewName("index");
        return modelAndView;
    }
}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>新闻列表</title>
</head>
<body>
<form action="/queryByCondition" method="post">
    新闻分类
    <select name="categoryid">
        <option value="0">全部</option>
        <option th:each="category:${cateList}"
                th:value="${category.id}"
                th:text="${category.cname}"
                th:selected="${newsCondition.categoryid==category.id}"></option>
    </select>
    标题
    <input type="text" name="title" th:value="${newsCondition.title}"/>
    <input type="submit" value="查    询"/>
</form>

<table border="1px" width="90%">
    <tr th:each="news:${newsList}">
        <td th:text="${news.id}"></td>
        <td th:text="${news.title}"></td>
        <td th:text="${news.summary}"></td>
        <td th:text="${news.author}"></td>
        <td>
            <a th:href="'/toUpdate/'+${news.id}">编辑</a>
        </td>
    </tr>
</table>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>新闻编辑</title>
</head>
<body>

<form action="/doUpdateSubmit" method="post">
	<table width="40%" border="1px">
		<input type="hidden" name="id" th:value="${newsDetail.id}"/>
		<tr>
			<td>标题</td>
			<td><input type="text"  name="title" th:value="${newsDetail.title}">
			</td>
		</tr>
		<tr>
			<td>类别</td>
			<td>
				<select name="categoryid">
					<option value="0">全部</option>
					<option th:each="category:${categoryList}" 
					        th:value="${category.id}"
					        th:text="${category.cname}"
					        th:selected="${category.id==newsDetail.categoryid}"></option>
				</select>
			</td>
		</tr>
		<tr>
			<td>作者</td>
			<td><input type="text" name="author" th:value="${newsDetail.author}"></td>
		</tr>
		<tr>
			<td>摘要</td>
			<td><textarea cols="33" rows="8" name="summary" th:text="${newsDetail.summary}"></textarea></td>
		</tr>
		<tr>
			<td colspan="2">
				<input type="submit" value="提     交">
			</td>
		</tr>
	</table>
</form>
</body>
</html>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值