1》、什么是MVC?

含义:SprinMVC 是一种基于java实现的MVC设计模型的请求驱动类型的轻量级的WEB层框架,属于Springframework的后续产品,已经融合在Springweb flow中。
Spring MVC已经成为目前主流的MVC框架之一,并随着任凭 3.0的发布,已经全面超越身体乳提升
struts2,成为最优秀的MVC框架,他通过一套注解,让一个简单的java类成为处理请求的控制器,而无需实现任何接口,同事还支持RESTful编程风格的请求。

1.MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
2.是将业务逻辑、数据、显示分离的方法来组织代码。
3.MVC主要作用是降低了视图与业务逻辑间的双向偶合。
4.MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

最典型的MVC就是JSP + servlet + javabean的模式。
SpringMvc笔记: - 图1

2》、 使用SpringMvc:

image.png
image.png

2.1》HandlerMapping与处理映射器:

1)SpringMvc的两大核心组件是ViewResolcer(用来处理逻辑视图名解析成实际的视图对象)和HandlerMapping(负责将请求映射到控制器的处理方法,就是当DispatcherServlet拦截到HTTP请求后,HandlerMapping负责告诉DispatcherServlet调用哪一个控制器那个方法来处理请求)。
2)目前HandlerMapping流行的实现类是RequestMappingHandlerMapping,他可以将HTTP请求映射到控制类中@RequestMapping修饰的方法。

2.1 导入依赖:

  1. <!--springMvc依赖-->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-webmvc</artifactId>
  5. <version>5.2.18.RELEASE</version>
  6. </dependency>

2.2 配置控制器(web.xml配置文件中):

  1. <!-- 加载Spring.xml配置文件-->
  2. <context-param>
  3. <param-name>contextConfigLocation </param-name>
  4. <param-value>classpath:applicationContext.xml </param-value>
  5. </context-param>
  6. <!--监听器-->
  7. <listener>
  8. <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class>
  9. </listener>
  10. <!--配置SpringMvc的前端控制器-->
  11. <servlet>
  12. <servlet-name>DispatcherServlet</servlet-name>
  13. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  14. <!--在启动的时候呢加载springmvc配置文件-->
  15. <init-param>
  16. <param-name>contextConfigLocation</param-name>
  17. <param-value>classpath:spring-mvc.xml</param-value>
  18. </init-param>
  19. <load-on-startup>1</load-on-startup>
  20. </servlet>
  21. <servlet-mapping>
  22. <servlet-name>DispatcherServlet</servlet-name>
  23. <url-pattern>/</url-pattern>
  24. </servlet-mapping>

2.3 编写controller类:

  1. package com.xxgc.spring.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. //把web类交个spring托管
  5. @Controller
  6. public class LoginController {
  7. //请求接口地址
  8. @RequestMapping("/login")
  9. public String userLogin(){
  10. return "";
  11. }
  12. }

2.4 配置spring-mvc.xml配置文件:

image.png

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. ">
  8. <!--配置Spring的controller主键扫描-->
  9. <context:component-scan base-package="com.xxgc.spring.controller"/>
  10. <!--开启注解扫描-->
  11. <mvc:annotation-driven />
  12. <!--如果是静态之源就交给web应用服务器处理,否则DispatcherServlet处理-->
  13. <mvc:default-servlet-handler/>
  14. <!--配置视图解析器(前缀和后缀)-->
  15. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  16. <!--视图解析器的前缀-->
  17. <property name="prefix" value="/WEB-INF/jsp/"/>
  18. <!--视图解析器的后缀-->
  19. <property name="suffix" value=".jsp"/>
  20. </bean>
  21. <!--开放静态资源访问-->
  22. <mvc:resources mapping="/js/**" location="/js/"/>
  23. </beans>

2.5 返回数据+页面的使用:

在spring-mvc.xml配置视图解析器:

  1. <!--配置视图解析器(前缀和后缀)-->
  2. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  3. <!--视图解析器的前缀-->
  4. <property name="prefix" value="/WEB-INF/jsp/"/>
  5. <!--视图解析器的后缀-->
  6. <property name="suffix" value=".jsp"/>
  7. </bean>

@RequestMapping注解的使用:

  1. /**
  2. * value="/login":代表请求路径
  3. * method = RequestMethod.POST :代表必须是POST请求
  4. * params = {"username","password"}:请求参数必须含有它俩
  5. * @param request
  6. * @return
  7. */
  8. @RequestMapping(value = "/login3",method = RequestMethod.POST,params = {"username","password"})
  9. public String userLogin3(HttpServletRequest request){
  10. System.out.println("login3...");
  11. HttpSession session = request.getSession();
  12. session.setAttribute("msg","噢噢噢噢哦哦哦");
  13. return "login";
  14. }

@ResponseBody的使用:

ps:如果返回JSON格式的数据,则要导入以下依赖:

  1. <!--springmvc返回json数据格式 数据绑定-->
  2. <dependency>
  3. <groupId>com.fasterxml.jackson.core</groupId>
  4. <artifactId>jackson-databind</artifactId>
  5. <version>2.12.3</version>
  6. </dependency>-
  1. /**
  2. * 获取数据
  3. * @return
  4. */
  5. @RequestMapping(value = "/login4")
  6. @ResponseBody
  7. public String userLogin4(@RequestParam("username")String username){
  8. System.out.println("login4...获取数据");
  9. return "{'username':'zhangsan','pass':'123456'}";
  10. }

ps:用了这个注解会跳过视图解析器,直接返回数据给页面
image.png

  1. <!--开启注解扫描-->
  2. <mvc:annotation-driven />

1、在SpringMvc的各个组件中,处理器、映射器、处理适配器 称为SpringMvc的三大组件。

2、使用了以上代码可以自动加载 RequestMappingHandlerMapping(处理映射器),和RequestMappingHandlerAdapler(处理适配器),来代替注解处理器和适配器的配置。
3、使用它,默认底层会集成jackson进行对象集合的JSON字符串转换。

2.6 获取请求数据参数:

服务器需要获取的参数有,有事还需要进行数据封装,SpringMvc可以接收如下类型参数:

2.6.1 基本类型参数:

Controller中业务方法的参数名称要求与请求参数name一致,参数会自动匹配。

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live1")
  5. @ResponseBody
  6. public void live1(Integer liveId,String liveName){
  7. System.out.println("进来了");
  8. System.out.println("直播间id = " + liveId);
  9. System.out.println("直播间name = " + liveName);
  10. }
  11. }

http://localhost:8080/springMvc/live1?liveId=1&liveName=LOL

ps:写了参数不一定不需要传递,可以传某个值,也可以完全不传。但要注意,不传值会给一个null,如果是int类型会报错,应该改为Integer。

2.6.2 POJO类型参数:

Controller中的业务方法的POJO的属性名一致,参数会自动映射匹配。
POJO:

  1. package com.xxgc.spring.pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import org.springframework.stereotype.Component;
  6. @Data
  7. @AllArgsConstructor
  8. @NoArgsConstructor
  9. @Component
  10. public class User {
  11. private long uId;
  12. private String userName;
  13. private String password;
  14. }

controller:

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live2")
  5. @ResponseBody
  6. public User live2(User user){
  7. System.out.println("进来了");
  8. System.out.println("user = " + user);
  9. return user;
  10. }
  11. }

http://localhost:8080/springMvc/live/live2?uId=1&userName=lisi
ps:在对象中,不需要传递所有参数,也可以不传,不传递会使用默认值null或0。

2.6.3 数组类行参数:

Controller中业务方法数组名称与请求参数name一致,参数会自动映射匹配。

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live3")
  5. @ResponseBody
  6. public String[] live3(String[] names){
  7. System.out.println(Arrays.asList(names));
  8. return names;
  9. }
  10. }

http://localhost:8080/springMvc/live/live3?names=zhangsan&names=lisi
ps:传递参数时,必须保证key的名称和方法参数名一致,否则拿不到。属性类型必须一致。

2.6.4 集合类型参数:

获取集合数据时,要将集合参数包装到一个POJO中才可以:
创建一个POJO:

  1. @Data
  2. public class UserList {
  3. private List<User> users;
  4. }

编写页面:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <form action="${pageContext.request.contextPath}/live/live4" method="post">
  8. <input type="text" name="users[0].uId"/>
  9. <input type="text" name="users[0].userName"/>
  10. <input type="text" name="users[0].password"/>
  11. <input type="text" name="users[1].uId"/>
  12. <input type="text" name="users[1].userName"/>
  13. <input type="text" name="users[1].password"/>
  14. <button type="submit">登录</button>
  15. </form>
  16. </body>
  17. </html>

编写Controller类:

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live4")
  5. @ResponseBody
  6. public void live4(UserList userList){
  7. System.out.println("live4进来了。。。。。");
  8. for (User user : userList.getUsers()) {
  9. System.out.println("user = " + user);
  10. }
  11. }
  12. }

2.6.5 集合参数二:

当使用ajax提交时,可以指定contentType为json格式,那么在方法参数使用位置使用@RequestBody可以直接接受集合数据而无需使用POJO进行包装。
Controller类:

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live5")
  5. @ResponseBody
  6. public void live5(@RequestBody List<User> users){
  7. for (User user : users) {
  8. System.out.println("user = " + user);
  9. }
  10. }
  11. }

apipost工具body属性中参数:

  1. [
  2. {
  3. "userId": "1",
  4. "userName": "zhangsan",
  5. "password": "123456",
  6. },
  7. {
  8. "userId": "2",
  9. "userName": "lisi",
  10. "password": "555"
  11. }
  12. ]

image.png

ps:调试工具
把body调成application/json
ajax:
Context-Type=json

3》静态资源:

3.1 方式一 、如果使用静态资源,则会被SpringMvc拦截,(需要在Spring-mvc.xml中配置以下信息:)

  1. <!--开放静态资源访问-->
  2. <mvc:resources mapping="/js/**" location="/js/"/>
  3. <mvc:resources mapping="/images/**" location="/images/"/>

访问路径案例:http://localhost:8080/springMvc/js/jquery/jquery.js

3.2 方式二、 (配置全部静态资源):

  1. <!--如果是静态之源就交给web应用服务器处理,否则DispatcherServlet处理-->
  2. <mvc:default-servlet-handler/>

注意:加上之后,所有的静态资源都会被用户看到,如果不想被用户看到,就放到WEB_INF文件夹下面。

注意:
1.通常情况下我们把不容易发生改变的静态资源放在web文件夹下面的CDN文件夹下。
image.png
2.需要保密的静态资源放在WEB-IN下通过@RequestMapping获取。
image.png

4》中文乱码问题:

方案一:

在web.xml中配置:

  1. <!--配置SpringMvc全局过滤器 解决乱码问题-->
  2. <filter>
  3. <filter-name>CharacterEncodingFilter</filter-name>
  4. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  5. <init-param>
  6. <param-name>encoding</param-name>
  7. <param-value>UTF-8</param-value>
  8. </init-param>
  9. <init-param>
  10. <param-name>forceEncoding</param-name>
  11. <param-value>true</param-value>
  12. </init-param>
  13. </filter>
  14. <filter-mapping>
  15. <filter-name>CharacterEncodingFilter</filter-name>
  16. <url-pattern>/*</url-pattern>
  17. </filter-mapping>

方案二:

spring-mvc中配置:

  1. <mvc:annotation-driven>
  2. <mvc:message-converters register-defaults="true">
  3. <bean class="org.springframework.http.converter.StringHttpMessageConverter">
  4. <property name="defaultCharset" value="UTF-8"/>
  5. <property name="writeAcceptCharset" value="false"/>
  6. </bean>
  7. </mvc:message-converters>
  8. </mvc:annotation-driven>

5》请求方法参数名和字段名不一致怎么办?

@RequestParam注解的使用:

使用场景:当某些字段需要隐藏其真实含义需要使用注解@RequestParam
@RequestParam(value = “liveId”,required = true,defaultValue = “1”):
value = “liveId”:代表参数名

  1. @Controller
  2. @RequestMapping("/live")
  3. public class LiveController {
  4. @RequestMapping("/live1")
  5. @ResponseBody
  6. public void live1(@RequestParam(value = "liveId",required = true,defaultValue = "1") Integer liveId, @RequestParam("liveName") String liveName){
  7. System.out.println("进来了");
  8. System.out.println("直播间id = " + liveId);
  9. System.out.println("直播间name = " + liveName);
  10. }
  11. }

6》Restful风格获取请求数据:

restful+普通参数的使用:

  1. @Controller
  2. public class VideoController {
  3. @RequestMapping("/video/{videoUrl}")
  4. public String playViedo(@PathVariable("videoUrl")String videoUrl,
  5. @RequestParam("money")String money){
  6. System.out.println("videoUrl = " + videoUrl);
  7. System.out.println("money = " + money);
  8. return "";
  9. }
  10. }

http://localhost:8080/springMvc/video/HGHDL?money=1245

7》自定义类型转换器:

含义:

SpringMvc默认提供了一些常用的类型转换器,例如客户端提供的字符串转换为int、long进行参数设置。但是不是又有类型都提供了转换器,没有提供的就要自定义转换器,如:时间Data类型。

实现步骤:

1.定义一个转换器实现Converter接口

  1. package com.xxgc.spring.converter;
  2. import org.springframework.core.convert.converter.Converter;
  3. import java.util.Date;
  4. public class DateConverter implements Converter<String,Date> {
  5. @Override
  6. public Date convert(String s) {
  7. if(s==null){
  8. throw new RuntimeException("时间为空");
  9. }
  10. long longs = Long.parseLong(s);
  11. Date date = new Date();
  12. date.setTime(longs);
  13. System.out.println("date.getTime() = " + date.getTime());
  14. return date;
  15. }
  16. }

2.在配置文件中声明转换器

  1. <!--声明转换器-->
  2. <bean id="DateConverter" class="org.springframework.context.support.ConversionServiceFactoryBean">
  3. <property name="converters">
  4. <set>
  5. <bean class="com.xxgc.spring.converter.DateConverter"></bean>
  6. </set>
  7. </property>
  8. </bean>

3.在中引用

  1. <mvc:annotation-driven conversion-service="DateConverter">
  2. </mvc:annotation-driven>

4.Controller类中的方法:

注意:定义类型转换器contorller方法参数必须是Date类型。

  1. @Controller
  2. public class VideoController {
  3. @RequestMapping("/vide/getVideoUrl")
  4. @ResponseBody
  5. public String routeTime(Date time){
  6. System.out.println("time = " + time);
  7. return "时间差="+time;
  8. }
  9. }

8》SpringMvc拦截器:

8.1 自定义拦截器类实现接口HandlerInterceptor:

preHandle——在向模型注入数据之前的操作
postHandle——模型被注入数据之后,返回视图之前的操作
afterCompletion——返回视图之后的操作

  1. public class loginIntercepter implements HandlerInterceptor {
  2. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  3. // 判断用户是否登录即判断session中有没有user对象
  4. HttpSession session = request.getSession();
  5. Object user = session.getAttribute("user");
  6. if (user==null){
  7. response.sendRedirect(request.getContextPath()+"/login.jsp");
  8. return false;
  9. }
  10. return true;
  11. }
  12. }

8.2 在spring-mvc.xml配置文件中注册拦截器:

  1. <!-- 配置登录拦截器-->
  2. <mvc:interceptors>
  3. <mvc:interceptor>
  4. <!-- 拦截哪些-->
  5. <mvc:mapping path="/**"/>
  6. <!-- 哪些不拦截-->
  7. <mvc:exclude-mapping path="/css/**"/>
  8. <mvc:exclude-mapping path="/plugins/**"/>
  9. <mvc:exclude-mapping path="/img/**"/>
  10. <!--配置哪些资源排除拦截操作-->
  11. <mvc:exclude-mapping path="/user/login"/>
  12. <!-- 自定义拦截器位置-->
  13. <bean class="com.wzy.intercepter.loginIntercepter"/>
  14. </mvc:interceptor>
  15. </mvc:interceptors>

ps:返回值为true表示方行 false不放行进行拦截。

9》数据的加密与解密(AES):

9.1 在html静态文件中引入对应的js:

  1. <script src="/springMvc/CDN/js/jquery/jquery.js"></script>
  2. <%--加密使用的包--%>
  3. <script src="https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.min.js"></script>
  4. <script src="https://cdn.bootcdn.net/ajax/libs/aes-js/3.1.2/index.min.js"></script>

9.2 书写加减密的js:

  1. // AES 加密,AES-128, AES-192, AES-256
  2. // AES-128: key和iv都是16个字节,16*8=128bit
  3. // AES-192: key和iv都是24个字节,24*8=128bit
  4. // AES-256: key和iv都是32个字节,32*8=128bit
  5. // iv 似乎一般都是纯数字
  6. // 例如:AES_encrypt_CBC('需要加密的内容', '1234567890123456', '1234567890654321');
  7. function AES_CBC_encrypt(message, key, iv) {
  8. // utf8字符串—>WordArray对象,WordArray是一个保存32位整数的数组,相当于转成了二进制
  9. let keyHex = CryptoJS.enc.Utf8.parse(key); //
  10. let ivHex = CryptoJS.enc.Utf8.parse(iv);
  11. let messageHex = CryptoJS.enc.Utf8.parse(message);
  12. let encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
  13. iv: ivHex,
  14. mode: CryptoJS.mode.CBC,
  15. padding: CryptoJS.pad.Pkcs7
  16. });
  17. return encrypted.toString();// base64结果
  18. //return encrypted.ciphertext.toString(); // 二进制结果
  19. }
  20. // AES CBC模式解密
  21. function AES_CBC_decrypt(messageBase64, key, iv) {
  22. // 如果加密后没有转成base64,那么先要转成base64再传入
  23. //let encryptedHexStr = CryptoJS.enc.Hex.parse(word); // 从二进制文本转成二进制
  24. //messageBase64 = CryptoJS.enc.Base64.stringify(encryptedHexStr); // 转成base64
  25. let keyHex = CryptoJS.enc.Utf8.parse(key);
  26. let ivHex = CryptoJS.enc.Utf8.parse(iv);
  27. let decrypt = CryptoJS.AES.decrypt(messageBase64, keyHex, {
  28. iv: ivHex,
  29. mode: CryptoJS.mode.CBC,
  30. padding: CryptoJS.pad.Pkcs7
  31. });
  32. let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
  33. return decryptedStr.toString();
  34. }
  35. // AES ECB模式加密,没有iv
  36. function AES_ECB_encrypt(message, key) {
  37. // utf8字符串—>WordArray对象,WordArray是一个保存32位整数的数组,相当于转成了二进制
  38. let keyHex = CryptoJS.enc.Utf8.parse(key); //
  39. let messageHex = CryptoJS.enc.Utf8.parse(message);
  40. let encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
  41. mode: CryptoJS.mode.ECB,
  42. padding: CryptoJS.pad.Pkcs7
  43. });
  44. return encrypted.toString();// base64结果
  45. //return encrypted.ciphertext.toString(); // 二进制结果
  46. }
  47. // AES ECB模式解密
  48. function AES_ECB_decrypt(messageBase64, key) {
  49. // 如果加密后没有转成base64,那么先要转成base64再传入
  50. //let encryptedHexStr = CryptoJS.enc.Hex.parse(word); // 从二进制文本转成二进制
  51. //messageBase64 = CryptoJS.enc.Base64.stringify(encryptedHexStr); // 转成base64
  52. let keyHex = CryptoJS.enc.Utf8.parse(key);
  53. let decrypt = CryptoJS.AES.decrypt(messageBase64, keyHex, {
  54. mode: CryptoJS.mode.ECB,
  55. padding: CryptoJS.pad.Pkcs7
  56. });
  57. let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
  58. return decryptedStr.toString();
  59. }

9.3 使用案例:

  1. <body>
  2. <form action="/userRegister" method="post" onsubmit="">
  3. 昵称:<input type="text" placeholder="请输入昵称" name="nick"/>
  4. 密码:<input type="password" name="pass"/>
  5. 手机号码:<input type="text" placeholder="请输入手机号码" name="phone"/>
  6. 验证码: <input type="text" name="smsvc"/>
  7. <input id="submit" type="button" value="提交">
  8. </form>
  9. <script>
  10. let key = "${key}";
  11. // AES ECB模式加密,没有iv
  12. function AES_ECB_encrypt(message, key) {
  13. // utf8字符串—>WordArray对象,WordArray是一个保存32位整数的数组,相当于转成了二进制
  14. let keyHex = CryptoJS.enc.Utf8.parse(key); //
  15. let messageHex = CryptoJS.enc.Utf8.parse(message);
  16. let encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
  17. mode: CryptoJS.mode.ECB,
  18. padding: CryptoJS.pad.Pkcs7
  19. });
  20. return encrypted.toString();// base64结果
  21. //return encrypted.ciphertext.toString(); // 二进制结果
  22. }
  23. /*ES6代码规范*/
  24. $(function(){
  25. $("#submit").on("click",function(){
  26. let nick = $("input[name='nick']").val();
  27. //对数据进行加密
  28. let pass = AES_ECB_encrypt($("input[name='pass']").val(),key);
  29. let phone = AES_ECB_encrypt($("input[name='phone']").val(),key);
  30. let smsvc = $("input[name='smsvc']").val();
  31. $.ajax({
  32. type:"post",
  33. url:"/springMvc/userRegister",
  34. contextType:"application/json",
  35. dataType:"json",
  36. data:{
  37. nick:nick,
  38. pass:pass,
  39. phone:phone,
  40. smsvc:smsvc
  41. },
  42. success:function(data){
  43. //成功回调
  44. console.log(data)
  45. },
  46. error:function(){
  47. //失败是回调
  48. }
  49. });
  50. })
  51. })
  52. </script>
  53. </body>

9.4 java后台的加减密工具类:

  1. /**
  2. * @author ybakiame
  3. * @className AESCrypt
  4. * @description AES加解密工具,AES-128: key和iv都是16个字节,16*8=128bit,java似乎只支持AES-128
  5. * @createTime 2021/11/15 21:19
  6. */
  7. public class AESCrypt {
  8. /**
  9. * AES CBC 加密
  10. * @param message 需要加密的字符串
  11. * @param key 密匙
  12. * @param iv IV,需要和key长度相同
  13. * @return 返回加密后密文,编码为base64
  14. */
  15. public static String encryptCBC(String message, String key, String iv) {
  16. final String cipherMode = "AES/CBC/PKCS5Padding";
  17. final String charsetName = "UTF-8";
  18. try {
  19. byte[] content = new byte[0];
  20. content = message.getBytes(charsetName);
  21. //
  22. byte[] keyByte = key.getBytes(charsetName);
  23. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  24. //
  25. byte[] ivByte = iv.getBytes(charsetName);
  26. IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
  27. Cipher cipher = Cipher.getInstance(cipherMode);
  28. cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
  29. byte[] data = cipher.doFinal(content);
  30. final Base64.Encoder encoder = Base64.getEncoder();
  31. final String result = encoder.encodeToString(data);
  32. return result;
  33. } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }
  38. /**
  39. * AES CBC 解密
  40. * @param messageBase64 密文,base64编码
  41. * @param key 密匙,和加密时相同
  42. * @param iv IV,需要和key长度相同
  43. * @return 解密后数据
  44. */
  45. public static String decryptCBC(String messageBase64, String key, String iv) {
  46. final String cipherMode = "AES/CBC/PKCS5Padding";
  47. final String charsetName = "UTF-8";
  48. try {
  49. final Base64.Decoder decoder = Base64.getDecoder();
  50. byte[] messageByte = decoder.decode(messageBase64);
  51. //
  52. byte[] keyByte = key.getBytes(charsetName);
  53. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  54. //
  55. byte[] ivByte = iv.getBytes(charsetName);
  56. IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
  57. Cipher cipher = Cipher.getInstance(cipherMode);
  58. cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
  59. byte[] content = cipher.doFinal(messageByte);
  60. String result = new String(content, charsetName);
  61. return result;
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. }
  65. return null;
  66. }
  67. /**
  68. * AES ECB 加密
  69. * @param message 需要加密的字符串
  70. * @param key 密匙
  71. * @return 返回加密后密文,编码为base64
  72. */
  73. public static String encryptECB(String message, String key) {
  74. final String cipherMode = "AES/ECB/PKCS5Padding";
  75. final String charsetName = "UTF-8";
  76. try {
  77. byte[] content = new byte[0];
  78. content = message.getBytes(charsetName);
  79. //
  80. byte[] keyByte = key.getBytes(charsetName);
  81. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  82. Cipher cipher = Cipher.getInstance(cipherMode);
  83. cipher.init(Cipher.ENCRYPT_MODE, keySpec);
  84. byte[] data = cipher.doFinal(content);
  85. final Base64.Encoder encoder = Base64.getEncoder();
  86. final String result = encoder.encodeToString(data);
  87. return result;
  88. } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
  89. e.printStackTrace();
  90. }
  91. return null;
  92. }
  93. /**
  94. * AES ECB 解密
  95. * @param messageBase64 密文,base64编码
  96. * @param key 密匙,和加密时相同
  97. * @return 解密后数据
  98. */
  99. public static String decryptECB(String messageBase64, String key) {
  100. final String cipherMode = "AES/ECB/PKCS5Padding";
  101. final String charsetName = "UTF-8";
  102. try {
  103. final Base64.Decoder decoder = Base64.getDecoder();
  104. byte[] messageByte = decoder.decode(messageBase64);
  105. //
  106. byte[] keyByte = key.getBytes(charsetName);
  107. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  108. Cipher cipher = Cipher.getInstance(cipherMode);
  109. cipher.init(Cipher.DECRYPT_MODE, keySpec);
  110. byte[] content = cipher.doFinal(messageByte);
  111. String result = new String(content, charsetName);
  112. return result;
  113. } catch (Exception e) {
  114. e.printStackTrace();
  115. }
  116. return null;
  117. }
  118. public static void main(String[] args) {
  119. String content = "测试8";
  120. String encrypt = AESCrypt.encryptECB(content,"abcdefgabcdefg12");
  121. String decrypt = AESCrypt.decryptECB(encrypt, "abcdefgabcdefg12");
  122. System.out.println(content);
  123. System.out.println(encrypt);
  124. System.out.println(decrypt);
  125. }
  126. }

9.5 后台的使用案例:

  1. /**
  2. * 注册方法
  3. * @return Info
  4. * "version v1.0
  5. * @Date 2021-11-16
  6. *
  7. */
  8. @RequestMapping("/userRegister")
  9. @ResponseBody
  10. public Info userRegister(UserRegisterInfo userRegisterInfo) throws Exception {
  11. userRegisterInfo.setPhone(DESUtil.decryptECB(userRegisterInfo.getPhone(),DESUtil.KEY));
  12. userRegisterInfo.setPass(DESUtil.decryptECB(userRegisterInfo.getPass(),DESUtil.KEY));
  13. return new Info(200,"注册成功","注册成功",userRegisterInfo);
  14. }

10》 获取Servlet相关API:

SpringMvc支持使用原始的ServletAPI对象作为控制器方法的参数进行注入,

10.1 HttpServletRequest:

10.2 HttpServletResponse:

10.3 HttpSession:

  1. /**
  2. * 获取原生ServletAPI
  3. *
  4. */
  5. @RequestMapping("/userLogin8")
  6. @ResponseBody
  7. public void userLogin8(HttpServletRequest request, HttpServletResponse response,HttpSession session){
  8. System.out.println("request = " + request);
  9. System.out.println("response = " + response);
  10. System.out.println("session = " + session);
  11. }

11》获取请求头:

11.1 @RequestHeader注解:

使用@RequestHeader可以获取请求信息,相当于web阶段血虚的request.getHeader(name)

11.1 @RequestHeader注解的属性如下:

1 value:请求头的名称:
2 required:是否必须携带请求头:

  1. /**
  2. *@RequestHeader(value="referer",required = true)
  3. * value:请求头名
  4. * required:是否必须带参数
  5. * @return
  6. */
  7. @RequestMapping("/userLogin9")
  8. @ResponseBody
  9. public String userLogin9(@RequestHeader(value="referer",required = true)String headerReferer,
  10. @RequestHeader(value="key",required = true)String key){
  11. if(headerReferer.equals("www.bilibili.com")){
  12. return "请求成功";
  13. }else{
  14. return "失败";
  15. }
  16. }

11.2 @CookieValue注解:

使用CookieValue可以获取指定的Cookie的值。

@CookieValue的属性如下:

1 value:指定cookie的名称
2 required:是否必须携带Cookie信息

  1. @RequestMapping("/userLogin10")
  2. @ResponseBody
  3. public String userLogin10(@CookieValue(value = "JSESSIONID",required = true)String jessionid,
  4. @CookieValue(value = "Idea-a1ffd5d4")String Idea){
  5. return jessionid+"--"+Idea;
  6. }

image.png
哔哩哔哩cookie用SESSDATA保存登录信息。

12》文件上传:

12.1 文件上传的三大条件:

  1. 表单type=”file”
  2. 提交表单方式为post
  3. 多部分表单形式 enctype=”multipart/form-data

    12.2 步骤:

    12.2.1 编写页面:

    ```html
    昵称: 文件:
  1. <a name="wLiEl"></a>
  2. ### 12.2.2 导包:
  3. ```xml
  4. <!--文件上传-->
  5. <dependency>
  6. <groupId>commons-fileupload</groupId>
  7. <artifactId>commons-fileupload</artifactId>
  8. <version>1.4</version>
  9. </dependency>
  10. <dependency>
  11. <groupId>commons-io</groupId>
  12. <artifactId>commons-io</artifactId>
  13. <version>2.6</version>
  14. </dependency>

12.2.3 speing-mvc.xml配置文件上传解析器信息:

  1. <!--配置MUltipartResolver,用于文件上传-->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <!--上传文件大小上限-->
  4. <property name="maxInMemorySize" value="5242800"/>
  5. <!--请求编码格式-->
  6. <property name="defaultEncoding" value="UTF-8"/>
  7. <!--上传单个文件大小-->
  8. <property name="maxUploadSizePerFile" value="5242800"/>
  9. </bean>

12.2.4 编写controller:

  1. @RequestMapping("/fileUpdate1")
  2. public void fileUpdate1(String nick,MultipartFile file) throws IOException {
  3. //方案一 日期文件夹
  4. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  5. String format = simpleDateFormat.format(new Date());
  6. //方案二:UUID
  7. String s = UUID.randomUUID().toString().replaceAll("-", "");
  8. String filenameExtension = StringUtils.getFilenameExtension(file.getOriginalFilename());
  9. //判断文件是否存在 不存在就创建一个
  10. File fileName = new File("D:\\upload\\"+format);
  11. if(!fileName.exists()){
  12. fileName.mkdirs();
  13. }
  14. String str = format+"/"+s+"."+filenameExtension;
  15. strings.add("/upload/"+str);
  16. //上传文件
  17. file.transferTo(new File("D:/upload",format+"/"+s+"."+filenameExtension));
  18. }

12.2.5 MultipartFile的内部方法:

12.2.5.1.判断上传的是不是图片:

  1. //判断上传的是不是图片
  2. boolean image = file.getContentType().toLowerCase().startsWith("image");

12.2.5.2 获取文件上传大小:

  1. //文件上传大小
  2. long size = file.getSize();

12.2.5.3 上传文件:

  1. //上传文件
  2. file.transferTo(new File(""));

注意:如果出现错误检查该项目的依赖是否导入到了项目里面
image.png

12.2.6 文件上传解决文件名冲突:

方案一:使用日期文件夹
方案二:使用UUID创建随机名

  1. @RequestMapping("/fileUpdate1")
  2. public void fileUpdate1(String nick,MultipartFile file) throws IOException {
  3. //方案一 日期文件夹
  4. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  5. String format = simpleDateFormat.format(new Date());
  6. //方案二:UUID
  7. String s = UUID.randomUUID().toString().replaceAll("-", "");
  8. String filenameExtension = StringUtils.getFilenameExtension(file.getOriginalFilename());
  9. //判断文件是否存在 不存在就创建一个
  10. File fileName = new File("D:\\upload\\"+format);
  11. if(!fileName.exists()){
  12. fileName.mkdirs();
  13. }
  14. String str = format+"/"+s+"."+filenameExtension;
  15. strings.add("/upload/"+str);
  16. //上传文件
  17. file.transferTo(new File("D:/upload",format+"/"+s+"."+filenameExtension));
  18. }

12.2.7 多文件上传:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>多文件上传</title>
  5. </head>
  6. <body>
  7. <form action="${pageContext.request.contextPath}/file/uploadFiles" method="post" enctype="multipart/form-data">
  8. 文件1:<input type="file" name="uploadImgs"><br>
  9. 文件2:<input type="file" name="uploadImgs"><br>
  10. 文件3:<input type="file" name="uploadImgs"><br>
  11. <button type="submit">提交</button>
  12. </form>
  13. </body>
  14. </html>
  1. @RequestMapping("/uploadFiles")
  2. @ResponseBody
  3. public List uploadFiles(MultipartFile[] uploadImgs) throws IOException {
  4. List<String> strings = new ArrayList<String>();
  5. for (MultipartFile uploadImg : uploadImgs) {
  6. //方案1 日期文件夹
  7. String yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(new Date());
  8. //方案2 UUID
  9. String uuid = UUID.randomUUID().toString().replace("-", "");
  10. //截取后缀
  11. String suffix = StringUtils.getFilenameExtension(uploadImg.getOriginalFilename());
  12. //文件名
  13. String fileName = yyyyMMdd+"\\"+uuid+"."+suffix;
  14. uploadImg.transferTo(new File("D:\\upload\\"+fileName));
  15. strings.add("\\abb\\"+fileName);
  16. }
  17. return strings;
  18. }

13》SpringMvc拦截器:

13.1 含义:

SpringMvc的拦截器类似于Servlet的过滤器Filter,用于对请求处理器进行预处理和后处理。
将拦截按一定的顺序结成一条链,这条链称为拦截器链(Interceptor Chain),在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是Aop思想的具体体现。

13.2 拦截器和过滤去的区别:

区别 过滤器 拦截器
使用范围 是servlet规范中的一部分,任何JavaWeb下都可以使用 是SpringMvc框架自己的,只有使用了SpringMvc框架的工程才可以使用
拦截范围 在url-pattern中配置/*过后,可以对所有要访问的资源拦截 中配置/**之后,也可以对所有资源进行拦截,通过标签排除不需要拦截的资源。

13.3 拦截器的实现:

13.3.1 自定义类实现HandlerInterceptor接口:

  1. package com.xxgc.spring.interceptor;
  2. import org.springframework.web.servlet.HandlerInterceptor;
  3. import org.springframework.web.servlet.ModelAndView;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. /**
  7. * @program: spring-study
  8. * @Email:2119196781@qq.com
  9. * @description
  10. * @author: 小唐唐
  11. * @create: 2021-11-18 10:41
  12. **/
  13. public class MyInterceptor implements HandlerInterceptor {
  14. //在目标方法之前执行
  15. @Override
  16. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  17. System.out.println("目标之前");
  18. return false;
  19. }
  20. //在目标方法之后执行,视图对象返回之前执行
  21. @Override
  22. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  23. System.out.println("目标之后");
  24. }
  25. //在所有流程执行完之后执行
  26. @Override
  27. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  28. System.out.println("所有都执行后 执行完了");
  29. }
  30. }

1.3.2 在Spring-mvc.xml配置文件中配置拦截器:

  1. <!--配置拦截器-->
  2. <mvc:interceptors>
  3. <mvc:interceptor>
  4. <!--对那些操作进行拦截-->
  5. <mvc:mapping path="/**"/>
  6. <bean class="com.xxgc.spring.interceptor.MyInterceptor"/>
  7. </mvc:interceptor>
  8. </mvc:interceptors>

14》配置Tomcat虚拟路径:

注意:单机使用虚拟路径,分布式环境使用OSS对象存储。
把请求url映射到本地的文件夹,一般用户文件上传之后的回显问题。
image.png
image.png

选择好文件夹过后,下面会有一个与文件夹对应的url地址

image.png
你可以把地址改成任何你喜欢的路径


15》SpringMvc异常处理:

15.1 什么是异常?

在系统中异常包括两类:
预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
系统的dao,service,controller出现异常都通过throws Exception向上抛出,最后由SpringMvc前端控制器交由异常处理器进行异常处理。

15.2 SpringMvc异常处理的两种方式:

15.2.1 使用SpringMvc提供的简单的异常处理器SimpleMappingExceptionResolver

  1. <!--简单异常处理器-->
  2. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  3. <!--默认错误视图-->
  4. <property name="defaultErrorView" value="error"/>
  5. </bean>

15.2.1.2 自定义异常页面跳转:

  1. <!--简单异常处理器-->
  2. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  3. <!--默认错误视图-->
  4. <!-- value="error" error代表错误的页面-->
  5. <property name="defaultErrorView" value="error"/>
  6. <property name="exceptionMappings">
  7. <map>
  8. <!--自定义异常跳转-->
  9. <entry key="java.io.FileNotFoundException" value="file_error"/>
  10. </map>
  11. </property>
  12. </bean>
  1. @RequestMapping("/live16")
  2. @ResponseBody
  3. public String test1() throws FileNotFoundException {
  4. System.out.println("进来了");
  5. FileInputStream file = new FileInputStream("f://testfff");
  6. return "";
  7. }

15.2.2 实现Spring的异常处理接口HandlerExcertionResolver自定义自己的异常处理器

15.2.2.1 创建异常处理实现HandlerExceptionResolver

  1. package com.xxgc.spring.resolver;
  2. import org.springframework.web.servlet.HandlerExceptionResolver;
  3. import org.springframework.web.servlet.ModelAndView;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.FileNotFoundException;
  7. public class LoginExceptionResolver implements HandlerExceptionResolver {
  8. @Override
  9. public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
  10. ModelAndView modelAndView = new ModelAndView();
  11. if(e instanceof FileNotFoundException){
  12. modelAndView.addObject("msg","文件异常");
  13. modelAndView.addObject("code","Foo_sdsa");
  14. modelAndView.setViewName("file_error");
  15. }else{
  16. modelAndView.setViewName("error");
  17. }
  18. return modelAndView;
  19. }
  20. }

15.2.2.2 配置异常处理器

  1. <!-- 自定义异常处理器-->
  2. <bean id="loginExceptionResolver" class="com.xxgc.spring.resolver.LoginExceptionResolver"/>

执行流程:
image.png

数据库设计必须有的表 错误日志表 请求记录表

Spring MVC的特点:

  1. 轻量级,简单易学
  2. 高效 , 基于请求响应的MVC框架
  3. 与Spring兼容性好,无缝结合
  4. 约定优于配置
  5. 功能强大:RESTful、数据验证、格式化、本地化、主题等
  6. 简洁灵活
  7. Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。

DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
SpringMvc笔记: - 图15

SpringMVC的原理:

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
SpringMvc笔记: - 图16
SpringMvc笔记: - 图17

SpringMvc简要分析执行流程:

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
  2. 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
  3. 如上url拆分成三部分:
  4. http://localhost:8080服务器域名
  5. SpringMVC部署在服务器上的web站点
  6. hello表示控制器
  7. 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
  8. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
  9. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
  10. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  11. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  12. Handler让具体的Controller执行。
  13. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  14. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  15. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  16. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  17. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
  18. 最终视图呈现给用户。

    SpringMvc配置:

    1.导入依赖:

    1. <dependency>
    2. <groupId>org.springframework</groupId>
    3. <artifactId>spring-web</artifactId>
    4. <version>${spring.version}</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework</groupId>
    8. <artifactId>spring-webmvc</artifactId>
    9. <version>${spring.version}</version>
    10. </dependency>

    2.配置web.xml , 注册DispatcherServlet: ```xml <?xml version=”1.0” encoding=”UTF-8”?>

springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml 1

springmvc /

  1. 3.编写SpringMVC 配置文件!名称:springmvc-servlet.xml : [servletname]-servlet.xml
  2. ```xml
  3. <?xml version="1.0" encoding="UTF-8"?>
  4. <beans xmlns="http://www.springframework.org/schema/beans"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd">
  8. </beans>

5、添加 处理映射器

  1. <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

6、添加 处理器适配器

  1. <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

7、添加 视图解析器

  1. <!--视图解析器:DispatcherServlet给他的ModelAndView-->
  2. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
  3. <!--前缀-->
  4. <property name="prefix" value="/WEB-INF/jsp/"/>
  5. <!--后缀-->
  6. <property name="suffix" value=".jsp"/>
  7. </bean>

8、编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;

  1. package com.kuang.controller;
  2. import org.springframework.web.servlet.ModelAndView;
  3. import org.springframework.web.servlet.mvc.Controller;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. //注意:这里我们先导入Controller接口
  7. public class HelloController implements Controller {
  8. public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
  9. //ModelAndView 模型和视图
  10. ModelAndView mv = new ModelAndView();
  11. //封装对象,放在ModelAndView中。Model
  12. mv.addObject("msg","HelloSpringMVC!");
  13. //封装要跳转的视图,放在ModelAndView中
  14. mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
  15. return mv;
  16. }
  17. }

9、将自己的类交给SpringIOC容器,注册bean

  1. <!--Handler-->
  2. <bean id="/hello" class="com.kuang.controller.HelloController"/>

10、写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面;

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Kuangshen</title>
  5. </head>
  6. <body>
  7. ${msg}
  8. </body>
  9. </html>

11、配置Tomcat 启动测试!

SpringMvc注解版本:

1.Maven可能存在资源过滤的问题

  1. <build>
  2. <resources>
  3. <resource>
  4. <directory>src/main/java</directory>
  5. <includes>
  6. <include>**/*.properties</include>
  7. <include>**/*.xml</include>
  8. </includes>
  9. <filtering>false</filtering>
  10. </resource>
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <includes>
  14. <include>**/*.properties</include>
  15. <include>**/*.xml</include>
  16. </includes>
  17. <filtering>false</filtering>
  18. </resource>
  19. </resources>
  20. </build>

ps:/ 和 /* 的区别:

1.< url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。
2.< url-pattern > / </ url-pattern > 会匹配 .jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。

2.SpringMvc配置:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. https://www.springframework.org/schema/context/spring-context.xsd
  10. http://www.springframework.org/schema/mvc
  11. https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  12. <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
  13. <context:component-scan base-package="com.kuang.controller"/>
  14. <!-- 让Spring MVC不处理静态资源 -->
  15. <mvc:default-servlet-handler />
  16. <!--
  17. 支持mvc注解驱动
  18. 在spring中一般采用@RequestMapping注解来完成映射关系
  19. 要想使@RequestMapping注解生效
  20. 必须向上下文中注册DefaultAnnotationHandlerMapping
  21. 和一个AnnotationMethodHandlerAdapter实例
  22. 这两个实例分别在类级别和方法级别处理。
  23. 而annotation-driven配置帮助我们自动完成上述两个实例的注入。
  24. -->
  25. <mvc:annotation-driven />
  26. <!-- 视图解析器 -->
  27. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  28. id="internalResourceViewResolver">
  29. <!-- 前缀 -->
  30. <property name="prefix" value="/WEB-INF/jsp/" />
  31. <!-- 后缀 -->
  32. <property name="suffix" value=".jsp" />
  33. </bean>
  34. </beans>

3.创建controller:

  1. package com.kuang.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.ui.Model;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. @Controller
  6. @RequestMapping("/HelloController")
  7. public class HelloController {
  8. //真实访问地址 : 项目名/HelloController/hello
  9. @RequestMapping("/hello")
  10. public String sayHello(Model model){
  11. //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
  12. model.addAttribute("msg","hello,SpringMVC");
  13. //web-inf/jsp/hello.jsp
  14. return "hello";
  15. }
  16. }

4.解决中文乱码问题:

  1. <filter>
  2. <filter-name>encoding</filter-name>
  3. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  4. <init-param>
  5. <param-name>encoding</param-name>
  6. <param-value>utf-8</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>encoding</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>