文章目录
什么是REST
REST介绍
AB动词
C:嵌套 改正:articles?authors_id-12
D:应该是/articles/2
RestController 实例
package cn.edu.nchu.springmvc_mvn;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1.0")
public class DemoRestController {
@Autowired
private StudentFactory sf;
// https://localhost:8080/api/v1.0/students/3
@RequestMapping(value="/students/{no}",method=RequestMethod.GET)
@ResponseBody
public Student students(@PathVariable("no") String no) {
return sf.find(no);
}
// https://localhost:8080/api/v1.0/students/
@RequestMapping(value="/students",method=RequestMethod.GET)
@ResponseBody
public List<Student> students() {
return sf.getStudents();
}
}
json的使用
自定义异常类
定义自定义异常类 StudentNoFoundException
public class StudentNoFoundException extends Exception{
public int getCode() {
return 101;
}
public String getMessage() {
return"this student not found";
}
}
在StudentFactory中抛异常
public Student find(String no) throws StudentNoFoundException{
List<Student> list = this.getStudents();
Student s = list.stream().filter(x -> x.getNo().equals(no)).findFirst().orElse(null);
if(s == null) {
throw new StudentNoFoundException();
}else {
return s;
}
}
在DemoRestController中抛异常
// https://localhost:8080/api/v1.0/students/no1
@ApiOperation(value=" find one student 17203113")
@RequestMapping(value="/students/{no}",method=RequestMethod.GET)
@ResponseBody
public Student students(@ApiParam(value = "student no" , required=true ) @PathVariable("no") String no) throws StudentNoFoundException {
return sf.find(no);
}
捕获异常通过页面分发到自定义的显示异常界面
package cn.edu.nchu.springmvc_mvn;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class StudentNoFoundExceptionHandler {
//这里为捕获异常的类型,这里捕获自定义的异常类
@ExceptionHandler(StudentNoFoundException.class)
// response by forward to controller with "forword:" in url
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleStudentNotFound3(StudentNoFoundException ex) {
System.out.println("stu no found exception");
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", ex.getCode());
map.put("message", ex.getMessage());
return "forward:/error";
}
}
定义异常类的Controller
package cn.edu.nchu.springmvc_mvn;
import javax.servlet.http.HttpServletResponse;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
class MainsiteErrorController implements ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletResponse res){
int statusCode = res.getStatus();
if(statusCode == 400){
System.out.println("error code: 400");
return "/error_show";
}else if(statusCode == 404){
System.out.println("error code: 404");
return "/error_show";
}else if(statusCode == 403){
System.out.println("error code: 403");
return "/403";
}else{
System.out.println("error code: 500");
return "/500";
}
}
@Override
public String getErrorPath() {
return "/error";
}
}
errow_show.html
<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2 th:text="${code}"></h2>
<h2 th:text="${message}"></h2>
</body>
</html>
Swagger文档的使用
配置pom.xml文件
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
创建SwaggerConfig类
package cn.edu.nchu.springmvc_mvn;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("标题")
.description("这是Swagger")
.version("1.0")
.build();
}
}
DemoRestController类中增加对应的注解
@RestController
@RequestMapping("/api/v1.0")
public class DemoRestController {
@Autowired
private StudentFactory sf;
@Deprecated
@ApiOperation(value="用于测试 ")
@RequestMapping(value="/test",method=RequestMethod.GET)
@ResponseBody
public String msg() {
return "测试";
}
// https://localhost:8080/api/v1.0/students/no1
@ApiOperation(value=" find one student 17203113")
@RequestMapping(value="/students/{no}",method=RequestMethod.GET)
@ResponseBody
public Student students(@ApiParam(value = "student no" , required=true ) @PathVariable("no") String no) throws StudentNoFoundException {
return sf.find(no);
}
// https://localhost:8080/api/v1.0/students/
@ApiOperation(value="find all student")
@RequestMapping(value="/students",method=RequestMethod.GET)
@ResponseBody
public List<Student> students() {
return sf.getStudents();
}
spring页面转发forward与重定向redirect
页面转发forward
方法一 以字符串的形式构建目标url, url 需要加上 forward: 前缀
@RequestMapping("/forwardTest1")
public String forwardTest1() {
System.out.println("DemoForwardRedirectController:forwardTest1()");
//return "forward:/forwardTarget";
return "forward:/forwardTarget?param1=v1¶m2=v2";
}
@RequestMapping("/forwardTarget")
public String forwardTargetView(Model model, @RequestParam("param1") String param1,
@RequestParam("param2") String param2) {
System.out.println("DemoForwardRedirectController:forwardTargetView()");
model.addAttribute("param1", param1);
model.addAttribute("param2", param2);
return "forward";
}
方法二 使用 ModelAndView() 设置转发的目标url
@RequestMapping("/forwardTest2")
public ModelAndView forwardTest2() {
System.out.println("DemoForwardRedirectController:forwardTest2()");
ModelAndView mav=new ModelAndView("forward:/forwardTarget2"); // 绝对路径OK
//ModelAndView mav=new ModelAndView("forwardTarget"); // 相对路径也OK
mav.addObject("param1", "value1");
mav.addObject("param2", "value2");
return mav ;
}
/*
* 通过ModelAndView Model @ModelAttribute @RequestParam("param1")
* 都无法获取forwardTest2中ModelAndView设置的param1和param2两个参数值
* @ModelAttribute会覆盖Model中的param1、2两个参数使之为“”
* @RequestParam获取还会发生注入错误,跳转到/error
* @RequestAttribute获取。
*/
@RequestMapping("/forwardTarget2")
public String forwardTargetView2(@RequestAttribute("param1") String param1) {
// 通过@RequestAttribute("param1") String param1来获取 ModelAndView中的值
System.out.println("forwardTarget2 Model attribute:"+param1);
System.out.println("DemoForwardRedirectController:forwardTargetView2()");
//model.addAttribute("param1", param1);
//model.addAttribute("param2", param2);
return "forward";
}
页面重定向 redirect
方法一 使用 redirect: 前缀url方式构建目标url
@RequestMapping("/redirectUrlTest")
public String redirectUrlTest(RedirectAttributes redirectAttributes) {
redirectAttributes.addAttribute("param1", "value1");
redirectAttributes.addAttribute("param2", "value2");
return "redirect:withParamTarget";
}
@RequestMapping("/withParamTarget")
public String withParamTarget(Model model, @RequestParam("param1") String param1,
@RequestParam("param2") String param2) {
model.addAttribute("param1", param1);
model.addAttribute("param2", param2);
return "redirect";
}
方法二(推荐使用): 使用 RedirectView 类型指定目标
@RequestMapping("/noParamRedirect")
public RedirectView noParamTest(RedirectAttributes redirectAttributes) {
RedirectView redirectTarget = new RedirectView();
redirectTarget.setContextRelative(true);
redirectTarget.setUrl("noParamTarget");
redirectAttributes.addAttribute("param1", "value1");
redirectAttributes.addAttribute("param2", "value2");
return redirectTarget;
}
@RequestMapping("/noParamTarget")
public String redirectTarget(HttpServletRequest r) {
//输出的结果为null
System.out.println(r.getParameter("param1"));
//输出的结果为:value1,
//通过getAttribute获取由页面重定向传递的参数,但是在下个页面参数param1丢失
System.out.println(r.getAttribute("param1"));
return "redirect";
}
方法三 使用 ModelAndView 类型指定目标, ModelAndView 视图名默认是forward, 所以对于redirect, 需要加上 redirect: 前缀
@RequestMapping("/withParamRedirect")
public RedirectView withParamRedirect(RedirectAttributes redirectAttributes) {
RedirectView redirectTarget = new RedirectView();
redirectTarget.setContextRelative(true);
redirectTarget.setUrl("withParamTarget");//noParamTarget");
redirectAttributes.addAttribute("param1", "value1");
redirectAttributes.addAttribute("param2", "value2");
return redirectTarget;
}
@RequestMapping("/withParamTarget")
public String withParamTarget(Model model, @RequestParam("param1") String param1,
@RequestParam("param2") String param2) {
model.addAttribute("param1", param1);
model.addAttribute("param2", param2);
return "redirect";
}
使用FlashRedirect 参数不在页面路径中显示
@RequestMapping("/withFlashRedirect")
public RedirectView withFlashTest(RedirectAttributes redirectAttributes) {
RedirectView redirectTarget = new RedirectView();
redirectTarget.setContextRelative(true);
redirectTarget.setUrl("withFlashTarget");
redirectAttributes.addAttribute("param", "value");//会在页面的url路径中显示
redirectAttributes.addFlashAttribute("flashParam", "flashValue");//不会在页面的url路径中显示
return redirectTarget;
}
/*
* redirectAttributes.addAttribute加的attr, 使用 @RequestParam()来fetch
* redirectAttributes.addFlashAttribute()加的attr, 使用 @ModelAttribute()来fetch
* */
@RequestMapping("/withFlashTarget")
public String withFlashTarget(Model model, @RequestParam("param") String param,
@ModelAttribute("flashParam") String flashParam) {
System.out.println("param:"+param+" flashParam:"+flashParam);
model.addAttribute("param", param);
model.addAttribute("flashParam", flashParam);
return "redirectFlash";
}
错误信息的转发,返回自定义的错误信息页面
studentFactory 如何修改,有问题
bootStrap
在vs code中使用bootStrap已经jquary
插件配置
示例代码
bootScrap-1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId"
aria-expanded="false" aria-label="Toggle navigation"></button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdownId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdownId">
<a class="dropdown-item" href="#">Action 1</a>
<a class="dropdown-item" href="#">Action 2</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<div class="container">
<h1>hello,bootstrap...</h1>
<hr>
<div class="alert alert-success" role="alert">
<strong>success</strong>
</div>
<table class="table table-hover table-inverse">
<thead class="thead-inverse">
<tr>
<th>No</th>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row"></td>
<td></td>
<td></td>
</tr>
<tr>
<td scope="row"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>
javaScript-1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId"
aria-expanded="false" aria-label="Toggle navigation"></button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdownId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdownId">
<a class="dropdown-item" href="#">Action 1</a>
<a class="dropdown-item" href="#">Action 2</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<div class="container">
<h1>hello,bootstrap...</h1>
<hr>
<div class="alert alert-success" role="alert">
<strong>success</strong>
</div>
<table class="table table-hover table-inverse">
<thead class="thead-inverse">
<tr>
<th>No</th>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row"></td>
<td></td>
<td></td>
</tr>
<tr>
<td scope="row"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>
jquery-1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" name="name" id="">
<input type="button" value="copy">
<h1></h1>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("input:button").click(function (e) {
//$("h1").text($("input:text").val());
$.ajax({
type: "get",
url: "https://localhost:8080/api/v1.0/msg",
//data: "data",
//dataType: "dataType",
success: function (response) {
console.log(response);
$("h1").text(response);
}
});
});
});
</script>
</body>
</html>
jquery
vue.js
同步刷新示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="msg">
<p>{{msg}}</p>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script>
var vue=new Vue({
el:"#app",
data:{
msg:"test message..."
}
});
</script>
</body>
</html>
使用axios发送get请求 示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="button" v-on:click="getMessage()" value="click">
<p>{{msg}}</p>
<ol>
<li v-for="student in students" v-text="student.name"></li>
</ol>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
<script>
var vue=new Vue({
el:"#app",
data:{
msg:"test message......",
students:[]
},
methods:{
getMessage:function(){
axios.get("https://localhost:8080/api/v1/students")
.then(response=>{
console.log(response.data);
//this.msg=response.data;
this.students=response.data;
})
.catch(function(error){
console.log(error);
});
}
},
});
</script>
</body>
</html>
AOP 拦截器
概述
拦截器使用
切入点
新建MoniterAspect.class
作用,拦截cn.edu.nchu.springmvc_mvn.StudentFactory.*(…))中的所有方法,选择不同的切入点
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
@Component
@Aspect
public class MoniterAspect {
public static int total = 0;
@Around("execution (* cn.edu.nchu.springmvc_mvn.StudentFactory.*(..))")
public Object count(ProceedingJoinPoint pjp) throws Throwable {
total++;
System.out.printf("aop ----around : total: %d ...\n", total);
return pjp.proceed();
}
@Before("execution (* cn.edu.nchu.springmvc_mvn.StudentFactory.*(..))")
public void doBeforeAdvice(JoinPoint joinPoint) {
System.out.println("aop ----before"); // 获取目标方法的参数信息 Object[] obj =
joinPoint.getArgs(); // AOP代理类的信息 joinPoint.getThis();
System.out.println("aop ----before joinPoint.getThis():" + joinPoint.getThis()); // 代理的目标对象
// joinPoint.getTarget();
System.out.println("aop ----before joinPoint.getTarget():" + joinPoint.getTarget()); // 用的最多 通知的签名
Signature signature = joinPoint.getSignature();
System.out.println("aop ----before joinPoint.getSignature():" + joinPoint.getSignature()); // 代理的是哪一个方法
System.out.println("aop ----before signature.getName():" + signature.getName());
// AOP代理类的名字
System.out.println("aop ----before signature.getDeclaringTypeName():" + signature.getDeclaringTypeName());
// AOP代理类的类(class)信息
signature.getDeclaringType();
System.out.println("aop ----before signature.getDeclaringType():" + signature.getDeclaringType());
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
// 如果要获取Session信息的话,可以这样写: //HttpSession session = (HttpSession)
requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
Enumeration<String> enumeration = request.getParameterNames();
Map<String, String> parameterMap = Maps.newHashMap();
while (enumeration.hasMoreElements()) {
String parameter = enumeration.nextElement();
parameterMap.put(parameter, request.getParameter(parameter));
}
String str = JSON.toJSONString(parameterMap);
System.out.println("aop ----before 请求的参数信息为:" + str);
}
}
springboot持久化设计
在pom.xml中引入mysql包
<!-- 数据库有关包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql5.1.40的包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
创建CompanyRepository类用来访问数据库
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
public class CompanyRepository {
@Autowired
private JdbcTemplate jt;
// 查询所有的公司的信息,返回公司列表
public List<Company> getCompanys(){
List<Company> list = new ArrayList<>();
list = jt.query("select * from company", new BeanPropertyRowMapper<Company>(Company.class));
return list;
}
// 根据id和password查询公司信息,返回公司对象
public Company getCompanyByLogin(String company_id,String company_password){
System.out.println("id:"+company_id+" password"+company_password);
Company com ;
com = jt.queryForObject("select * from company where com_id=? and com_password=?",new BeanPropertyRowMapper<Company>(Company.class),company_id,company_password);
return com;
}
}
使用CompanyRepository类
@Autowired
CompanyRepository cr;
@ApiOperation(value="公司登录")
@RequestMapping(value="/comLogin",method= RequestMethod.GET)
public Company comLogin(@RequestAttribute("id") String id,@RequestAttribute("password") String password){
Company com = cr.getCompanyByLogin(id,password);
return com;
}