做网站凡科如何/百度搜索引擎的网址
目录
- mvc模式
- springmvc概述
- springmvc的主要组件 | 核心组件
- springmvc的工作流程
- 后端接收前端传递的参数(数据绑定)
- 1、使用普通类型接收
- 2、使用实体类接收
- 3、使用Map接收
- 4、使用扩展类接收
- 表单常见控件的参数接收
- restful
- url映射
- controller返回数据
- 转发、重定向
- springmvc常用的注解
- 标注controller的注解
- 用于指定url映射的注解
- 获取请求参数(request对象)的注解
- 处理响应(response对象)的注解
- cookie的使用
mvc模式
常见问题
- mvc是什么?
- mvc模式有什么好处?
mvc是 java web 中最常用的架构模式,常见的 mvc 框架有 springmvc、struts2
- M是model 模型(model),model是一个泛化的概念,不单单是指用于封装数据、在层间传递数据的实体类,往往是指对业务的整个处理流程。
- V是view 视图,用于显式内容、展示数据
- C是controller 控制器,用于接收、分发请求,返回响应。
在springmvc中
- C可以理解为 DispatcherServlet、controller层,controller可以将请求分发给某个方法进行处理,可以看做是C的一部分;
- M可以理解为 service -> dao 整个流程,以及层间传递数据的实体。
使用springmvc是,尽量遵循单一职责的设计原则,controller用于接口级别的处理,比如参数校验、返回值设置,把业务逻辑下沉到 service 层来处理。
mvc模式的优点
mvc的核心思想是分层设计,这有2个好处
- 控制层、数据层、视图层分离,有利于组件间的解耦,提高了扩展性,易于维护
- 三层可以同时进行开发,可以加快开发进度
springmvc概述
常见问题
- 什么是Spring MVC?谈谈你对Spring MVC的理解
- springmvc有什么优点?你们项目为什么选择用springmvc?
- struts2、springmvc有什么区别?
springmvc 是 java web 中的一个轻量级mvc框架,基于spring,支持restful编程风格,是目前最受欢迎的mvc框架之一。
springmvc的优点
- 与spring集成方便
- 支持多种视图技术
- 支持各种请求映射策略
springmvc、struts2的区别
- springmvc基于servlet,前端控制器是 DispatcherServlet ,struts2基于filter,前端控制器是 StrutsPreparedAndExcutorFilter。
- 接收请求参数的方式不一样:springmvc基于方法接收请求参数,用controller中方法的参数来接收请求参数;struts2基于类接收请求参数,用action的属性来接收请求参数。也正是由于此,controller可以是单例的,action只能为多例的。
- springmvc的controller是默认是单例的,节约资源,不是线程安全的;struts2的action是多例的,资源消耗多,线程安全。
springmvc的主要组件 | 核心组件
- DispatcherServlet:前端控制器,用于接收、转发请求,响应结果。Spring的MVC框架是围绕DispatcherServlet来设计的,用来处理所有的HTTP请求和响应。DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。
- HandlerMapping:处理器映射器,内部维护Handler、url的映射关系,根据请求的URL确定要使用的Handler
- HandlerAdapter:处理器适配器,用于按照特定规则执行Handler
- Handler:处理器,用于处理业务,返回ModelAndView,需要开发进行编写,即Controller
- ViewResolver:视图解析器,用于解析视图,根据model中的数据填充视图。先根据逻辑视图名找到对应的物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 sprnigmvc支持多种视图解析器。
- View:视图,作为载体,用于显示页面。springmvc支持html、thymeleaf、freemarker、velocity、jsp等多种格式的视图
springmvc的工作流程
常见问题
- springmvc的工作流程
- springmvc的执行原理
- springmvc处理请求的流程
- 浏览器向服务器发送请求
- DispatcherServlet 统一拦截所有请求,将请求地址(url)传给HandlerMapping
- HandlerMapping 根据 url、controller 之间的映射关系,查找该 url 对应的 controller 并返回给 DispatcherServlet
- DispatcherServlet 使用合适的处理器适配器 HandlerAdapter ,调用指定的controller
- controller处理请求,将处理结果封装住在ModelAndView中,返回给 HandlerAdapter,HandlerAdapter 返回给 DispatcherServlet
- DispatcherServlet 调用 ViewResolver 来解析ModelAdnView ,得到的Model、View
- DispatcherServlet 将Model中的数据填充到View中
- DispatcherServlet 将填充好数据的View封装为响应返回给浏览器
后端接收前端传递的参数(数据绑定)
有三种方式
- 使用普通类型接口
- 使用Map接收
- 使用实体类接收:扩展类也算实体类
1、使用普通类型接收
<!-- 表单 -->
用户名:<input name="username" type="text" /><br />
密码:<input name="password" type="password" /><br />
年龄:<input name="age" type="number" /><br />
// 默认同名赋值
public String xxx(String username, String password){}// @RequestHeader用于请求头,@RequestBody用于请求体,@RequestParam是通用的(请求头+请求体)
// @CookieValue用于获取请求头携带的cookie字段,使用方式和以上3个注解相同// 如果形参、请求参数名不一致,可绑定请求参数名
public String xxx(String username, @RequestParam("password") String pwd){}// 默认为true 该参数必需,可以指定为false,为false时自动取defaultValue设置的默认值,如果没有设置defaultValue则为该类型的默认值
//username相当于加了@RequestParam(name="username"),默认同名,也可以使用name的别名value
public String xxx(String username, @RequestParam(required = false, defaultValue = "") String pwd){}
require的必需和前端表单的必填不是一个概念,必需是请求参数中一定要有该字段、但值可以是空(没有值),必填是请求参数中该字段一定要有值(不为空)。
2、使用实体类接收
// pojo类
@Setter
@Getter
public class User {private String username;private String password;private int age;
}
//controller使用pojo类接收。如果没有传递某些成员变量,为该类型的默认值
public String xxx(User user){}
<!-- 表单字段的name使用pojo的成员变量 -->
用户名:<input name="username" type="text" /><br />
密码:<input name="password" type="password" /><br />
年龄:<input name="age" type="number" /><br />
3、使用Map接收
和实体类的接收方式差不多,字段名作为map的key,字段值作为键值对的value。
缺点:往往需要自己转换数据类型,很麻烦;map.get(“xxx”)获取字段值时,字段名是字符串形式,可能写错。
一般不用这种方式。
4、使用扩展类接收
// 扩展类
@Setter
@Getter
public class UserExt {private User user;//... //其它成员
}
// controller使用扩展类接收
public String xxx(UserExt userExt){}
<!-- 表单字段的name使用扩展类的成员变量。注意:是扩展类的成员变量,不是controller中的扩展类形参 -->
用户名:<input name="user.username" type="text" /><br />
密码:<input name="user.password" type="password" /><br />
年龄:<input name="user.age" type="number" /><br />
扩展类也可以继承原来的类,写成第二种的方式
表单常见控件的参数接收
-
单选框用String接收,复选框用String[ ]接收,复选框的name使用数组名
-
日期使用Date接收,表单使用type=“date”
如果不进行相关计算,后台也可使用String接收。
表单可使用type=“text”,但使用text日期格式只能是 年/月/日 ,需严格校验格式。 -
批量操作,用数组或List接收
比如视图以表格形式列出了多个商品的信息,管理员在页面上修改了多个商品的信息,提交修改时可以使用Goods[ ]或List来传递数据。注意:如果数组、List的元素是自定义的类,比如Goods、User,后台不能直接使用数组、List接收,需要包装一下数组、List
// 使用包装类包装数组|List
@Setter
@Getter
public class GoodsArrayVO {private Goods[] goodsArray;// private List<Goods> goodsList;
}
// controller使用数组|List的包装类来接收
public String xxx(GoodsArrayVO goodsArrayVO){Goods[] goodsArray = goodsArrayVO.getGoodsArray();//.....}
<!-- 和普通扩展类一样,表单字段使用扩展类的成员变量 -->
Goods1:<br />
<input type="hidden" name="id" value="001" />
商品名称:<input name="goodsArray[0].name" type="text"><br />
商品价格:<input name="goodsArray[0].price" type="number"><br /><br />Goods2:<br />
<input type="hidden" name="id" value="002" />
商品名称:<input name="GoodsArray[1].name" type="text"><br />
商品价格:<input name="goodsArray[1].price" type="number"><br /><br />
如果需要操作request、session、response对象,直接在形参中声明即可,springmvc会自动传入对应的对象。
restful
restful风格的url也能传递参数
@GetMapping("/user/{id}")
public String findUser(@PathVariable int id){ //@PathVariable修饰变量
}@GetMapping("/user/{user_id}")
public String findUser(@PathVariable("user_id") int userId){ //名称不一致时,要指定绑定哪个{}
}@GetMapping("/product/{type}/{id}")
public String findProduct(@PathVariable String type, @PathVariable int id) { //有多个时,1个@PathVariable修饰1个变量}
养成规范,@PathVariable都指定变量名。
url映射
//只处理get方式的请求
@GetMapping("/api/v1/xxx")
//只处理post方式的请求
@PostMappping("/api/v1/xxx")
//可处理所有请求方式
@RequestMapping("/api/v1/xxx")// 可指定要处理的请求方式、映射路径,都是数组{ }
@RequestMapping(value = {"/api/v1/xxx1", "/api/v1/xxx2"}, method = {RequestMethod.GET, RequestMethod.POST})
// value、path互为别名,都可以用于指定映射路径
@RequestMapping(value = "/api/v1/xxx1", method = RequestMethod.GET)// 可缺省开头的/
@RequestMapping("api/v1/xxx1")
常用的请求方式
请求方式 | 应用 | 说明 | 对应CRUD |
---|---|---|---|
GET | 获取资源 | 安全、幂等 | R(Retrieve 读取) |
POST | 创建资源 | 非安全、非幂等 | C |
PUT | 更新资源 | 非安全、幂等 | U |
DELETE | 删除资源 | 非安全、幂等 | D |
其实post、put都可以创建、更新资源
- post主要用于创建资源,如果资源已存在会覆盖,即更新;
- put主要用于更新资源,如果资源不存在会先创建,比如根据id更新用户信息,如过指定id的用户不存在,会先创建该id的记录(其它字段使用默认值),再更新
controller返回数据
- @Controller:可以返回String形式的视图名,也可以返回包含数据、视图名的ModelAndView
- @RestController:等于 @Controller + @ResponseBody,@ResponseBody可以将返回值转换为指定格式放在响应体(body)中返回,格式常用 json、xml 。
@Controller 向视图传递数据
//方式一:Model作为方法参数,返回String类型的视图名,会自动传递Model
public String xxx(Model model){model.addAttribute("username", "chy");return "index";
}//方式二:使用ModelAndView封装要传递的数据,返回ModelAndView
public ModelAndView xxx(){ModelAndView mav = new ModelAndView("index"); //指定视图名mav.addObject("username", "chy1"); //携带数据return mav;
}
转发、重定向
@org.springframework.stereotype.Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/register")public String login() {//forward是转发,redirect是重定向return "forward:/user/login";}}
springmvc常用的注解
常见问题:springmvc中有哪些注解,作用分别是什么?
说明:可标注在类上、方法上 => 标注在类上时对应用到类中的所有方法上
标注controller的注解
- @Controller:标注在类上,用于把一个类标记为控制器类
- @RestController:等于 @Controller + @ResponseBody
用于指定url映射的注解
- @RequestMapping:可使用method属性指定支持的请求方式,默认支持所有请求方式
- @GetMapping:只支持get请求方式
- @PostMapping:只支持post请求方式
- @PutMapping:只支持put请求方式
- @DeleteMapping:只支持delete请求方式
均可标注在类上、方法上,其它几个都是在 @RequestMapping 的基础上实现的,只是缺少了method属性。
可以在@RequestMapping 的源码中看各个属性的使用说明
@RequestMapping(value = "xxx", method = {RequestMethod.GET, RequestMethod.POST}, params = {"type=1", "userId"},consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
- value、path:互为别名,用于指定映射的路径
- method:指定支持的请求方式,String[ ] 可以同时指定多种请求方式
- params:指定需要的参数。可以用 =、!= 进行筛选,示例:"type=1"表示必须传递type这个参数,且值必须为1;"userId"表示必须要传递userId这个参数
- consumes:指定支持的ContentType,即请求参数的提交类型。值可以用MediaType 类中定义的常量,也可以直接写 “application/json” 之类的字符串。
- produces:指定支持的Accept,即客户端期待返回的数据类型
这些属性都是用于限制请求的,只有请求满足这些条件,才会被这个方法处理。
获取请求参数(request对象)的注解
- @CookieValue:用于获取cookie中携带的参数
- @PathVariable:获取 restful 风格的 url 中传递的参数
- @RequestHeader:用于获取请求头中携带的参数
- @RequestBody:用于获取请求体中携带的参数
- @RequestParam:用于获取请求中携带的参数
注意点:后端使用实体类接收参数时
- springmvc转换参数时是把传递的键值对转换为实体类中的字段,前端不能 {userQo : this.UserQo} 这样来传递整个对象,实体类中没有 userQo 这个字段,接收不到对应的参数。可以 {username : ‘xxx’, tel : ‘xxx’} 传递字段,如果前端想直接传递整个对象,需要用qs之类的方式做额外处理
this.$qs.stringify(this.params))
。 - 后端 get、post 方式的参数都不用加 @RequestXxx 系列注解。
处理响应(response对象)的注解
- @ResponseBody:可标注在类上、方法上,用于将方法返回值转换为客户端Accept指定的数据类型(通常是json),并写入到Response对象的body区域。
- @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
cookie的使用
设置cookie
@PostMapping("login")
public UserVO login(UserVO userVO, HttpServletRequest req, HttpServletResponse resp) {//...Cookie userIdCookie = new Cookie("userId", String.valueOf(userVO.getUserId()));userIdCookie.setMaxAge(7 * 24 * 60 * 60);//当前项目|应用的根路径,eg. /malluserIdCookie.setPath(req.getContextPath());resp.addCookie(userIdCookie);return userVO;
}
cookie 常见属性
- maxAge:指定有效期,单位 s,0表示立刻删除此cookie,负数表示只在本次http交互中有效、不用存储这个cookie,默认值 -1。
- domain:指定cookie作用的域名,默认为当前url所在域名。
- path:指定cookie作用的资源路径,默认为当前url路径,eg. /mall/user/login,常见的值比如 req.getContextPath() 当前应用全部资源。
- secure:设置为 true 时只在 https 请求中携带此cookie,在 http 请求中不会携带此cookie。
- httpOnly:设置为 true 时浏览器端不能通过 js 的 Document.cookie api访问此cookie,可防止跨站点脚本(xss)攻击。
- version:指定使用的cookie协议版本,可选的值 0、1,默认0。类似于 http 的1.0、2.0,是协议版本,不是value数据的版本。
只有请求 url 的 domain、path 对应时,请求中才会携带此cookie。
删除cookie
Cookie userIdCookie = new Cookie("userId", null);
userIdCookie.setMaxAge(0);
userIdCookie.setPath(req.getContextPath());
resp.addCookie(userIdCookie);
有效期设置为0,cookie的其它属性与之前保持一致,依然需要添加到 resp 中。
value置为null不是必须的。
获取cookie指定字段的值
@GetMapping("findUserById")
public UserVO findUserById(@CookieValue(value = "userId", defaultValue = "") Long userId) {//...return null;
}
@CookieValue 会根据 name 解析注入指定 cookie 的 value,此注解需要设置 defaultValue 属性,不然http请求未携带对应的cookie时,会抛出 MissingRequestCookieException ,defaultValue 的值只能是 String 形式。
获取全部cookie
@GetMapping("xxx")
public void xxx(HttpServletRequest req) {//如果未携带任何cookie,则数组为 nullCookie[] cookies = req.getCookies();if (cookies != null) {}
}