首页 > 编程学习 > SpringMVC学习笔记

SpringMVC学习笔记

发布时间:2022/11/18 21:10:17

目录

SpringMVC

为什么出现了SpringMVC?

什么是SpringMVC?

简单使用

SpringMVC工作流程

设置bean加载控制

在服务器启动时加载SpringConfig 

后台接受五种类型参数传递

REST风格

描述

RESTful入门

新建以下目录

实体类

控制器

统一异常处理

新建Code类用于记录状态码

新建异常处理类

新建异常处理器

模拟异常

结果

拦截器

使用

文件上传

part方式

Multipart方式 

IDEA SpringMVC配置详情

XML方式(常用)

依赖引入

web.xml文件

Application.xml

SpringMVC.xml

路径一览

 纯注解方式

依赖引入

ServletContainersInitConfig

SpringConfig

SpringMVCConfig

注解方式返回给前台的数据乱码的解决


 

SpringMVC

为什么出现了SpringMVC?

因为servlet处理请求和数据的时候,存在的问题是一个servlet只能处理一个请求 针对web层进行了优化,采用了MVC设计模式,将其设计为controller、view和Model’

什么是SpringMVC?

SpringMVC是一种基于Java实现MVC模型的轻量级Web框架

优点是使用简单、开发便捷(相比于Servlet) 灵活性强

简单使用

1 依赖引入

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
//解决冲突的问题
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

2 建立基本目录

目录如下 

3 新建SpringMVC配置类

package com.learn.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.learn.controller")
public class SpringMVCConfig {
}

4 新建web.xml配置类(用于替换web.xml)

package com.learn.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public class ServletContainersInitConfig extends
        AbstractDispatcherServletInitializer {
    //加载springmvc配置类
    protected WebApplicationContext createServletApplicationContext() {
//初始化WebApplicationContext对象
        AnnotationConfigWebApplicationContext ctx = new
                AnnotationConfigWebApplicationContext();
//加载指定配置类
        ctx.register(SpringMVCConfig.class);
        return ctx;
    }

    //设置由springmvc控制器处理的请求映射路径
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //加载spring配置类
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

5 新建控制器

package com.learn.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {
    //浏览器请求的路径
    @RequestMapping("/save")
    //标识发送的数据为JSON格式
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'info':'springmvc'}";
    }
}

6 最终目录

7 配置web服务器

添加webapp框架

 配置工件

配置服务器

 8 启动调试

 相关知识点

SpringMVC是基于Spring的,在pom.xml只导入了spring-webmvc jar包的原因是它会自动依赖
spring相关坐标
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器
的抽象类
AbstractDispatcherServletInitializer提供了三个接口方法供用户实现
createServletApplicationContext方法,创建Servlet容器时,加载SpringMVC对应
的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用
范围为ServletContext范围,即整个web容器范围
getServletMappings方法,设定SpringMVC对应的请求映射路径,即SpringMVC拦截哪些
请求
createRootApplicationContext方法,如果创建Servlet容器时需要加载非SpringMVC
对应的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
createServletApplicationContext用来加载SpringMVC环境
createRootApplicationContext用来加载Spring环境

@RequestMapping

SpringMVC控制器类或方法定义上方

设置当前控制器方法请求访问路径

@ResponseBody

SpringMVC控制器类或方法定义上方

设置当前控制器方法响应内容为当前返回值,无需解析

SpringMVC工作流程

1. 发送请求http://localhost/save
2. web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理
3. 解析请求路径/save
4. 由/save匹配执行对应的方法save()
上面的第五步已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法
5. 执行save()
6. 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方

设置bean加载控制

1 修改Spring配置类,设定扫描范围为精准范围。

2 修改Spring配置类,设定扫描范围为com.itheima,排除掉controller包中的bean

@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
excludeFilters属性:设置扫描加载bean时,排除的过滤规则
type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
ANNOTATION:按照注解排除
ASSIGNABLE_TYPE:按照指定的类型过滤
ASPECTJ:按照Aspectj表达式排除,基本上不会用
REGEX:按照正则表达式排除
CUSTOM:按照自定义规则排除
大家只需要知道第一种ANNOTATION即可
classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean

在服务器启动时加载SpringConfig 

1 更改ServletContainersInitConfig 配置类

public class ServletContainersInitConfig extends
AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new
AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new
AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}
1

2 ServletContainersInitConfig 的内容替换成如下

public class ServletContainersInitConfig extends
AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

后台接受五种类型参数传递

普通参数

  public String commonParam(@RequestParam("name") String name, int age)
    {
        System.out.println("普通参数传递 name ==> "+name);
        System.out.println("普通参数传递 age ==> "+age);
        return "{'module':"+name+"}";
    }

POJO类型参数

  //POJO类型的参数,直接使用实体类接受,但是注意,实体类中的字段必须和参数名相同
    public String commonParam(User user)
    {
        System.out.println("普通参数传递 name ==> "+user.getName());
        System.out.println("普通参数传递 age ==> "+user.getAge());
        return "{'module':"+user.getName()+"}";
    }

嵌套POJO类型参数

实体

public class Ts {
    User user;
    Address address;
}
    //POJO类型的嵌套参数,直接使用实体类接受,但是注意,实体类中的字段必须和参数名相同
    public String commonParam(Ts ts)
    {
        System.out.println("普通参数传递 name ==> "+ts.getUser().getName());
        System.out.println("普通参数传递 age ==> "+ts.getUser().getAge());
        return "{'module':"+ts.getUser().getName()+"}";
    }

请求写法

数组类型参数

    //数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
    public void commonParam(String[] array)
    {
        System.out.println(Arrays.toString(array));
    }

请求参数的名,必须要和后台的数组名相同 

集合类型参数

    public String listParam(@RequestParam List<String> likes){
        System.out.println("集合参数传递 likes ==> "+ likes);
        return "{'module':'list param'}";
    }

 请求参数的名,必须要和后台的集合名相同

JSON传输参数 

SpringMVC接收JSON数据的实现步骤为:

(1)导入jackson包

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>

(2)使用PostMan发送JSON数据

(3)开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解

@EnableWebMvc
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)参数传递 list ==> "+list);
return "{'module':'list pojo for json param'}";
}

(4)Controller方法的参数前添加@RequestBody注解

@RequestParam与@RequestBody的区别:
 

@RequestParam用于接收url地址传参,表单传参【application/x-www-formurlencoded】 @RequestBody用于接收json数据【application/json】 @RequestMapping("/listPojoParamForJson") @ResponseBody public String listPojoParamForJson(@RequestBody List list){ System.out.println("list pojo(json)参数传递 list ==> "+list); return "{'module':'list pojo for json param'}"; } 应用 后期开发中,发送json格式数据为主,@RequestBody应用较广 如果发送非json格式数据,选用@RequestParam接收请求参数

时间类型参数

如果格式不一致,需要我们使用@DateTimeFormat来进行格式化

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date
date2)
System.out.println("参数传递 date ==> "+date);
System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}

响应

controller在接受请求后可以转发给service,从而获得一些响应内容,我们需要把他们返回给前台

@EnableWebMvc
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("传智播客");
user1.setAge(15);
User user2 = new User();
user2.setName("黑马程序员");
user2.setAge(12);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
}
}

返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖 @ResponseBody注解和@EnableWebMvc注解

返回jsp页面

@Controller
public class UserController {
@RequestMapping("/toJumpPage")
//注意
//1.此处不能添加@ResponseBody,如果加了该注入,会直接将page.jsp当字符串返回前端
//2.方法需要返回String
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
}
}

返回纯文本

@Controller
public class UserController {
@RequestMapping("/toText")
//注意此处该注解就不能省略,如果省略了,会把response text当前页面名称去查找,如果没有
回报404错误
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
}

REST风格

描述

rest:表现形式状态转换,它是一种软件架构风格
当我们想表示一个网络资源的时候,可以使用两种方式:
传统风格资源描述形式
http://localhost/user/getById?id=1 查询id为1的用户信息
http://localhost/user/saveUser 保存用户信息
REST风格描述形式
http://localhost/user/1
http://localhost/user
传统方式一般是一个请求url对应一种操作,这样做不仅麻烦,也不安全,因为会程序的人读取了你的
请求url地址,就大概知道该url实现的是一个什么样的操作。
查看REST风格的描述,你会发现请求地址变的简单了,并且光看请求URL并不是很能猜出来该URL的
具体功能
所以REST的优点有:
隐藏资源的访问行为,无法通过地址得知对资源是何种操作
书写简化

根据REST风格对资源进行访问称为RESTful

RESTful入门

新建以下目录

其中配置文件可看(就在文章的下面)--》IDEA SpringMVC配置详情《---

实体类

public class Book {private String name;
    private double price;}


    public class User {
        private String name;
        private int age;
    }

控制器


@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private BookService bookService;
    @PostMapping
    public Result save(@RequestBody Book book) {
        boolean b = bookService.save(book);
        return new Result(b?Code.SAVE_OK:Code.SAVE_ERR);
    }
    @PutMapping
    public Result update(@RequestBody Book book) {
        boolean b = bookService.update(book);
        return new Result(b?Code.UPDATE_OK:Code.UPDATE_ERR);
    }
}

统一异常处理

新建Code类用于记录状态码

package com.learn.entity;

public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;
    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;

    //异常处理状态码
    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;
    public static final Integer BUSINESS_ERR = 60002;
}

新建异常处理类

package com.learn.exception;
//让自定义异常类继承RuntimeException的好处是,后期在抛出这两个异常的时候,就不用在
//try...catch...或throws了
//自定义异常类中添加code属性的原因是为了更好的区分异常是来自哪个业务的

public class BusinessException extends RuntimeException{
    private Integer code;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }
    public BusinessException(Integer code, String message, Throwable cause) {
//        这里的super直接传到了Throwable类的身上
        super(message, cause);
        this.code = code;
    }
}
package com.learn.exception;

public class SystemException extends RuntimeException{
    private Integer code;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }
    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }
}

新建异常处理器

package com.learn.exception;

import com.learn.entity.Code;
import com.learn.entity.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


@RestControllerAdvice
public class ProjectExceptionAdvice {
    //@ExceptionHandler用于设置当前处理器类对应的异常类型
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发人员,ex对象发送给开发人员
        return new Result(null,ex.getCode(),ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex){
        return new Result(null,ex.getCode(),ex.getMessage());
    }

    //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
    @ExceptionHandler(Exception.class)
    public Result doOtherException(Exception ex){
    //记录日志
    //发送消息给运维
    //发送邮件给开发人员,ex对象发送给开发人员
        return new Result(null,Code.SYSTEM_UNKNOW_ERR,"系统繁忙,请稍后再试!");
    }
}

模拟异常

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id)
    {
        if(id==1)
        {
            //抛出异常后下面的delete程序就不会再执行了
            throw new BusinessException(Code.BUSINESS_ERR,"有人想干掉管理员!",new Throwable());
        }
        boolean b = bookService.delete(id);
        return new Result(b?Code.DELETE_OK:Code.DELETE_ERR);
    }

结果

拦截器

(1)浏览器发送一个请求会先到Tomcat的web服务器
(2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源
(3)如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问
(4)如果是动态资源,就需要交给项目的后台代码进行处理
(5)在找到具体的方法之前,我们可以去配置过滤器(可以配置多个),按照顺序进行执行
(6)然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截
(7)如果满足规则,则进行处理,找到其对应的controller类中的方法进行执行,完成后返回结果
(8)如果不满足规则,则不进行处理
(9)这个时候,如果我们需要在每个Controller方法执行的前后添加业务,具体该如何来实现?
这个就是拦截器要做的事。
拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法
的执行
作用:
在指定的方法调用前后执行预先设定的代码
阻止原始方法的执行
总结:拦截器就是用来做增强

使用

新建拦截器ProjectInterceptor

package com.learn.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class ProjectInterceptor implements HandlerInterceptor {
    @Override
    //原始方法调用前执行的内容
    public boolean preHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler) throws Exception {
        System.out.println("preHandle...");
        //获取请求头
        String header = request.getHeader("Content-Type");
        System.out.println("请求头为:"+header);
        HandlerMethod method=(HandlerMethod)handler;
        System.out.println("执行的方法是:"+method.getMethod().getName());
        //如果返回为fasle则此拦截器中的方法将不再执行
        return true;
    }
    @Override
    //原始方法调用后执行的内容
    public void postHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
        HandlerMethod method=(HandlerMethod)handler;
        System.out.println("执行的方法是:"+method.getMethod().getName());
    }
    @Override
    //原始方法调用完成后执行的内容
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex) throws Exception
    {
        System.out.println("afterCompletion...");
        HandlerMethod method=(HandlerMethod)handler;
        System.out.println("执行的方法是:"+method.getMethod().getName());
    }

}

在springmvc中配置拦截器

<!--    拦截器配置-->
    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置一个全局拦截器,拦截所有请求 -->
        <bean class="com.learn.interceptor.ProjectInterceptor" />
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <!-- 配置不需要拦截作用的路径 -->
            <mvc:exclude-mapping path="/a" />
            <!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
            <bean class="com.learn.interceptor.ProjectInterceptor" />
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/gotoTest" />
            <!-- 定义在<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
            <bean class="com.learn.interceptor.ProjectInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

 

文件上传

part方式

新建文件上传控制器

package com.learn.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.util.Collection;

@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class FileUpdateController {

    //    part方式单文件上传
    @GetMapping("/updateImg")
    private String imgUpdate(HttpServletRequest request) {
        try {
            Part image = request.getPart("image");
            String realPath = request.getServletContext().getRealPath("/WEB-INF/img");
            image.write(realPath + image.getSubmittedFileName());
            return "success";
        } catch (Exception e) {
            System.out.println("图片上传失败");
            return "fail";
        }
    }

    //    part方式多文件上传
    @GetMapping("/updateImgs")
    private String imgsUpdate(HttpServletRequest request) {
        try {
            Collection<Part> requestParts = request.getParts();
            //获取上传路径(web目录中的)
            String realPath = request.getServletContext().getRealPath("/WEB-INF/img");
            requestParts.forEach(part -> {
                try {
                    part.write(realPath + part.getSubmittedFileName());
                } catch (Exception e) {
                    System.out.println(part.getSubmittedFileName() + "上传出错!");
                }
            });
            return "success";
        } catch (Exception e) {
            System.out.println("图片上传失败");
            return "fail";
        }
    }
}

web.xml配置

    <servlet>
<!--        配置文件上传-->
        <multipart-config>
<!--            单位为字节-->
<!--            单个文件大小-->
            <max-file-size>5242880</max-file-size>
<!--            一次请求所有文件大小-->
            <max-request-size>52428800</max-request-size>
        </multipart-config>
    </servlet>

Multipart方式 

以下的代码可能会上传失败

依赖引入

<!--        springmvc文件上传-->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

springmvc.xml

<!--    配置视图解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

编写控制器

package com.learn.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;

@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class FileUpdate2Controller {
    @GetMapping("/fileUpdate")
    protected String fileUpdate(HttpServletRequest request, MultipartFile multipartFile)
    {
        try {
            String realPath = request.getServletContext().getRealPath("/WEB-INF/img/");
            String filename = multipartFile.getOriginalFilename();
            multipartFile.transferTo(new File(realPath,filename));
            return "success";
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
            return "fail";
        }
    }
}

IDEA SpringMVC配置详情

XML方式(常用)

依赖引入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SSM2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--spring相关的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <!-- aspectjweaver-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
            <scope>runtime</scope>
        </dependency>
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!--json-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

<!--        springmvc文件上传-->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

web.xml文件

<?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">

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--需要给ContextLoaderListener指定Spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:Application.xml</param-value>
    </context-param>
    <!--    tomcat整合SpringMVC-->

    <!--SpringMVC容器,核心:DispatcherServlet-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMVC.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>

<!--        配置文件上传-->
        <multipart-config>
<!--            单位为字节-->
<!--            单个文件大小-->
            <max-file-size>5242880</max-file-size>
<!--            一次请求所有文件大小-->
            <max-request-size>52428800</max-request-size>
        </multipart-config>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--Filter处理乱码-->
    <filter>
        <filter-name>encodingFilter</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>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <!--      Todo  注意这里如果过滤器不生效,请去掉*号-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

Application.xml

 Spring配置文件

<?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
     http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="com.learn">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driveClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.learn.dao"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

SpringMVC.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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com.learn.controller"/>

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.learn.interceptor.ProjectInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

    <mvc:annotation-driven>
        <mvc:message-converters>

            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=utf-8</value>
                    <value>application/json;charset=UTF-8</value>
                </list>
             </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="5242880" />
        <property name="maxInMemorySize" value="4096" />
        <property name="defaultEncoding" value="UTF-8"></property>
    </bean>

    <mvc:default-servlet-handler/>

    <mvc:cors>
        <mvc:mapping path="/**" />
    </mvc:cors>
</beans>

路径一览

 纯注解方式

(返回给前台的中文可能会出现乱码)

依赖引入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SSM2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--spring相关的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <!-- aspectjweaver-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
            <scope>runtime</scope>
        </dependency>
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!--json-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

<!--        springmvc文件上传-->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

ServletContainersInitConfig

package com.learn.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer
    {
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{SpringMVCConfig.class};
        }
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
        protected Class<?>[] getRootConfigClasses() {
            return new Class[0];
        }
        //乱码处理(只能处理后台接受到的参数乱码问题,返回给前台的json数据不会乱码)
        @Override
        protected Filter[] getServletFilters() {
            CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
            encodingFilter.setEncoding("UTF-8");
            encodingFilter.setForceRequestEncoding(true);
            HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
            return new Filter[]{encodingFilter, hiddenHttpMethodFilter};
        }

    }

SpringConfig

package com.learn.config;

import com.learn.controller.UserController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
@ComponentScan(value = "com.learn",excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = UserController.class
))
public class SpringConfig {
}

SpringMVCConfig

package com.learn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.learn.controller")
public class SpringMVCConfig {

}

注解方式返回给前台的数据乱码的解决

就是要在 @RequestMapping上加上produces = "text/html;charset=utf-8"

给个实例

package com.learn.controller;
import com.learn.entity.Ts;
import com.learn.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.List;

@Controller
public class UserController {
    //浏览器请求的路径
    @RequestMapping(value = "/getdata",produces = "text/html;charset=utf-8")
    //标识发送的数据为JSON格式
    @ResponseBody
    //如果前端传的参数和后端不一样可以使用注解,@RequestParam
    public String commonParam(@RequestParam("name") String name, int age)
    {
        System.out.println("普通参数传递 name ==> "+name);
        System.out.println("普通参数传递 age ==> "+age);
        return "{'module':"+name+"}";
    }
}

Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式