SpringBoot 一篇搞定(Cookie Session 跳转 内容协商 converter解析器 thymeleaf)

SpringBoot 一篇搞定(Cookie Session 跳转 内容协商 converter解析器 thymeleaf),第1张

SpringBoot 一篇搞定(Cookie Session 跳转 内容协商 converter解析器 thymeleaf)

文章目录
  • 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放行可以保证作用域参数丢失的问题。

通过Request
request.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 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 作用,引入公共页面片段 2、字面量

文本值: ‘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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4748301.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-08
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存