SpringMVC
一、SpringMVC
介绍
-
回顾MVC
M:model 模型(dao,service)
V:view 视图(jsp)
C:controller 控制器(Servlet) -
MVVM
M:model 模型(dao,service)
V:view 视图(jsp)
VM:ViewModel :双向绑定(前后端分离的核心) -
Spring
我们可以将SpringMVC中所有要用到的bean,注册到Spring中! -
SpringMVC
- Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架
- Spring的web框架围绕DispatcherServlet设计,DispatcherServlet的作用是将请求分发到不同的处理器。
- Spring MVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(继承自HttpServlet)
- SpringMVC必须配置的三大件:
处理器映射器,处理器适配器,视图解析器
依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
二、first SpringMVC
在使用springmvc后,我们在处理页面和后台交互时很多地方都可以简化了。
1. 先看看需要依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</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</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
用idea一般都不要忘记加入输出配置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2.定义DispatcherServlet
ps:springmvc-servlet.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">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<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>
<!-- / 匹配所有的请求:(不包括.jsp)-->
<!-- /* 匹配所有的请求:(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3.创建Spring MVC配置文件(自定义的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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--添加处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!--添加处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!--
添加视图解析器: DispatcherServlet给他的ModelAndView
1.获取了ModelAndView的数据
2.解析了ModelAndView的视图名字
3.拼接视图名子,找到对应的视图 hello
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/" />
<!--后缀-->
<property name="suffix" value=".jsp" />
</bean>
</beans>
4.创建Controller
在src的java下创建自己的包/com/person/controller,再创建文件FirstController
public class FirstController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv=new ModelAndView();
//封装对象,放在ModelAndView中。Model、
mv.addObject("msg","HelloSpringMVC");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello");// : /WEB-INF/jsp/hello.jsp
return mv;
}
}
这时记得回到springmvc-servlet.xml加上配置
<!--Handler-->
<bean id="/hello" class="com.person.controller.FirstController"/>
此时完整的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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--添加处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!--添加处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!--
添加视图解析器: DispatcherServlet给他的ModelAndView
1.获取了ModelAndView的数据
2.解析了ModelAndView的视图名字
3.拼接视图名子,找到对应的视图 hello
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/" />
<!--后缀-->
<property name="suffix" value=".jsp" />
</bean>
<!--Handler-->
<bean id="/hello" class="com.person.controller.FirstController"/>
</beans>
5.创建View
在“WEB-INF”下创建/jsp/hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
6.部署查看
在部署后自动开启的页面后加/hello即可
三、controller注解
controller类使用注解
使用注解的情况下不需要
<!--Handler-->
<bean id="/hello" class="com.person.controller.FirstController"/>
将controller包的类改为
@Controller
@RequestMapping("/hello")
public class HelloController v{
@RequestMapping("/h1")
public String hello(Model model){
// 封装数据
model.addAttribute("msg","AnnotationTest信息");
return "hello";//会被视图解析器处理
}
}
即可。
对应的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"
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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.person.controller" />
<!--让Spring MVC不处理静态资源-->
<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>
网页访问hello方法
URL为:http://localhost:3306/项目地址/hello/h1
@Controller注解
-
@Controller注解类型用于声明Spring类的实例是一个控制器(在IOC时还学了另外三个注解:@Component,@Service,@Repository)
@Component 组件 @Service service @Controller controller @Repository dao
四、控制器Controller
- 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现
- 控制器负责解析用户的请求并将其转化为一个模型
- 在Spring MVC中的一个控制器类可以包含多个方法
- 在Spring MVC中,对于Controller的配置方式有很多种
Controller的配置方式:第一种方法
不需要配置自动扫描包,不处理映射文件,mvc注解驱动(处理器映射器,处理器适配器):
<context:component-scan base-package="com.person.controller" />
<mvc:default-servlet-handler />
<mvc:annotation-driven />
- 完整代码如下:
web.xml:
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
spring-servlet.xml——springmvc配置文件
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean name="/t1" class="com.person.controller.ControllerTest1"/>
</beans>
Controller类:
//只要实现类Controller接口的类,说明这就是一个控制器
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;
}
}
View:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
部署后网页搜索:前缀/t1(见spring-servlet.xml的bean)
Controller的配置方式:第二种方法
在类上使用@Controller注解
@Controller//代表这个类会被Spring接管,被这个注解的类中的所有方法,如果返回值为String,并且有具体的类可以跳转,那么就会被视图解析器解析
public class ControllerTest2 {
@RequestMapping("/t2")
public String test1(Model model){
model.addAttribute("msg","ControllerTest2");
return "test";//这里表示会去找/WEB-INF/jsp/test.jsp文件
}
@RequestMapping("/t3")
public String test2(Model model){
model.addAttribute("msg","test3");
return "test";//这里表示会去找/WEB-INF/jsp/test.jsp文件
}
}
然后只需在spring-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"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.person.controller" />
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
部署后网页搜索:
http://localhost:3306/项目地址/t2
http://localhost:3306/项目地址/t3
可见多个请求可以指向同一个视图,但是页面输出的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱耦合关系
第二种方法扩展
使用第二种方法可见ControllerTest2中可以写多个方法
并且也可以对url进一步操作
@Controller
@RequestMapping("/c3")
public class ControllerTest3 {
@RequestMapping("/t1")
public String test3(Model model){
model.addAttribute("msg","测试三");
return "test";
}
}
此时重新部署后在网页搜索:
http://localhost:3306/项目地址/c3/t1
五、RestFul风格
概念:
Restful就是一个资源定位及资源操作的风格,不是标准/协议,只是一种风格
例如:
原来URL:http://localhost:3306?item=xxx&id=sss
使用该风格后:http://localhost:3306/item/xxx/id/sss
传统方式操作资源:通过不同的参数来实现不同的效果!方法单一,post和get
RESTFul操作资源:可以通过不同的请求方式来实现不同的效果!(请求地址一样,但是功能可以不同)(GET POST PUT DELETE)
对比测试
1.之前
@Controller
public class RestFulController {
@RequestMapping("/add")
public String test(int a,int b,Model model){
model.addAttribute("msg","结果为"+(a+b));
return "test";
}
}
网页输入:http://localhost:9527/add?a=1&b=2
输出结果为3
2.现在RestFul
在Spring中使用@PathVariable注解,让方法参数的值对应绑定到一个URL模板变量上
@Controller
public class RestFulController {
@RequestMapping("/add/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
model.addAttribute("msg","结果为"+(a+b));
return "test";
}
}
URL:http://localhost:9527/add/1/2
输出结果为3
RestFul的请求方式method
RestFul风格下如果前端网页表单提交方式和后端不符,会出异常
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
ps:这里value可以换成path(不能用name,name是mapping的名字,value和path互为别名)
也可以用请求方式对应的标签:
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
@DeleteMapping("/add/{a}/{b}")
@GetMapping("/add/{a}/{b}")
@Controller
public class RestFulController {
// @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
// @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
// @GetMapping("/add/{a}/{b}")
// @DeleteMapping("/add/{a}/{b}")
@PostMapping("/add/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
model.addAttribute("msg","POST方法请求结果为"+(a+b));
return "test";
}
@GetMapping("/add/{a}/{b}")
public String test2(@PathVariable int a,@PathVariable int b, Model model){
model.addAttribute("msg","GET方法返回结果为"+(a+b));
return "test";
}
}
六、跳转
设置ModelAndView对象后
页面:{视图解析器前缀} + viewName + {视图解析器后缀}
ServletAPI
通过设置ServletAPI,我们就不需要视图解析器了
- 1.通过HttpServletResponse进行输出
- 2.通过HttpServletResponse实现重定向
- 3.通过HttpServletResponse实现转发
Servlet重定向
用上面的‘四、控制器Controller’第二种方式模板
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
System.out.println(session.getId());
return "test";
}
}
可以用HttpServlet中的跳转重定向(需要视图解析器)
用SpringMVC来实现转发和重定向-无需视图解析器
在spring-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"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.person.controller" />
</beans>
测试实例:
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
System.out.println(session.getId());
return "test";
}
@RequestMapping("/m2/t1")
public String test1(){
//跳转
return "/jumpTest.jsp";
}
@RequestMapping("/m2/t2")
public String test2(){
//跳转
return "forward:/WEB-INF/jsp/test.jsp";
}
@RequestMapping("/m2/t3")
public String test3(){
//重定向
return "redirect:/WEB-INF/jsp/test.jsp";
}
}
七、处理提交数据
1.提交的域名称和处理方法的参数名一致
提交数据:http://localhost:9527/t1?name=lisi
public class ModelTest1 {
@RequestMapping("/t1")
public String test1(String name, Model model){
//1.接受前端参数
System.out.println("接收到前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
return "test";
}
}
后台输出:lisi
2.提交的域名称和处理方法的参数名不一致
使用@RequestParam(“username”)注解标注方法参数
提交数据:http://localhost:9527/t2?username=lisi
@Controller
public class ModelTest1 {
@RequestMapping("/t2")
public String test2(@RequestParam("username") String name, Model model){
//1.接受前端参数
System.out.println("接收到前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
return "test";
}
}
后台输出:lisi
3.提交的是一个对象
提交数据:http://localhost:9527/t3?id=1&name=lisi&age=18
@Controller
public class ModelTest1 {
//前端接收的是一个对象
/*
1.接受前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
2.假设传递的是一个对象User,匹配User对象中的字段名,如果名字一致则OK,否则,匹配不到
*/
@RequestMapping("/t3")
public String test3(User user){
System.out.println(user);
return "test";
}
}
后台输出:User(id=1, name=lisi, age=18)
如果前端提交的参数名和类的属性名不匹配
前端:http://localhost:9527/t3?id=1&username=lisi&age=18
后端输出:User(id=1, name=null, age=18)
八、数据显示到前端
第一种:通过ModelAndView
一开始的方法
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","SecondHello");
mv.setViewName("testJsp");
return mv;
}
}
第二种:通过ModelMap
继承了LinkedMap,Model是ModelMap的精简版,主要使用Model,ModelMap目前使用和Model无区别
第三种:通过Model
上面的第二种方式的例子:
@Controller
public class ModelTest1 {
@RequestMapping("/t2")
public String test2(@RequestParam("username") String name, Model model){
//1.接受前端参数
System.out.println("接收到前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
return "test";
}
}
三者对比
Model 只有寥寥几个方法适合用于储存数据,简化了新手对于Model对象的操作和理解
ModelMap 继承了LinkedMap,除了实现自身的一些方法,同样的继承LinkedMap的方法和特性
ModelAndView可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转
九、乱码
实例
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">
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-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"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.person.controller" />
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
controller:
@Controller
public class ModelTest1 {
@PostMapping("/t1")
public String test1(String name, Model model){
System.out.println(name);
model.addAttribute("msg",name);
return "test";
}
}
前端页面(和index.jsp同级)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/t1" method="post">
<input type="text" name="name">
<input type="submit" value="提交按钮">
</form>
</body>
</html>
前端页面test.jsp(在/WEB-INF/jsp/下)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${
msg}
</body>
</html>
测试
测试说明
在jsp页面表单输入”无敌“
提交给Controller后
控制台输出:???
回显到网页页面”æ— æ•Œ“
可见在java获得页面提交数据时就已经乱码了
解决方法1-自己写个过滤器
在com.person.filter包下创建EncodingFilter类
public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
chain.doFilter(request,response);
}
public void destroy() {
}
}
再去web.xml配置过滤器
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.person.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
再次测试无误
注意:<url-pattern>/*</url-pattern>,过滤所有页面包括jsp要用/*而不是/
解决方法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>
万能解决方法
解决网页传送数据给java乱码的万能解决方法:
因为网页传送数据是ISO-8859-1,把这个转化成中文就行
byte[] bytes=name.getBytes("ISO-8859-1");
name=new String(bytes,"UTF-8");
十、JSON
- 现在是前后端分离时代
后端部署后端,提供接口,提供数据:
前端独立部署,负责渲染后端的数据:
前后端传送数据最常用JSON数据格式
Java生成json对象
Maven导入JSON处理器jar包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
用jar包处理
public class A{
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@ResponseBody//标注该注解就不会走视图解析器,会直接返回一个字符串
public String json1(){
//jackson. ObjectMapper
ObjectMapper mapper=new ObjectMapper();
//创建对象
User user=new User(1,"王二",18);
String str=null;
try {
str=mapper.writeValueAsString(user);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return str;
}
}
@RestController用在类上,标注该注解就不会走视图解析器,会直接返回一个字符串,替代@Controlle
@ResponseBody用在方法上,标注该注解就不会走视图解析器,会直接返回一个字符串,配合@Controlle使用
produces用来处理乱码问题
乱码处理
可以通过spring配置统一指定编码
在springmvc中加上一段消息StringHttpMessageConverter转换配置
<!--解决乱码问题-->
<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>
FastJson.jar
fastjson.jar是阿里开发的一款用于Java开发的包,可以方便的实现json对象与JavaBean对象的转化,
实现JavaBean对象和json字符串的转化,实现json对象和json字符串的转化。
fastjson三个主要的类:
- JSONObject代表json对象
- JSONArray代表json对象数组
- JSON代表JSONObject和JSONArray的转化
导包
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
十一、springmvc拦截器
过滤器与拦截器的区别:拦截器是AOP思想的具体应用
过滤器:
- servlet规范中的一部分,任何java web工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
拦截器:
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
拦截器简单介绍
我们可以实现HandlerInterceptor接口来写自己的拦截器
public class MyInterceptor implements HandlerInterceptor {
//return true;执行下一个拦截器,放行
//return false;不执行下一个拦截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("=======处理前======");
return true;
}
//后面两个类似于日志
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//System.out.println("========处理后======");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//System.out.println("======清理======");
}
}
然后在applicationContext.xml中配置拦截器即可
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--包括这个请求下面的所有的请求-->
<mvc:mapping path="/**"/>
<bean class="com.person.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
十二、文件上传和下载
核心过程简介
1.配置jar
<dependencies>
<!--文件上传-->
<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>
</dependencies>
2.前端html
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
3.applicationContext.xml配置
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--请求编码格式,必须和jsp的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1-->
<property name="defaultEncoding" value="utf-8"/>
<!--上传文件大小上限,单位为字节-->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
4写fileController.java
完整实例
pom.xml导入依赖
<dependencies>
<!--文件上传-->
<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>
</dependencies>
web.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>
applicationContext.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: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
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.person.controller"/>
<mvc:default-servlet-handler /><!--静态资源过滤,类似jQuery之类的静态资源导入必须要用-->
<mvc:annotation-driven/>
<!--解决JSON乱码问题配置 -->
<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>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--请求编码格式,必须和jsp的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1-->
<property name="defaultEncoding" value="utf-8"/>
<!--上传文件大小上限,单位为字节-->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
</beans>
在java.com.person.controller包下创建FileController类
@RestController
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";
}
/*
采用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";
}
@RequestMapping("/download")
public String downloads(HttpServletResponse response,HttpServletRequest request) throws IOException {
//要下载的图片地址
String path=request.getServletContext().getRealPath("/upload");
String fileName="1.png";
//1.设置response 响应头
response.reset();//设置页面不缓存,清空buffer
request.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[] buffer=new byte[1024];
int index=0;
while ((index=input.read(buffer))!=-1){
out.write(buffer,0,index);
out.flush();
}
out.close();
input.close();
return null;
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
</body>
</html>
这里提一下测试
此代码部署后,首页上传文件可以在out输出中看见
下载也必须是out/upload/1.png文件才可以使用/download下载
创建好了项目,网页打不开先看这!!
idea需要手动创建lib包(依赖)
应用就行,需要注意的是:
之后每次加入新的依赖必须重复操作以上步骤,否则依赖不会生效