文章目录
1 Spring MVC介绍
对于服务端的程序来说,我们首要解决的是如何处理浏览器端的请求,在这方面,Spring MVC是最流行的技术。
1.1 服务端代码分为三层
服务端开发的代码是有层次的,分层的目的是解耦、易于维护。
服务端的代码分为三层,分别是:表现层/业务层/数据层。
浏览器访问服务器,首先访问表现层,期待表现层给它一些数据,表现层会调用业务层处理业务,业务层在处理业务过程中会调用数据访问层来访问数据库。表现层(Controller)得到业务层返回的数据封装在Model里传给视图层View,View利用数据生成html返回给浏览器
1.2 表现层的代码分为三层
Spring MVC是一种设计模式,理念是将复杂的代码分为三个层次
C - Controller:控制器。接受用户请求,调用 Model 处理,然后选择合适的View给客户。
M - Model:模型。业务处理模型,接受Controller的调遣,处理业务,处理数据。
V - View:视图。渲染
Spring官方手册:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet
HandlerMapping:敲一个路径,利用HandlerMapping来匹配到对应的Controller,我们所写的RequestMapping注解就是由HandlerMapping来管理的
1.3 处理请求的过程
浏览器传入的请求由前端控制器处理(就是DispatcherServlet)
DispatcherServlet根据注解RequestMapping找到对应的Controller
Controller把处理后得到的数据封装在Model里返回给DispatcherServlet
DispatcherServlet把Model传给View
View渲染之后返回DispatcherServlet
DispatcherServlet返回给浏览器
2 示例
是个小示例就不写数据访问层和业务层了
(其中数据访问层已在MyBatis入门里演示过)
视图层包含在controller文件夹里的Controller和resource文件下的templates文件夹下的动态模板
Controller:
1.写注释@Controller
2.(这步可省略)写映射地址
3.里面写方法,方法前面写映射地址
2.1 测试接收请求数据
@RequestMapping("/request")
public void testRequest(HttpServletRequest request,HttpServletResponse response){
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);
}
response.setContentType("text/html;charset=utf-8");
try(
PrintWriter writer = response.getWriter();
){
writer.write("<h1>i get your request</h1>");
}catch (IOException e){
e.printStackTrace();
}
}
2.1.1 接收从URL传进来的参数
1.用@RequestParam
// /students?current=1&limit=20
@RequestMapping(path = "/students" , method = RequestMethod.GET)
@ResponseBody//返回一个简单的字符串
//1.要怎么获取请求的参数呢?方法的参数名称与请求的参数名称一致就行了
//DispatcherServlet检测到方法有参数之后,就会把请求中与之匹配的参数传进来
//如果请求没有传来参数怎么办呢?需要在方法参数前面加上注解。注解中第二个参数:可以不传;第三个参数:不传的话默认值
public 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";
}
2.用@PathVariable
//2 根据学生id查询一个学生的信息:/student/123 直接把参数编排到路径中
@RequestMapping(path = "/student/{id}",method = RequestMethod.GET)
@ResponseBody
public String getStudent(@PathVariable("id") int id){
System.out.println(id);
return "a student";
}
2.1.2 接收从POST请求传入的数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>增加学生</title>
</head>
<body>
<form method="post" action="/community/demo/student">
<p>
姓名: <input type="text" name="name">
</p>
<p>
年龄: <input type="text" name="age">
</p>
<p>
<input type="submit" value="保存">
</p>
</form>
</body>
</html>
访问一下试试,重新编译,访问static里的静态页面,路径里static不用打
属性名写得和网页一致就行了,DispatcherServlet匹配到该方法之后会自动将传入数据与方法参数做匹配
@RequestMapping(path = "/student",method = RequestMethod.POST)
@ResponseBody
public String saveStudent(String name,int age){
System.out.println("姓名:"+name+",年龄:"+age);
return "success!";
}
2.2 测试返回响应数据
@Controller
@RequestMapping("/demo")
public class DemoController {
@RequestMapping("/response")
//测试一下返回响应数据
public void testResponse(HttpServletResponse response) {
//浏览器返回的类型是HTML
response.setContentType("text/html;charset=utf-8");
try(
PrintWriter writer = response.getWriter();
){
writer.write("<h1>hello,this is a response demo!</h1>");
}catch (IOException e){
e.printStackTrace();
}
}
}
调试一下,writer里的数据在response里的hb里存着的
这应该算是计网里的内容
Connection不了解
Content-Length: 我的响应一共39个字符
Content-Type:响应类型,我在程序里设置过(不设置的话,响应头里没这句,但是页面还是可以解析成HTML语句)
Data:时间
Keep-Alive:不了解
HttpServletResponse是谁创建的?老师说的是把HttpServletResponse写在方法参数里,SpringMVC里的DispatcherServlet在调用该方法时会自动把HttpServletResponse对象传给方法
2.2.1 响应HTML
在templates目录下新建一个test文件夹,里面新建view2.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>
//返回html文件
@RequestMapping(path = "/teacher" ,method = RequestMethod.GET)
public ModelAndView getTeacher(){
ModelAndView mav = new ModelAndView();
mav.addObject("name", "李老师");
mav.addObject("age", 30);
mav.setViewName("/test/view2");//返回templates目录下html的文件路径
return mav;
}
现在显示的这个页面就是view2.html被模板引擎动态渲染之后的页面
还有一种更简单一点的调用方式
返回的类型是String,就是返回的动态模板的路径
@RequestMapping(path = "/school",method = RequestMethod.GET)
public String getSchool(Model model){
model.addAttribute("name","电子科技大学");
model.addAttribute("age",65);
return "/test/view2";
}
2.2.2 响应JSON数据
在异步请求中要响应JSON数据
举例:在某网站注册时,输入昵称,网站会查询服务器该昵称是否被占用,然后以异步请求的方式返回到网页
@ResponseBody
不加该注解默认返回html
@RequestMapping(path = "/emp",method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> getEmp(){
Map<String, Object> emp = new HashMap<>();
emp.put("name", "张三");
emp.put("age", 23);
emp.put("salary", 8000);
return emp;
}
DispatcherServlet看到该方法加了@ResponseBody
,并且返回类型为Map,就会自动把Map转成JSON字符串
还可以往外面再包一层:多组相似数据
基本上所有数据都可以通过这种方式转成JSON返回网页
@RequestMapping(path = "/emps",method = RequestMethod.GET)
@ResponseBody
public 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);
list.add(emp);
emp = new HashMap<>();
emp.put("name", "李四");
emp.put("age", 24);
emp.put("salary", 9000);
list.add(emp);
emp = new HashMap<>();
emp.put("name", "王五");
emp.put("age", 22);
emp.put("salary", 8000);
list.add(emp);
return list;
}