springMVC 部分知识点

六.数据处理

6.4乱码问题

测试步骤
1.我们首先在首页页面写一个form表单 用来提交数据(Get方式提交一般不会产生乱码)

<form action="/filter/t1" method="Post">
    <input type="text" name="name"/>
    <input type="text" name="age"/>
    <input type="submit" value="提交">
</form>

2.编写Controller控制器 处理前台的数据

@PostMapping("/filter/t1")
	public String test1(String name, int age, Model model) {
		model.addAttribute("name", name);
		model.addAttribute("age", age);
		System.out.println(name);
		System.out.println(age);
		return "hello01";
	}

3.输入中文 发现乱码
在这里插入图片描述
不得不说,乱码问题是在我们开发中十分常见的问题,也是我们特别头大的问题!
以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 . 修改了xml文件需要重启服务器

处理方法:

方法一:找到tomcat包config下的server.xml 添加其编码格式 (F:\DevInstall\apache-tomcat-9.0.31\conf)

<Connector port="8888" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
			   URIEncoding="UTF-8"/>

如果没有解决 就尝试下方法二

方法二:在web.xml中配置了 DispatchServlet过滤器

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

注意:<url-pattern>/*</url-pattern>的书写内容
“/”: 一般表示过滤不到后缀名的文件 不包括.jsp文件
“/*”: 一般表示带后缀名的文件,包括.jsp文件

到这里一般乱码问题就会迎刃而解,如果还出现乱码情况 就尝试方法三

方法三:自定义过滤器

在filter包下创建一个EncodingFilter 类实现过滤操作

package com.zz.filter;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * @Author 张哲
 * @Date 2020/8/2 7:58
 */
public class EncodingFilter implements Filter {
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

		//处理response的字符编码
		HttpServletResponse myResponse = (HttpServletResponse) response;
		myResponse.setContentType("text/html;charset=UTF-8");

		// 转型为与协议相关对象
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		// 对request包装增强
		HttpServletRequest myrequest = new MyRequest(httpServletRequest);
		filterChain.doFilter(myrequest, response);
	}

	public void destroy() {

	}
}

//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {

	private HttpServletRequest request;
	//是否编码的标记
	private boolean hasEncode;

	//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
	public MyRequest(HttpServletRequest request) {
		super(request);// super必须写
		this.request = request;
	}

	// 对需要增强方法 进行覆盖
	@Override
	public Map getParameterMap() {
		// 先获得请求方式
		String method = request.getMethod();
		if (method.equalsIgnoreCase("post")) {
			// post请求
			try {
				// 处理post乱码
				request.setCharacterEncoding("utf-8");
				return request.getParameterMap();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else if (method.equalsIgnoreCase("get")) {
			// get请求
			Map<String, String[]> parameterMap = request.getParameterMap();
			if (!hasEncode) { // 确保get手动编码逻辑只运行一次
				for (String parameterName : parameterMap.keySet()) {
					String[] values = parameterMap.get(parameterName);
					if (values != null) {
						for (int i = 0; i < values.length; i++) {
							try {
								// 处理get乱码
								values[i] = new String(values[i]
										.getBytes("ISO-8859-1"), "utf-8");
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
							}
						}
					}
				}
				hasEncode = true;
			}
			return parameterMap;
		}
		return super.getParameterMap();
	}

	//取一个值
	@Override
	public String getParameter(String name) {
		Map<String, String[]> parameterMap = getParameterMap();
		String[] values = parameterMap.get(name);
		if (values == null) {
			return null;
		}
		return values[0]; // 取回参数的第一个值
	}

	//取所有值
	@Override
	public String[] getParameterValues(String name) {
		Map<String, String[]> parameterMap = getParameterMap();
		String[] values = parameterMap.get(name);
		return values;
	}
}

注意:创建该过滤器后要在web.xml文件中注册该过滤器,否则不生效

<!--在filter中自定义过滤器-->
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>com.zz.filter.EncodingFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
   </filter-mapping>

这个是在网上找的一些大神写的,一般情况下,SpringMVC默认的乱码处理就已经能够很好的解决了!
乱码问题,需要平时多注意,在尽可能能设置编码的地方,都设置为统一编码 UTF-8!

八.json

8.1、什么是JSON

  • JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
  • 采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
  • 在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON
    来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

很多人搞不清楚 JSON 和 JavaScript 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。

//定义一个javascript对象
        var user={
          name:"张哲",
          age:21,
          city:"河南"
        };
        console.log(user);

要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:

// 实现从javascript 对象转换成json对象
        var json = JSON.stringify(user);
        console.log(json);
        //结果:{"name":"张哲","age":21,"city":"河南"}

要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:

//将json对象转换为js对象
        var parse = JSON.parse(json);
        console.log(parse);
        //结果:{name:"张哲",age:21,city:"河南"}

代码测试
1、新建一个module ,springmvc-05-json , 添加web的支持
2、在web目录下新建一个 json-1.html , 编写测试内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        //定义一个javascript对象
        var user={
          name:"张哲",
          age:21,
          city:"河南"
        };
        console.log(user);

        // 实现从javascript 对象转换成json对象
        var json = JSON.stringify(user);
        console.log(json);

        //将json对象转换为js对象
        var parse = JSON.parse(json);
        console.log(parse);

    </script>
</head>
<body>
</body>
</html>

3.在浏览器控制台 查看输出格式
在这里插入图片描述

8.2Controller返回JSON数据

  • Jackson应该是目前比较好的json解析工具了
  • 当然工具不止这一个,比如还有阿里巴巴的 fastjson 等等。
  • 我们这里使用Jackson,使用它需要导入它的jar包;
         <!--json数据解析-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.0</version>
        </dependency>

配置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:springmvc-servlet.xml</param-value>
        </init-param>
		 <!--启动顺序 数字越小 启动越早-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <!--配置DispatcherServlet 中文乱码过滤器-->
    <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>

springmvc-servlet.xml

 <context:component-scan base-package="com.zz.controller"/>
	 <!--过滤静态资源-->
    <mvc:default-servlet-handler/>
	
    <!--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>

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

web.xml

 <!-- 可以将 GET 和 POST 请求通过过滤器转化成 DELETE 和 PUT 请求-->
    <!-- 配置HiddenHttpMethodFilter过滤器 -->
    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <!--拦截所有请求-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

由于浏览器表单无法发送 DELETE 和 PUT 请求,所以为了让 HiddenHttpMethodFilter 识别请求的方法,需要在表单中添加一个隐藏域,名字为 _method 值为 DELETE 或 POST 或PUT,修改后 index.jsp 页面代码如下:

<!-- 新建id为1的user -->
  <form action="user" method="post">
          <input type="hidden" name="_method" value="DELETE"/>
  	<input type="submit" value="Test Rest DELETE"/>
  </form>

Controller层

	@RequestMapping(value="/user/{id}", method=RequestMethod.DELETE)
	public String destroy(@PathVariable("id") Integer id) {
		System.out.println("删除id为:" + id + "的user");
		return "success";

在pojo包下面编写一个User的实体类,然后去编写我们的测试Controller;

package com.zz.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author 张哲
 * @Date 2020/8/2 9:51
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
	private String name;
	private int age;
	private String sex;
}

在controller包下面编写UserController类
这里我们需要两个新东西,一个是@ResponseBody,一个是ObjectMapper对象,我们看下具体的用法

@Controller

//整合了@Controller+@ResponseBody 作用的效果 定义在类上
/*@RestController*/
public class UserJson {
	//原生态解决json中文乱码问题
	//@RequestMapping(value = "/json/t1", produces = "application/json;charset=utf-8")
	@RequestMapping("/json/t1")
	//他不会走视图解析器 会直接返回一个字符串(能实现前后端分离)
	@ResponseBody

	public String json1() throws JsonProcessingException {
		//创建一个jackson的对象映射器,用来解析数据
		ObjectMapper mapper = new ObjectMapper();
		//创建一个对象
		User user = new User("张哲", 21, "男");
		//讲对象转换成json格式
		String value = mapper.writeValueAsString(user);
		//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
		return value;
	}
}

代码中详细解释了@ResponseBody、@RestController的用法和区别

还有json数据解析乱码问题 解决方式
1.@RequestMappin请求方式这样写
@RequestMapping(value = "/json/t1", produces = "application/json;charset=utf-8")
2.在springmvc-servlet.xml文件中配置如下

 <!--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>

8.3 测试集合输出

@RequestMapping("/json/t2")
	@ResponseBody
	public String json2() throws JsonProcessingException {
		//测试集合转换成json格式数据
		List<User> list = new ArrayList<User>();
		ObjectMapper mapper = new ObjectMapper();
		User user1 = new User("张哲1", 21, "男");
		User user2 = new User("张哲2", 21, "男");
		User user3 = new User("张哲3", 21, "男");
		User user4 = new User("张哲4", 21, "男");

		list.add(user1);
		list.add(user2);
		list.add(user3);
		list.add(user4);

		String value = mapper.writeValueAsString(list);
		return value;
	}

运行结果:
在这里插入图片描述注意:一般在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody !我们在前后端分离开发中,一般都使用 @RestController ,十分便捷!

8.4输出时间对象

@RequestMapping("/json/t3")
	@ResponseBody
	public String json3() throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();

		Date date = new Date();

		String value = mapper.writeValueAsString(date);

		return value;

	}

运行结果:
在这里插入图片描述

  • 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!
  • Jackson 默认是会把时间转成timestamps形

解决方案:取消timestamps形式 , 自定义时间格式

@RequestMapping("/json/t4")
	@ResponseBody
	public String json4() throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();
		//不适用时间戳格式
		mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");

		//使用时间格式
		mapper.setDateFormat(simpleDateFormat);
		Date date = new Date();
		String value = mapper.writeValueAsString(date);
		return value;
	}

在这里插入图片描述
成功输出

8.5 抽取为工具类

如果要经常使用的话,这样是比较麻烦的,我们可以将这些代码封装到一个工具类中;
在utils包下创建一个JsonUtils工具类

/**
 - @Author 张哲
 - @Date 2020/8/2 12:01
 */
public class JsonUtils {

	public static String getJson(Object object) {
		//转换为指定的时间格式
		 return getJson(object, "yyyy-MM-dd HH-mm-ss");
	}

	public static String getJson(Object object, String dataFormat) {
		ObjectMapper mapper = new ObjectMapper();
		//不适用时间戳格式
		mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dataFormat);

		//使用时间格式
		mapper.setDateFormat(simpleDateFormat);

		try {
			String value = mapper.writeValueAsString(object);
			return value;
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}
}

Controller调用

    @RequestMapping("/json/t1")
	@ResponseBody
public String json1() throws JsonProcessingException {
		//创建一个对象
		User user = new User("张哲", 21, "男");
		//调用工具类中的方法
		String json = JsonUtils.getJson(user);
		return json;
	}
    @RequestMapping("/json/t4")
	@ResponseBody
	public String json4() {
		Date date = new Date();
		String json = JsonUtils.getJson(date);
		return json;
	}

8.6 FastJson

fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转 换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法 很多,最后的实现结果都是一样的。

fastjson 的 pom依赖

	<!--fastjson数据解析-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>

fastjson 三个主要的类:

  • 【JSONObject 代表 json 对象 】
  • 【JSONArray 代表 json 对象数组】
  • 【JSON 代表 JSONObject和JSONArray的转化】

测试实现:

@RequestMapping(value = "/fastjson")
	@ResponseBody
	public void fastjso(){
		//创建一个对象
		User user1 = new User("秦疆1号", 3, "男");
		User user2 = new User("秦疆2号", 3, "男");
		User user3 = new User("秦疆3号", 3, "男");
		User user4 = new User("秦疆4号", 3, "男");
		List<User> list = new ArrayList<User>();
		list.add(user1);
		list.add(user2);
		list.add(user3);
		list.add(user4);


		//java对象转json对象
		String str2 = JSON.toJSONString(user1);
		//{"age":3,"name":"秦疆1号","sex":"男"}
		System.out.println(str2);

		//json对象转java对象
		User jp_user1=JSON.parseObject(str2,User.class);
		//User(name=秦疆1号, age=3, sex=男)
		System.out.println(jp_user1);


		JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
		//秦疆2号
		System.out.println(jsonObject1.getString("name"));

		User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
		//User(name=秦疆2号, age=3, sex=男)
		System.out.println(to_java_user);
	}

在这里插入图片描述

这种工具类,我们只需要掌握使用就好了,在使用的时候在根据具体的业务去找对应的实现。和以前的 commons-io那种工具包一样,拿来用就好了!

九、ajax

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
  • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
  • Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
  • 在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。Google Suggest能够自动帮你完成搜索单词。
  • Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当您在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
  • 就和国内百度的搜索框一样!
  • 传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页。
  • 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
  • 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。

9.1、伪造ajax操作

1、创建一个test.html静态页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>iframe</title>
</head>
<script>
    function go() {
       var url=document.getElementById("url").value;
       document.getElementById("ifream1").src=url;
    }
</script>
<body>

<div>
    <p>
        <input type="text" id="url" value="https://www.baidu.com/">
        <input type="button" value="提交" onclick="go()">
    </p>
</div>
<div>
    <iframe id="ifream1" style="width: 95%;height: 800px">

    </iframe>
</div>
</body>
</html>

当点击提交后 请求百度的地址 并显示页面到指定的div中
效果:
在这里插入图片描述

9.2、jQuery.ajax

纯JS原生实现Ajax我们不去讲解这里,直接使用jquery提供的,方便学习和使用,避免重复造轮子,有兴趣的同学可以去了解下JS原生XMLHttpRequest !

Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。

jQuery 提供多个与 AJAX 有关的方法。

通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中。

jQuery 不是生产者,而是大自然搬运工。

jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!

jQuery.ajax(...)
      部分参数:
            url:请求地址
            type:请求方式,GET、POST(1.9.0之后用method)
        headers:请求头
            data:要发送的数据
    contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
          async:是否异步
        timeout:设置请求超时时间(毫秒)
      beforeSend:发送请求前执行的函数(全局)
        complete:完成之后执行的回调函数(全局)
        success:成功之后执行的回调函数(全局)
          error:失败之后执行的回调函数(全局)
        accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
        dataType:将服务器端返回的数据转换成指定类型
          "xml": 将服务器端返回的内容转换成xml格式
          "text": 将服务器端返回的内容转换成普通文本格式
          "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
        "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
          "json": 将服务器端返回的内容转换成相应的JavaScript对象
        "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

1、jQuery官网下载jquery-3.4.1.js作为原生态的js源码
2、把该文件放到web下的static文件夹下
3、编写html页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>

    <script src="${pageContext.request.contextPath}/static/jquery-3.4.1.js"></script>
    <script>
      function a() {
          $.post({
              url:"${pageContext.request.contextPath}/a1",
              data:{"name":$("#username").val()},
              success: function (data,status) {
                   //控制台Console显示请求的信息
                   /*console.log("data-->"+data);
                  console.log("status-->"+status);*/
                  alert(data);
              }
          })
      }
    </script>
  </head>
  <body>
  <%--ajax当失去焦点的时候,向服务器发送一个请求--%>
  <input type="text" id="username" onblur="a()">
  </body>
</html>

4、Controller

@RestController
public class ajaxController {
	@RequestMapping("/a1")
	public void ajax(String name, HttpServletResponse response) throws IOException {
		if ("admin".equals(name)){
			response.getWriter().print("true");
		}else {
			response.getWriter().print("false");
		}
	}
}

true

false
在这里插入图片描述

9.3、ajax操作实体类

1、创建一个实体类user

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

	private String name;
	private String sex;
	private int age;
}

2、Controller方法

@RequestMapping("/a2")

	public List<User> ajax01() {
		ArrayList<User> list = new ArrayList<User>();
		list.add(new User("小明", "男", 15));
		list.add(new User("小刘", "女", 21));
		list.add(new User("小张", "男", 16));
		return list;
	}

3、在web下面创建ajax.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>

    <script src="${pageContext.request.contextPath}/static/jquery-3.4.1.js"></script>

    <script>
        $(function () {
            $("#btn").click(function () {

                /*
                   $.post(url,parm(可以省略),success)
                 */
                $.post("${pageContext.request.contextPath}/a2", function (data) {
                    var html = "";
                    for (let i = 0; i < data.length; i++) {
                        html += "<tr>" +
                            "<td>" + data[i].name + "</td>" +
                            "<td>" + data[i].sex+ "</td>" +
                            "<td>" + data[i].age+ "</td>" +
                            "</tr>"
                    }
                    $("#content").html(html);
                })
            })
        });

    </script>

</head>
<body>
<input type="button" value="加载数据" id="btn" onclick="click">
<table>
    <tr>
        <th>姓名</th>
        <th>性别</th>
        <th>年龄</th>
    </tr>
    <tbody id="content">

    </tbody>
</table>
</body>
</html>

当点击加载数据按钮时,后台数据没经过服务器,将后台信息 提交到前台页面 运用了ajax技术
运行结果:
在这里插入图片描述

9.4、ajax实现用户登录提示

用于用户名 密码的验证 给出用户提示信息,使用户体验感更好
Controller

@RequestMapping("/a3")
	public String login(String name, String pwd) {
		String msg = "";

		if (name != null) {
			if ("zhang".equals(name)) {
				msg = "OK";
			} else {
				msg = "用户名错误";
			}
		}

		if (pwd != null) {
			if ("123456".equals(pwd)) {
				msg = "OK";
			} else {
				msg = "密码错误";
			}
		}
		return msg;
	}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>

<script src="${pageContext.request.contextPath}/static/jquery-3.4.1.js"></script>
<script>
    function a1() {
        $.post({
            url: "${pageContext.request.contextPath}/a3",
            //key-value值 key为用户后台传的参数 value:为用户文本框的id 来获取用户输入的值
            data: {"name": $("#name").val()},
            // 通过匹配渠道后台 返回的值 保存到data数据中
            success: function (data) {
               if (data.toString()==="OK"){
                   $("#userinfo").css("color","green");
               }else {
                   $("#userinfo").css("color","red");
               }

               $("#userinfo").html(data);
            }
        })
    }

    function a2() {
        $.post({
            url: "${pageContext.request.contextPath}/a3",
            data: {"pwd": $("#pwd").val()},
            success: function (data) {
                if (data.toString()==="OK"){
                    $("#pwdinfo").css("color","green");
                }else {
                    $("#pwdinfo").css("color","red");
                }

                $("#pwdinfo").html(data);
            }
        })
    }
</script>
<body>

<p>
    用户名:<input type="text" id="name" onblur="a1()"/>
    <span id="userinfo"></span>
</p>

<p>
    密码:<input type="text" id="pwd" onblur="a2()"/>
    <span id="pwdinfo"></span>
</p>

</body>
</html>

运行结果:
在这里插入图片描述

十、拦截器

10.1、登录功能添加拦截器

1、完善登录页面,在该网站没有登录用户之前,为了安全性不允许用户登录其他页面,其中就运用了拦截器功能,当session中没有对象时,不能进行其他页面的跳转,当存入session对象时,才能进行其他页面的访问,并且通过AJAX实现了判断用户名 密码是否正确的功能
2、首先定义一个起始页面index.jsp通过点击跳转到 用户登录的界面

  <a href="${pageContext.request.contextPath}/user/tologin">点击登录</a><br>
  <a href="${pageContext.request.contextPath}/user/tomain">首页</a>

在这里插入图片描述
3、当点击“点击登录”链接时通过tologin()方法跳转到login.jsp登录界面,该页面定义了一个用户登录的form表单,当提交表单时,通过login()方法跳转到main.jsp页面,说明登录成功,并运用了ajax功能判断用户名密码 是否登录正确(这里没有做数据库的连接 所有没有复杂的实现),最后在首页有一个退出功能,通过移除session中的对象,最后跳转到登录页面。
(1)在spingmvc-servlet.xml中注册拦截器

 <!--拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--拦截哪个请求-->
            <mvc:mapping path="/user/**"/>
            <!--让谁拦截-->
            <bean class="com.zz.config.LoginInterceptor"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <!--拦截哪个请求-->
            <mvc:mapping path="/**"/>
            <!--让谁拦截-->
            <bean class="com.zz.config.MyInterceptor"/>
        </mvc:interceptor>

    </mvc:interceptors>

(2)在config文件夹下面创建LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor {

	//true: 放行 执行下一个拦截器
	//false: 被拦截器拦截 不能执行下一步
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		HttpSession session = request.getSession();
		//request.getRequestURI() 返回除去host(域名或者ip)部分的路径
		
		//当进入登录页面时放行
		if (request.getRequestURI().contains("toLogin")) {
			return true;
		}
		//当提交登录表单的数据时放行
		if (request.getRequestURI().contains("login")) {
			return true;
		}

		//当点击退出时,放行
		if (request.getRequestURI().contains("logout")) {
			return true;
		}
		//当session中不为空时 说明已经登录 放行
		if (session.getAttribute("users") != null) {
			return true;
		}
		
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		return false;
	}
}

(3)创建LoginController.java

@Controller
@RequestMapping("/user")
public class LoginController {


	//当点击登录链接时 跳转到登录页面
	@RequestMapping("/toLogin")
	public String tologin() {
		//进入登录页面
		return "login";
	}

	@RequestMapping("/logout")
	public String logout(HttpSession session) {
		//注销用户 退出到首页
		if (session != null) {
			//清除session
			session.removeAttribute("users");
		}
		//return "forward:/index.jsp";
		return "redirect:/index.jsp";
	}

	@RequestMapping("/login")
	public String login(String name, String pwd, HttpSession session, Model model) {

		session.setAttribute("users", name);
		model.addAttribute("user", name);

		return "main";
	}

	@RequestMapping("/tomain")
	public String main() {

		return "main";
	}
}

(4)、VerifyController.java该类中方法的返回值不需要视图解析器的解析,直接返回需要的值,做登录信息的校验

@RestController
public class VerifyController {

	@RequestMapping("/verify")
	@ResponseBody
	//进行用户名、密码的校验
	public String verify(String name, String pwd) {

		String msg = "";
		if (name != null) {
			if ("zhang".equals(name)) {
				msg = "ok";
			} else {
				msg = "用户名错误";
			}
		}

		if (pwd != null) {
			if ("123456".equals(pwd)) {
				msg = "ok";
			} else {
				msg = "密码错误";
			}
		}
		return msg;
	}
}

在这里插入图片描述

(5)、当用户登录成功后跳转到该main.jsp页面

<body>

<h2>首页</h2>

<p style="font-weight: bold">${user}</p>
<a href="${pageContext.request.contextPath}/user/logout" style="color: red">退出</a>
</body>

在这里插入图片描述

(6)、login.jsp页面做用户的登录以及用户信息的检验

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>

    <script src="${pageContext.request.contextPath}/static/jquery-3.4.1.js"></script>

    <script>
        function a1() {
            $.post({
                url: "${pageContext.request.contextPath}/verify",
                data: {"name": $("#userName").val()},
                success: function (data) {
                    if (data.toString() === "ok") {
                        $("#nameInfo").css("color", "green");
                    } else {
                        $("#nameInfo").css("color", "red");
                    }

                    $("#nameInfo").html(data);
                }
            })
        }

        function a2() {
            $.post({
                url: "${pageContext.request.contextPath}/verify",
                data: {"pwd": $("#userPassword").val()},

                success: function (data) {
                    if (data.toString() === "ok") {
                        $("#passwordInfo").css("color", "green");
                    } else {
                        $("#passwordInfo").css("color", "red");
                    }

                    $("#passwordInfo").html(data);
                }
            })
        }

    </script>
</head>
<body>

<form action="${pageContext.request.contextPath}/user/login" method="post">
    <p>
        用户名:<input type="text" name="name" id="userName" onblur="a1()">
        <span id="nameInfo"></span>
    </p>
    <p>
        密码:<input type="text" name="pwd" id="userPassword" onblur="a2()">
        <span id="passwordInfo"></span>
    </p>
    <input type="submit" value="登录">
</form>
</body>
</html>

十一、文件上传和下载

文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;

对表单中的 enctype 属性做个详细的说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value
    属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
  • 而Spring MVC则提供了更简单的封装。
  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:
  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons
    FileUpload的组件。

1、导入maven依赖

 <!--文件上传-->
        <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>

2、在mvc中配置文件上传的bean

<!--文件上传配置-->
    <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>

3、编写Controller

/*
	 * 采用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";
	}

index.jsp

<form action="${pageContext.request.contextPath}/upload2" enctype="multipart/form-data" method="post">
    <input type="file" name="file"/><br>
    <input type="submit" value="upload">
</form>

4、文件下载

Controller

@RequestMapping(value="/download")
	public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
		//要下载的图片地址
		String  path = request.getServletContext().getRealPath("/upload");
		String  fileName = "1.png";

		//1、设置response 响应头
		response.reset(); //设置页面不缓存,清空buffer
		response.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[] buff =new byte[1024];
		int index=0;
		//4、执行 写出操作
		while((index= input.read(buff))!= -1){
			out.write(buff, 0, index);
			out.flush();
		}
		out.close();
		input.close();
		return null;
	}

请求下载链接(从该路径下面获取下载资源:E:\IdeaSpringBoot\KSSIdeaCode\SpringMVC\out\artifacts\springmvc_08_file_war_exploded\upload)

<h3>从upload文件夹下面下载</h3>
<a href="${pageContext.request.contextPath}/download">文件下载</a>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值