SpringMVC + json

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工作流程图解

springmvc执行流程.jpg

7.2 springmvc工作流程详解

首先应清楚:控制器Controller = 处理器Handler
  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter处理器适配器(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)。
  5. HandlerAdapter经过适配调用具体的处理器(Controller)。调用之前有一个入参的过程,在Handler的入参过程中,如果有配置,spring还会做一些额外的工作:
HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
  1. Controller执行完成返回ModelAndView。
  2. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
  3. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  4. ViewReslover解析后返回具体View,这个view仅仅是一个页面(视图)名字,且没有后缀名。
  5. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  6. DispatcherServlet响应用户。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章