SpringMVC

image-20231023194013212


  • MVC : 模型(dao,service) 视图(jsp) 控制器(Servlet)


核心

<!--处理器映射器-->



<!--处理器适配器-->



<!--视图解析器-->





HelloSpringMVC

1.新建一个Moudle,添加web框架支持!

2.确定导入了SpringMVC的依赖!

项目结构 –> 工件 –> 在WEB-INF目录下创建lib文件夹 与class同级 –> 点击 + 选择库文件 –> 全选导入

3.配置web.xml,注册DispatcherServlet



原生流程

1、web.xml

  • 配置DispatchServlet
  • 请求
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<!--1.注册Servlet-->
<!-- 配置DispatchServlet:这个是SpringMVC的核心:请求分发器,前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- DispatchServlet 要绑定Spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--配置文件-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别:1(服务器一启动则同一起启动)-->
<load-on-startup>1</load-on-startup>
</servlet>

<!--
在SpringMVC中 ,/ 和 /*
/ :只匹配所有的请求,不会去匹配jsp页面
/* :匹配所有的请求,包括jsp页面(如请求为:index.jsp,会继续走视图解析器,无限拼接请求字符index.jsp.index.jsp)
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


</web-app>

2、springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">


<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>


<!--视图解析器 (将来:模板引擎 Thymeleaf Freemarker)
1.获取ModeLAndview的数据
2.解析ModelAndview的视图名字
3.拼接视图名字,找到对应的视图 wEB-INF/5sp/helLo.jsp
4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>


</beans>

image-20230608011342167


3、类Controller

  • 实现Controller接口,说明这就是一个控制器了
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

ModelAndView modelAndView = new ModelAndView();

//调用业务层

//封装对象,放ModeLAndview中。ModeL
modelAndView.addObject("键",值);

//视图跳转,封装要跳转的视图,放在ModeLAndview中
modelAndView.setViewName("ViewName");

return modelAndView;
}
}



4、配置请求的bean

  • 写完毕后,去springmvc-servlet.xml配置文件中注册请求的bean;name / id 对应请求路径,class对应处理请求的类
<!--BeanNameUrlHandlerMapping:bean-->
<bean name="/请求路径" class="com.chen.controller.HelloController"/>


简要分析执行流程

image-20230607234544202

  • 实现虚线

1.DispatcherServlet表示前置控器,是整个SpringMVC的控制中心。用户发出l求DispatcherServlet接收请求并拦截请求。

  • 假设请求的url为:http://localhost:8080/SpringMVC/hello
  • 如上url拆分成三部分
  • http://localhost:8080 :服务器域名
  • SpringMVC :部署在服务器上的web站点
  • hello :表示控制器
  • 如上url表示为:请求位于服务器localhost:8080上的Spring MVC站点的hello控制器。

2.HandlerMapping为处理器映射。DispatcherServleti 调用 HandlerMapping,HandlerMapping根据请求url查找Handler。

3.HandlerExecution 表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

5.HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

6.Handleri让具体的Controller执行。

7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

8.HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

9.DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

10.视图解析器将解析的逻辑视图名传给DispatcherServlet

11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

12.最终视图呈现给用户。









配置

依赖

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>


注解

@Controller

  • @Control1er注解的 类 会自动添加到spring上下文中 – 走视图层 – 隶属于@Component组件

@RestController

  • 前后端分离 – 当前 不走视图解析器 – 配置实现返回字字符串

@ResponseBody

  • 前后端分离 – 当前 方法 不走视图解析器 – 配置实现返回字字符串


@RequestMapping

  • 映射访问路径 – (置于类上+方法上 ==父子组件路径) – 方法上–单路径
@RequestMapping("/路径")
@RequestMapping(value = "路径", method = RequestMethod.POST )
//根据请求方法实现路径映射注解替换 ==》 RequestMapping(name="/add/{a}/{b}",method = RequestMethod.方法)
@GetMapping ----- @GetMapping("/add/{a}/{b}")
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping


@PathVariable

  • Restful风格 – 获取路径上的变量
@RequestMapping(value="/add/{a}/{b}",method = RequestMethod.GET)//方法上

(@PathVariable("a") int a,@PathVariable("b") int b) //参数


@RequestParam

  • 接收数据 – url请求上携带的数据 – 映射请求参数
@RequestParam("url中参数名") String name
  • 如果不传值,设置默认值
@RequestParam(required = false,defaultValue = "1") Integer pageNo


@RequestBody

请求传递的是json

从请求体中,获取数据,转为形参的对象

1、前端是json格式的数据,例如{id:1001,name:”Lisi”}

2、后端控制器方法,使用java对象接收参数,加入@RequestBody

3、服务器接收json转为对象,需要在对象类型的形参前面加入@RequestBody

@PostMapping("/user/json")
public User addUserJsonUser(@RequestBody User user){
}


@RequestHeader

请求头里面获取数据

public RespResult userCenter(@RequestHeader("uid") Integer uid){

}





注解开发【*】

1、web.xml

  • 注册DispatcherServlet【以下内容固定】
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<!--1.注册Servlet-->
<!-- 配置DispatchServlet:SpringMVC的核心:请求分发器,前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- DispatchServlet 要绑定Spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--配置文件-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别:1(服务器一启动则同一起启动)-->
<load-on-startup>1</load-on-startup>
</servlet>

<!--所有请求都会被springmvc栏截-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


<!--2.配置SpringMVC乱码过滤-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

2、springmvc-servlet 配置

  • 【以下内容固定】
    • 自动扫描
    • 资源过滤
    • 处理器和映射器
    • 视图解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--自动扫描包,让指定包下的注解生效,由I0C容器统一管理-->
<context:component-scan base-package=" packNaem "/>
<!--资源过滤Spring MVC不处理静态资源 .css .js .html .png-->
<mvc:default-servlet-handler />

<!--
支持mvc注解驱动 -- 处理器和映射器
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping.注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter.实例
这两个实例分别在类级别和方法级别处理。
而annotation-driven,配置帮助我们自动完成上述两个实例的注入。
-->
<mvc:annotation-driven/>

<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceviewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>

</beans>

3、创建制类

controller

  • @Controller : 被spring托管

代表这个类spring托管,被这个注解的类所有的方法,如果**返回值是String,**并且有具体页面可以跳转,那么就会被视图解析器解析


  • @RequestMapping(“/hello”) – 映射访问路径

    类前:为下层RequestMapping添加前缀 —– 拼接,前缀为/hello/子

    方法:拼接网址

//@Control1er注解的类会自动添加到spring上下文中
@Controller

//添加前缀--(如果在类上添加则为上层地址,类中的方法为下层地址--》/hello/chen)
//@RequestMapping("/hello")
public class HelloController {

//映射访问路径
@RequestMapping("/chen")
public String hello(Model model,HttpSession session){
//封装数据
model.addAttribute("msg","Hello,SpringMVCAnnotation");
return "hello"; //会被视图解析器处理
}
}

4、前端视图

image-20230608152525242


使用spring MVC必须配置的三大件:

  • 处理器映射器、处理器适配器、视图解析器
  • 通常,我们只需要手动配置视图解析器,而处理器映射器处理器适配器只需要开启注解驱动即可,而省去了大段的xm配置





Controller

控制器Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法
  • 在Spring MVC中,对于Controller的配置方式有很多种

1、实现Controller接口【非注解】

  • 参考上面 HelloSpringMVC



2、@Controller【注l解】

  • @Controller

    • @Controller注解的类会自动添加到spring上下文中

    • 被这个注解的类所有的方法,如果返回值是String,并且有具体页面可以跳转,那么就会被视图解析器解析:


@Controller //代表这个类spring托管
public class ControllerTest2 {

}


3、@RequestMapping

  • 当只有一个参数,value可以省略 @RequestMapping(value=”value/t2”)

  • 映射访问路径 – (置于类上+方法上 ==父子组件路径) – 方法上–单路径

  • 项目中遇到的映射请求配置:

    @RequestMapping(value = “路径”, method = RequestMethod.POST )


@Controller
public class ControllerTest3 {

//映射访问路径
@RequestMapping("/t2")
public String test2(Model model){
//Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg","ControllerTest2");

//返回请求地址
return "test2";
}

@RequestMapping("/t3")
public String test3(Model model){
model.addAttribute("msg","test3");
return "test3";
}
}

访问路径:http ://localhost:8084/t2

  • 同时注解类与方法
@Controller
@RequestMapping("/c3")
public class ControllerTest3 {

@RequestMapping("/t2")
public String test3(Model model){
model.addAttribute("msg","ControllerTest3");
return "test";
//return "admin/test";
}

}

访问路径:http: //localhost:8084/c3/t2






Restful风格

  • 安全,隐藏参数

  • / 为url分隔符,(参数、页面)


@PathVariable

  • 在Spring MVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URI模板变量
@Controller
public class RestFulController {

//@RequestMapping(value="/add/{a}/{b}",method = RequestMethod.GET)
@RequestMapping("/add/{a}/{b}")
public String test1(@PathVariable("a") int a,@PathVariable("b") int b, Model model){
int res=a+b;
model.addAttribute("msg","结果集为:"+res);
return "test";
}

}

原来的 :http ://localhost:8084/add?a=1&b=1

RestFul : http ://localhost:8084/add/a/b


  • 简化注解实现@RequestMapping中的method
  • @RequestMapping(name=”/add/{a}/{b}”,method = RequestMethod.GET)
//根据请求方法实现路径映射注解  == RequestMapping(name="/add/{a}/{b}",method = RequestMethod.方法)
@GetMapping ----- @GetMapping("/add/{a}/{b}")
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping





结果跳转方式

设置ModelAndView对象,根据vilew的名称,和视图解析器跳转到指定的页面

页面:「视图解析器前缀] + viewName +「视图解析器后缀]

<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceviewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>

对应的controller类【不使用注解】

public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

//处理请求且返回一个模型与视图对象
ModelAndView mv=new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}

【使用注解】

@Controller
public class ControllerTest2 {

//映射访问路径
@RequestMapping("/t2")
public String test2(Model model){
model.addAttribute("msg","ControllerTest2");

//返回请求地址
return "test";
}

}

  • 原生ServletAPI

image-20230608174757674



1、配置视图解析器

  • 不需要全命名

  • 默认是转发(拼接下一页url),不改变url

//转发
return "test";

  • 重定向(跳转去指定页面)
    • redirect:/

重定向,不需要视图解析器,本质就重新请求一个新地方,所以注意路径问题

//重定向
return "redirect:/index.jsp";


2、不配置视图解析器

  • 全命名–加前缀和后缀
//转发一  --前缀加 /
return "/WEB-INF/jsp/test.jsp";

//转发二
return "forward:/WEB-INF/jsp/test.jsp";


//重定向
return "redirect:/WEB-INF/jsp/test.jsp"





数据处理

接收数据

1、提交的域名称和处理方法的参数名一致

提交数据:http:/localhost:8080/hello?name=chen

处理方法:

  • @RequestParam(“url中参数名”)
@GetMapping("/hello")
public String test1(@RequestParam("name") String name,HttpSession session){
//接收前端参数
System.out.println("接收到前端的参数为:"+name);
}


2、提交的域名称和处理方法的参数名不一致

提交数据:http:/localhost:8080/hello?username=chen

处理方法:

  • @RequestParam(“url中参数名”) 映射字段
@GetMapping("/hello")
public String test1(@RequestParam(" username") String name){
//接收前端参数
System.out.println("接收到前端的参数为:"+name);
}


3、**@RequestBody** 从请求体中,获取数据,转为形参的对象

从请求体中,获取数据,转为形参的对象

1、前端是json格式的数据,例如{id:1001,name:”Lisi”}

2、后端控制器方法,使用java对象接收参数,加入@RequestBody

3、服务器接收json转为对象,需要在对象类型的形参前面加入@RequestBody

@PostMapping("/user/json")
public User addUserJsonUser(@RequestBody User user){
}

3、接收的参数为对象类型

1.接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用

2.假设传递的是一个对User,匹配User对象中的字段名:如果名字一致则OK,否则,匹配不到Null

  • 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
public int id;
private String name;
private int age;
}

  • 提交数据:localhost:8084/t2?id=1&name=陈呀&age=18

  • 处理方法:要求提交的表单和对象的属性一致,参数使用对象即可

@GetMapping("/user")
public String test2(User user){
System.out.println(user);
return "test";
}

说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。



数据显示到前端

第一种:通过ModelAndView【非注解】

  • addObject
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

//处理请求且返回一个模型与视图对象
ModelAndView mv=new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;

}
}


第二种:通过ModelMap

ModelMap

@GetMapping("/t1")
public String test1(@RequestParam("username") String name, ModelMap model){
//将返回的结果传输给前端,model
model.addAttribute("msg",name);
return "test";
}


第三种:通过Model【重点】

@GetMapping("/t1")
public String test1(@RequestParam("username") String name, Model model){
//1.接收前端参数
System.out.println("接收到前端的参数为:"+name);

//2.将返回的结果传输给前端,model
model.addAttribute("msg",name);

//3.视图跳转
return "test";
}


对比

Model 只有寥寥几个方法只适合用丁储存数据,简化了新于对丁Model对象的操作和理解

ModelMap 继承了LinkedMap:除了实现了自身的一些方法,同样的继承LinkedMap的方法和特性

ModelAndview 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。






乱码问题

1、自定义过滤器

package com.chen.filter;

import javax.servlet.*;
import java.io.IOException;
import java.util.logging.LogRecord;

public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}

@Override
public void destroy() {

}
}

  • 在web.xml中注册
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.chen.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>



2、Spring提供在web.xml中配置【重点】

<!--2.配置SpringMVC乱码过滤-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


1、修改tomcat配置文件:设置编码

包–conf–servel.xml

<Connector URIEncoding="utf-8"port="8080"protocol="HTTP/1.1"
connectionTimeout="20000"
redirectport="8443"/>





JSON

  • 对象表示为键值对,数据由逗号分隔

  • 花括号保存对象

  • 方括号保存数组



前端

对象转json – JSON.stringify( );

//编写一个JavaScript 对象
let user={
name : "辰呀",
age:3,
sex:"男"
}

//js对象转json对象
let json = JSON.stringify(user);

JSON对象 转 js 对象 – JSON.parse( )

//将JSON 对象转换为JavaScript对象
let obj =JSON.parse(json)
console.log("obj",obj)


Jackson

1、导入依赖

<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>

2、乱码解决

  • springmvc-servlet.xml配置文件
<!--JS0N乱码问题配置-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

原生方案:

@RequestMapping(value = "j1", produces = "application/json;charset=utf-8")

3、测试

前后端分离,不需要跳转视图,只返回数据,不要@Controller

@RestController 【放在类上】

**@ResponseBody 【放在方法上】 **

  • 写入json数据:writeValueAsString

  • 对象–转为Json

//@Controller
@ResponseBody //整个类不会走视图解析器,不跳转界面,直接返回一个字符串
public class UserController {

@RequestMapping("j1")
@ResponseBody//当前方法不会走视图解析器,不跳转界面,直接返回一个字符串
public String json1() throws JsonProcessingException {

User user =new User("辰1",3,"男");

//jackson,ObjectMapper
ObjectMapper mapper=new ObjectMapper();
String str = mapper.writeValueAsString(user);

return str.toString();
}
}

代码复用–抽取为工具类

  • 创建工具类JsonUtils
  • 最终只是写入json
public class JsonUtils {

public static String getJson(Object object) {
return getJson(object,"yyyy-MM--dd HH:mm:ss");
}


//将传递的 时间戳 转为 单位时间
public static String getJson(Object object,String dateFormt){
ObjectMapper mapper=new ObjectMapper();

//不使用时间戳的方式
//1.使用ObjectMapper(false=不使用时间戳的方式输出,即显示单位)
mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
//自定义日期的格式
SimpleDateFormat sdf =new SimpleDateFormat(dateFormt);
mapper.setDateFormat(sdf);

try {
return mapper.writeValueAsString(object);
}catch (JsonProcessingException e){
e.printStackTrace();
}
return null;
}
}



  • 列表–转为Json

@RequestMapping(value = "j2")
@ResponseBody
public String json2() throws JsonProcessingException {

//jackson,ObjectMapper
ObjectMapper mapper=new ObjectMapper();

List<User> userList=new ArrayList<>();
//创建一个对象
User user1 =new User("辰1",3,"男");
User user2 =new User("辰2",3,"男");
User user3 =new User("辰3",3,"男");
User user4 =new User("辰4",3,"男");
User user5 =new User("辰5",3,"男");

userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);

return JsonUtils.getJson(userList);
}



  • 时间Date–转为Json

@RequestMapping(value = "j3")
public String json3() throws JsonProcessingException {

Date date = new Date();
return JsonUtils.getJson(date,"yyyy-MM--dd HH:mm:ss");

}


FastJson

json对象 <==> JavaBean < == > json字符串

依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>


fastjson三个主要的类

  • 【JSONObject代表json对象】

    • JSONObject实现了Map接口,猜想JSONObject底层操作是由Map实现的。
    • JSONObjecti对应json对象,通过各种形式的get0方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取”键:值”对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。

  • 【JSONArray代表json对象数组】

    • 内部是有Lst接口中的方法来完成操作的。

  • 【JSON代表JSONObject和)SONArray的转化】

    • JSON类源码分析与使用

    • 仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。


  • 直接导入类即可 JSON.方法【无需new ObjectMapper();】
  @RequestMapping(value = "j2")
@ResponseBody
public String json2() throws JsonProcessingException {

List<User> userList=new ArrayList<User>();
//创建一个对象
User user1 =new User("辰1",3,"男");
User user2 =new User("辰2",3,"男");
User user3 =new User("辰3",3,"男");
User user4 =new User("辰4",3,"男");
User user5 =new User("辰5",3,"男");

userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);

System.out.println("****java对象转JS0N字符串****");
String str1 = JSON.toJSONString(userList);
System.out.println("JSON.toJSONString(userList)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);


System.out.println("\n****JS0N字符串 转 JaVa对象***");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseobject(str2,User.class)==>"+jp_user1);

System.out.println("\n****JaVa对象 转 JS0N对象***");
JSONObject jsonobject1 = (JSONObject)JSON.toJSON(user2);
System.out.println("(JSONObject)JSON.toJSON(user2)==>"+jsonobject1.getString("name"));

System.out.println("\n***JS0N对象 转 JaVa对象****");
User to_java_user = JSON.toJavaObject(jsonobject1,User.class);
System.out.println("JSON.toJavaobject(jsonobject1,User.class)==>"+to_java_user);

//获取json中指定数据--转为map
String json:="{"age\":30,\"id\":5671,\"name\":\"周畅"}";
JSONObject jsonobject = JSONObject.parseobject(json);
//JSONObject是-个map
String name jsonobject.getstring(key:"name");
System.out.println ("name="+name);
int age jsonobject.getIntValue(key:"age");
System.out.println("age ="age);

//对象中存在对象
Stringstring JSONObject.parseobject(json).getJSONObject("school").getstring(key:"address");


return "hello";
}





HttpClient

  • 调用第三方接口

一个开源的 HTTP 客户端库,它允许您以编程方式发送 HTTP 请求并处理 HTTP 响应。它提供了简单、灵活的 API,可用于与 Web 服务器进行通信。


依赖

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>

Get方式

public void testGet(){
//发起get请求,编程方式处理http请求。
String url="https://restapi.amap.com/v3/ip?key=0113a13c88697dcea6a445584d535837&ip=60.25.188.64";

//1、创建HttpClient对象
CloseableHttpClient client = HttpClients.createDefault();

//2.创建HttpGet对象
HttpGet httpGet = new HttpGet(url);

//3.执行请求,使用client对象的方法,执行请求后获取返回结果
//CloseableHttpResponse是返回结果,相当于HttpServletResponse
try {
CloseableHttpResponse response = client.execute(httpGet);

//从response获取应答消息
if (response.getStatusLine().getStatusCode()== HttpStatus.SC_OK){
//4、获取数据
//response.getEntity().getContent();//数据
String json = EntityUtils.toString(response.getEntity());
System.out.println("访问ip的应答结果:" + json);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//5、关闭资源
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Post方式

public void testPsot(){
//1、创建HttpClient对象
CloseableHttpClient client = HttpClients.createDefault();

//2、创建HttpPost对象,表示post请求
String url = "https://restapi.amap.com/v3/ip";
HttpPost httpPost = new HttpPost(url);

//3、准备post请求的参数
List<NameValuePair> params =new ArrayList<NameValuePair>();
//添加参数 BasicNameValuePair类,实现了NameValuePair接口
// BasicNameValuePair(参数名,参数值)
params.add(new BasicNameValuePair("key","0113a13c88697dcea6a445584d535837"));
params.add(new BasicNameValuePair("ip","60.25.188.64"));

//4、设置HttpPost使用参数
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));

//5、执行请求
CloseableHttpResponse response = client.execute(httpPost);

//6、读取数据
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
String json = EntityUtils.toString(response.getEntity());
System.out.println("json=" + json);
}

} catch (Exception e) {
e.printStackTrace();
}
}





拦截器

  • Spring MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用,把当前拦截器横切入当前访问的控制器

  • 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js.是不会进行拦截的-

1、自定义拦截类

实现 HandlerInterceptor 接口,重写全部方法

public class MyInterceptor implements HandlerInterceptor {

//return ture; 执行下一个拦截器,放行
//return false; 不执行下一个拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==================方法处理前==================");
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("==================方法处理后==================");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("==================清理==================");
}
}



2、配置拦截器

  • spring-mvc.xml

<!--视图解析器-->

<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--包括这个请求下面的所有的请求-->
<mvc:mapping path="/**/"/>
<bean class="com.chen.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

  • 输出结果(AOP

————–方法处理前————–

Intercepter ==> test()方法执行了

————–方法处理后————–

——————清理——————-



3、常用【登录判断拦截】

  • 拦截类
public class MyInterceptor implements HandlerInterceptor {

//return ture; 执行下一个拦截器,放行
//return false; 不执行下一个拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==================方法处理前==================");
HttpSession session = request.getSession();
//放行:判断什么情况下登录
//登录页面也会放行
if (request.getRequestURI().contains("登录请求的url:goLogin")){
return true;
}
//提交登录请求
if (request.getRequestURI().contains(" ")){
return true;
}
//第一次登录,没有session
if (session.getAttribute(" sessiom中的键 ")!=null){
return true;
}


//判断什么情况下没有登录
request.getRequestDispatcher("重定向的页面").forward(request,response);
return false;

}
}





文件上传

1、依赖

<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>


2、文件上传配置

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>

CommonsMultipartFile 的 常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中


3、代码

  • 前端
    • enctype=”multipart/form-data”
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>

Controller

  • 1、方式一
@Controller
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {

//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();

//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);

//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);

InputStream is = file.getInputStream(); //文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流

//读取写出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}


2、方式二

/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);

//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));

return "redirect:/index.jsp";
}





文件下载

  • Controller
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/图片的下载地址");
String fileName = "基础语法.jpg";

//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));

File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();

byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}

  • 请求
<a href="/download">点击下载</a>