- cookie处理
- 设置cookie
- 获取cookie
- 删除cookie
- 小结
- Session处理
- 作用域
- Request参数设置
- 页面跳转
- 通过Response
- 通过Request
- 内容协商
- Json返回
- XML 返回
- 基本原理说明
- 自定义类型转换器
- 通过特定参数获取返回类型
- 参数解析
- 原理解析
- 示例
- 自定义解析器
- 视图处理
- 使用thymeleaf
- 基本语法
- 1、表达式
- 2、字面量
- 3、文本操作
- 4、数学运算
- 5、布尔运算
- 6、比较运算
- 7、条件运算
- 设置属性值-th:attr
- 迭代
- 条件运算
- 进入页面使用
- 初步使用
- 获取示图参数
到这一步假设我要处理一些请求过来的特殊参数,或者像Django那样后面的操作,那么我就需要用到这个比较高级的用法,用到servlet提供的一些API接口,例如前面的HttpServletRequest等等。 cookie处理 设置cookie
这个玩意的话还是很简单的而且昨天的博客也说了怎么玩。
@GetMapping("/change-username")
public String setcookie(HttpServletResponse response) {
// 创建一个 cookie对象
cookie cookie = new cookie("username", "Jovan");
cookie.setMaxAge(7 * 24 * 60 * 60); // 7天过期
cookie.setSecure(true); //Https 安全cookie 只通过https传输
//将cookie对象加入response响应
response.addcookie(cookie);
return "Username is changed!";
}
获取cookie
@GetMapping("/all-cookies")
public String readAllcookies(HttpServletRequest request) {
cookie[] cookies = request.getcookies();
if (cookies != null) {
return Arrays.stream(cookies)
.map(c -> c.getName() + "=" + c.getValue())
.collect(Collectors.joining(", "));
}
return "No cookies";
}
删除cookie
若要删除cookie,请将Max-Age指令设置为0并取消其值的设置。您还必须传递用于设置它的相同的其他cookie属性。不要将Max-Age指令值设置为-1。否则,浏览器将把它视为会话cookie。
换句话来说
你的一个cookie是这样的
cookie cookie = new cookie("username", "Jovan");
cookie.setMaxAge(7 * 24 * 60 * 60); // 7天过期
cookie.setSecure(true); //Https 安全cookie 只通过https传输
现在删除,你要这样做
cookie cookie = new cookie("username",null);
cookie.setMaxAge(0);
cookie.setSecure(true); //Https 安全cookie 只通过https传输
response.addcookie(cookie);
小结
这里的话主要就是用了servlet里面的一些原生的API去做,一个是HttpServletRequest还有就是Response。
Session处理这个Session是啥我想都不用多说了,这个也是需要利用到cookie的玩意。那么在SpringBoot里面设置也非常简单。
首先HttpSession是我们的Session对象。
这么用呢也相当简单
@Controller
public class IndexController {
@GetMapping("/index1")
public String index1(HttpSession session){
session.setAttribute("name","Huterox");
return "redirect:/index2";
}
@GetMapping("/index2")
@ResponseBody
public String index2(HttpSession session){
String name = (String) session.getAttribute("name");
return name;
}
}
这样一来就是先了session处理。
作用域而且这里都记住这个Session和request里面的参数都是由作用域的,request的作用域:是从当前请求到服务器处理请求结束,包括服务器转发到内部的资源路径,也同样可以访问到request中的内容;
所以如果要从当前资源转发到其他资源中,还需要共享数组,就可以使用request.setAttribute(“名称”,Object obj)共享数据;
另外Session的作用域是一次会话,从打开浏览器到关闭浏览器之前,都可以访问到Session中的数据;作用域更大;
如果是重定向,就不能访问到Request域中的共享数据;可以使用session作用域;
Request参数设置@Controller
public class IndexController {
@GetMapping("/index1")
public String index1(HttpSession session, HttpServletRequest request){
session.setAttribute("name","Huterox");
request.setAttribute("world","Hello world");
return "redirect:/index2";
}
@GetMapping("/index2")
@ResponseBody
public String index2(HttpSession session,HttpServletRequest request){
String name = (String) session.getAttribute("name");
String world = (String) request.getAttribute("world");
return name+world;
}
}
这里大概率你得到的值一定是
Huteroxnull
原因很简单我这里用到是跳转,前面说了它们之间是由作用域的!redirect是跳转,意味着当前的请求处理完了那么进入了下一个请求处理,那么这个时候自然作用不了了。
那么在这里的话我们
return “forward:/index2”;
向前就好了。
这个也是servlet里面进行跳转的方式。
页面跳转首先这个方式有很多最简单的方式就是
return "forward:/xxx";
或者
return "redirect:/xxx";
但是二者是有区别。
forward的意思是向前的、(按新地址)转寄、促进、前锋的意思,而redirect的意思是改变方向、重新寄送。
这个英文意思基本上就是在Spring当作的意思。
通过Response我们也可以通过这个来搞定
@GetMapping("/index1")
public void index1(HttpSession session, HttpServletResponse response) throws IOException {
session.setAttribute("name","Huterox");
response.sendRedirect("/index2");
// return "redirect:/index2";
}
但是这样方式有作用域的问题,要么你用session搞定,或者放行,这边可以使用request放行可以保证作用域参数丢失的问题。
通过Requestrequest.getRequestDispatcher("/index2").forward(request,response);
不过这里也是只用
内容协商首先:
内容协商的核心之一就是,(Converter)类型转换器!这玩应通过反射等手段实现自动类型的加载转换,同时结合不同的依赖实现不同的类型转换。这一点在实际的操作过程当中相当重要这就意味着可以实现一S端(server)对应不同的客户端
这是很不错的点感觉除了数据库操作麻烦一点其他的要完爆Django
Json返回首先SpringBoot由于自己在搭建start-web场景的时候自己自带了一个Json的数据转换,所以的话默认在Spring Boot里面就是返回一个Json对象的。
@GetMapping("/jsonget")
@ResponseBody
public String index2(){
User user = new User();
return user;
}
}
XML 返回
这边我们需要先导入依赖
com.fasterxml.jackson.dataformat jackson-dataformat-xml
之后我们的服务器后根据客户端请求头
Accept: text/css,* public class HMessageConverter implements HttpMessageConverter{ @Override public boolean canRead(Class> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class> clazz, MediaType mediaType) { return clazz.isAssignableFrom(Person.class); } @Override public List getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-Huterox"); //类型,自定义的类型名称 } @Override public Person read(Class extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null; } @Override public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { //自定义协议数据的写出 String data = person.getUserName() + ";" + person.getAge() + ";" + person.getBirth(); //写出去 OutputStream body = outputMessage.getBody(); body.write(data.getBytes()); } }
重写方法
@Configuration(proxyBeanMethods = false)
public class WebConfig {
//WebMvcConfigurer定制化SpringMVC的功能
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List> converters) {
converters.add(new HMessageConverter());
}
}
}
通过特定参数获取返回类型
在这里面除了浏览器自带的参数接受形式外,SpringBoot还支持带参数返回,例如
127.0.0.1:8000/index?format=xml
不过在这里需要先开启这个功能
spring:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
现在我们想让我们自己定义的类型也能够通过参数获取,那么同样的我们现在也需要重写。
@Configuration(proxyBeanMethods = false)
public class WebConfig {
//WebMvcConfigurer定制化SpringMVC的功能
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List> converters) {
converters.add(new HMessageConverter());
}
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//Map mediaTypes
Map mediaTypes = new HashMap<>();
mediaTypes.put("json", MediaType.APPLICATION_JSON);
mediaTypes.put("xml", MediaType.APPLICATION_XML);
mediaTypes.put("H", MediaType.parseMediaType("application/x-Huterox"));
//指定支持解析哪些参数对应的哪些媒体类型
ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
// parameterStrategy.setParameterName("ff");改变参数名字 ?ff=xml
HeaderContentNegotiationStrategy headeStrategy = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(parameterStrategy, headeStrategy));
}
}
这样一来就完成了完整的功能。
参数解析这个也是很好玩很厉害的东西。
举个例子就是昨天的。
@RestController
public class HelloController {
@PostMapping("/hello")
public String hello(User user) {
return user.toString();
}
}
根据获取的参数SpringBoot会自动封装一个指定的对象。
原理解析一说到这个又是涉及到自定义的问题了。
首先参数返回到springboot后,准确的来说是springMVC 先进入它的参数解析器-HandlerMethodArgumentResolver
-
HandlerMapping中找到能处理请求的Handler(Controller.method())
-
为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
-
适配器执行目标方法并确定方法参数的每一个值
之后参数解析器-HandlerMethodArgumentResolver
确定将要执行的目标方法的每一个参数的值是什么;
SpringMVC目标方法能写多少种参数类型。取决于参数解析器。
- 当前解析器是否支持解析这种参数
- 支持就调用 resolveArgument
这样一来就完成了对对象的封装。
所以这里面的核心还是说,返回的参数格式里面和我们定义的Bean里面 的属性是否对得到,OK才能进行一系列的操作。
示例例如我这里有两个Bean
@Data
public class Person {
private String userName;
private Integer age;
private Date birth;
private Pet pet;
}
@Data
public class Pet {
private String name;
private Integer age;
}
现在有这样的表单
@PostMapping("/GetPerson")
public Person saveuser(Person person) {
return person;
}
现在ok
自定义解析器现在我把表单这样改一下
显然虽然有pet但是没有具体的映射关系,解析器解析不了。
那么在这里也是我们是定制MVC里面的东西我们需要进入到前面的webconfigurer里面去
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter() {
@Override
public Pet convert(String source) {
// 啊猫,3
if (!StringUtils.isEmpty(source)) {
Pet pet = new Pet();
String[] split = source.split(",");
pet.setName(split[0]);
pet.setAge(Integer.parseInt(split[1]));
return pet;
}
return null;
}
});
}
};
}
}
这样一来就可以解析pet了,因为pet这玩意他是找得到的,只是没法解析。
视图处理现在终于到了万众瞩目的示图了,看到了熟悉的template这个文件夹
那么同样在这边处理视图的话需要用到对应的引擎,进行解析。这个我们这边先使用的还是
thymeleaf
那么对于视图的处理分一下流程。
1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址
2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer
**3、任何目标方法执行完成以后都会返回 ModelAndView(**数据和视图地址)。
4.processDispatchResult 处理派发结果(页面改如何响应)
使用thymeleaf加入依赖(如果你IDEA选了就不用了)
基本语法org.springframework.boot spring-boot-starter-thymeleaf
(此部分内容参照尚硅谷提供的笔记,对部分内容进行筛选)
1、表达式| 表达式名字 | 语法 | 用途 |
|---|---|---|
| 变量取值 | ${…} | 获取请求域、session域、对象等值 |
| 选择变量 | *{…} | 获取上下文对象值 |
| 消息 | #{…} | 获取国际化等值 |
| 链接 | @{…} | 生成链接 |
| 片段表达式 | ~{…} | jsp:include 作用,引入公共页面片段 |
文本值: ‘one text’ , ‘Another one!’ **,…**数字: 0 , 34 , 3.0 , 12.3 **,…**布尔值: true , false
空值: null
变量: one,two,… 变量不能有空格
3、文本操作字符串拼接: +
变量替换: |The name is ${name}|
4、数学运算运算符: + , - , * , / , %
5、布尔运算运算符: and , or
一元运算: ! , not
6、比较运算比较: > , < , >= , <= ( gt , lt , ge , le **)**等式: == , != ( eq , ne )
7、条件运算If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
设置属性值-th:attr多个值
th:text
改变标签内容
迭代条件运算Onions 2.41 yes
view
进入页面使用User is an administrator
User is a manager
User is some other thing
首先在使用的时候需要进行导入命名空间
xmlns:th="http://www.thymeleaf.org
Index
首页
初步使用
首先准备index.html
在template文件夹下面
然后编写
@GetMapping("/index")
public String index(){
return "index";
}
不需要加入index.html
获取示图参数这边我们主要是通过Model来处理的。
model.addAttribute(“users”,users);
@GetMapping("/index")
public String index(Model model){
model.addAttribute("msg","Hello哈");
return "index";
}




