SpringMVC + json
文章目录
1. 导包及初始化配置
1.1 导包
spring-mvc需要的包:
spring核心包
spring-web
spring-webmvc
json需要的包:
jackson-core
jackson-databind
jackson-annotations
1.2 mavne依赖
<!--springmvc框架-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--json包(Springmvc默认使用jackson)-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
1.3 配置前端(核心)控制器
- web.xml中配置前端控制器。
<!--配置springmvc核心控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--
contextConfigLocation配置springmvc加载的配置文件(配置处理器、映射器、适配器等等)
如果不配置contextConfigLocation,默认加载WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml)
-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<!--在tomcat启动的时候就创建核心控制器-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
url-pattern:
第一种:*.action,访问以.action结尾由DispatcherServlet进行解析。
第三种:/,所有访问的地址都由DispatcherServlet进行解析,但对于静态文件的解析需要配置不让DispatcherServlet进行解析。
第三种:/*,错误的配置方法,运行结果报错。
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
1.4 配置静态资源放行
- applicationContext.xml中配置静态资源放行。
<!--静态资源放行-->
<mvc:default-servlet-handler/>
2. 实现控制器的三种方式
2.1 实现Controller接口
- 实现Controller接口
public class ControllerOne implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return null;
}
}
- applicationContext.xml配置controller对应的bean
<!-- name:配置controller的访问路径 -->
<bean name="/my1.do" class="com.yogie.controller.ControllerOne"></bean>
2.2 实现HttpRequestHandler接口
public class ControllerTwo implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
- 配置bean
<bean name="/my2" class="com.yogie.controller.ControllerTwo"></bean>
2.3 全注解的方式
2.3.1 开启注解支持和注解扫描
- applicationContext.xml中配置开启注解
<!--开启注解支持-->
<mvc:annotation-driven/>
<!--开启注解扫描-->
<context:component-scan base-package="com.yogie.controller"/>
@Controller
@RequestMapping("/my3")
public class ControllerThree {
@RequestMapping("/test")
public String test(){
return null;
}
}
2.3.2 springmvc注解大全
1、@Component 表示一个组件(类),把当前组件加入IOC容器,加入容器的组件的名称默认是类名且第一个字母小写。@Component("userDao")//相当于:<bean id="userDao" class=...> 可简化为:@Component
2、@Repository 表示是一个持久层的组件
3、@Service 表示是一个业务逻辑层的组件
4、@Controller 表示是一个控制层的组件
5、@Scope("prototype")指定对象单例还是多例
6、@Resource 默认根据修饰的字段名称会去IOC容器找对象自动注入,如果名称没有找到,在根据类型查找。如果该类型在IOC容器有多个对象,报错!根据类型没有找到对象,报错!
7、Resource(name="") 会根据指定的名称去容器找对象自动注入。
3. 获取参数的四种形式
3.1 直接获取
@RequestMapping("/param1")
//前台地址:localhost/param1?password=123&name=tom
public ModelAndView param1(String name,String password){
//前台传递过来的参数名与方法的参数名必须一致,顺序可以不一致
return null;
}
@RequestMapping("/param2")
//前台地址:localhost/param2?password=123&username=tom
//解决前台后台参数名字不一致的情况
public ModelAndView param2(@RequestParam("username")String name, String password){
return null;
}
3.2 封装到Javabean对象
@RequestMapping("/param3")
//前台地址:localhost/param3?pwd=123&name=tom
public ModelAndView param3(User user){
return null;
}
3.3 通过HttpServletRequest对象
@RequestMapping("/param4")
//前台地址:localhost/param4?password=123&name=tom
public ModelAndView param4(HttpServletRequest request){
//通过request对象的getParameter()方法获取值
String name = request.getParameter("name");
return null;
}
3.4 Restful风格传递参数
@RequestMapping("/param5/GET/{name}/{pwd}")
//前台地址:localhost/param5/GET/tom/123
//注意:使用restful风格传递多个参数时,前台的参数顺序与方法的形参要一致。
public ModelAndView param5(@PathVariable("name")String name,@PathVariable("pwd")String password){
return null;
}
4. 返回数据及视图的五种方式
- 配置视图解析器
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前端-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
4.1 Model方式
public String returnData1(Model model){
//实际上将数据放入到了request域中
model.addAttribute("name","tom");
User user = new User("tom","123");
//前台通过user来获取User对象的数据
model.addAttribute(user);
//返回视图名称:配置了视图解析器,会自动添加前缀后后缀
return "list";
}
4.2 ModelAndView方式
public ModelAndView returnData2(){
ModelAndView mv = new ModelAndView();
mv.addObject("name","tom");
//设置视图
mv.setViewName("list");
return mv;
}
4.3 HttpServletRequest方式
public void returnData3(HttpServletRequest request,HttpServletResponse response){
request.setAttribute("name","tom");
//转发的方式,不会走视图解析器
request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request,response);
}
4.4 直接返回对象
@RequestMapping("/data")
//这种情况返回的是默认视图,即:data.jsp
//data.jsp中可以获取到user对象的数据
public User returnData4(){
User user = new User("adf","123");
return user;
}
4.5 返回json数据
@RequestMapping("/data5")
@ResponseBody//添加这个注解后,数据将会以json的格式返回到前台,不会返回视图
public List<User> returnData5(){
List<User> list = Arrays.asList(...);
return list;
}
//注意:如果User对象中有日期类型的字段,需要给对应的get、set方法添加属性。
public class User{
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
public Date getDate() {
return date;
}
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public void setDate(Date date) {
this.date = date;
}
}
5. 请求转发与重定向
控制器中的视图设置,以下这两种情况都不会进入视图解析器的配置中加前缀后缀。但是区别于不加forward和redirect关键字的情况:如果不加这两个关键字,一定会进入视图解析器加前缀后缀。
5.1 转发
@RequestMapping("/forward")
public String forwordPage(){
return "forward:WEB-INF/jsp/hello.jsp";
}
5.2 重定向
@RequestMapping("/redirect")
public String redirectPage(){
return "redirect:index.html";
}
6. 解决Springmvc中文乱码问题
<!--springmvc乱码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6. 文件上传与下载
6.1 配置文件上传解析器
<!--文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--配置文件上传的最大尺寸为:100kb-->
<property name="maxUploadSize" value="102400"/>
</bean>
6.1 文件上传
@RequestMapping(path = "/upload",method = RequestMethod.POST)
public String upload(String name, MultipartFile upload, HttpServletRequest request) throws IOException {
System.out.println("post方法");
System.out.println("其他属性name::" + name);
System.out.println("上传文件的类型:" + upload.getContentType());
System.out.println("上传文件名称:" + upload.getName());
System.out.println("上传文件文件名:" + upload.getOriginalFilename());
// 上传的流
InputStream inputStream = upload.getInputStream();
// 获取webapp路径
String webapp = request.getServletContext().getRealPath("/uploads/");
System.out.println(webapp);
/*File file = new File(webapp, upload.getOriginalFilename());
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
// 如果upload文件夹不存在,就创建
parentFile.mkdirs();
}
// 拷贝到webapp一个目录里面
IOUtils.copy(inputStream, new FileOutputStream(file));*/
return "upload";
}
6.2 文件下载
@RequestMapping("/download")
public void download(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//解决文件名中文乱码,对文件名进行utf-8编码
String encode = URLEncoder.encode("springmvc执行流程.jpg", "UTF-8");
resp.setCharacterEncoding("utf-8");
//设置建议的下载文件名
resp.setHeader("Content-Disposition", "filename=springmvc执行流程.jpg");
//设置文件名的类型,查w3cschool中HTTP content-type对照表
resp.setHeader("Content-Type", "application/x-img");
// 准备文件
String webapp = req.getServletContext().getRealPath("/uploads/");
File file = new File(webapp, "springmvc执行流程.jpg");
FileInputStream inputStream = new FileInputStream(file);
IOUtils.copy(inputStream, resp.getOutputStream());
}
7. SpringMVC的执行流程
7.1 springmvc工作流程图解
7.2 springmvc工作流程详解
首先应清楚:控制器Controller = 处理器Handler
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter处理器适配器(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)。
- HandlerAdapter经过适配调用具体的处理器(Controller)。调用之前有一个入参的过程,在Handler的入参过程中,如果有配置,spring还会做一些额外的工作:
HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View,这个view仅仅是一个页面(视图)名字,且没有后缀名。
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户。