JavaSSM

Day1221

一、IT行业分类

  • 前端

    用户界面,眼睛能看到的,视觉效果比较。

    html5、css和css3、javascript、jquery。技术基础

    bootstrap(css框架)、vue.js(js框架)

  • 后端

    比如java后端

    javase基础

    数据库:mysql、oracle、sqlserver

    前端基础

    JavaEE基础:jsp(不推荐使用),thymeleaf(spring推荐),freemarker,volicity。或者前后端分离通过js和java数据接口进行数据对接即可

    servlet:很重要,是struts2和springmvc的基础

    java框架:struts2(替代品springmvc)、hibernate(替代品mybatis)、spring

    java微服务:spring boot、spring cloud

二、Java反射

  • 包装器类型

    基本数据类型byte、short、char、int、float、double、boolean

    包装器类型Byte、Short、Character、Integer、Float、Double、Boolean

    包装器类型,可以很方法将基本类型进行转换,比如String转为Integer,同时包装器类型是属于引用数据类型,所以默认值null。

  • 反射的作用,通过字符串名称获取类的属性对象或方法对象

DBUtil.java

package com.neuedu.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/* JDBC数据库编程
* 1.找到mysql数据库驱动jar包,并放到WebContent/WEB-INF/lib
* 2.编写数据库连接与关闭的类DBUtil
* 1.在静态代码块中加载驱动
* 2.实现数据库连接方法,并且返回java.sql.Connection对象
* 3.实现数据库关闭方法
* 注意,所有的类都是使用java.sql包下的
*/
public class DBUtil {
static {
//静态代码块
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

/**
* 数据库连接方法
* @return
*/
public static Connection getConnection() {
Connection conn = null;
String user = "root";
String password = "root";
/* jdbc:mysql:// 协议
* localhost:3306 地址及端口
* qst_yiyuan 数据库名称
* ?useUnicode=true&characterEncoding=utf8" 连接参数,设置为unicode编码并且是utf-8
*
*/
String url = "jdbc:mysql://localhost:3306/leo?useUnicode=true&characterEncoding=utf8";
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}

return conn;
}

public static void main(String[] args) {
Connection conn = getConnection();
System.out.println(conn);
}

/**
* 关闭数据库连接
* @param rs
* @param st
* @param conn
*/
public static void close(ResultSet rs, Statement st, Connection conn) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

User.java

package com.neuedu.model;

public class User {
private Integer id;
private String name;
private Integer age;

public User() {

}

public User(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

@Override
//方便打印。更方便测试查看数据是否正确
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}

}

UserDao.java

package com.neuedu.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

import com.neuedu.db.DBUtil;
import com.neuedu.model.User;
import com.neuedu.util.ReflectUtil;

public class UserDao {
private final String TABLE_NAME = "user";

/**
*
* @param sql
* @param args 可变参数,即参数的数量是不固定的,本质上是数组。 可变参数只能在形参最后一个
* @return
*/
public boolean doADU(String sql, Object... args) {
// 获取数据库连接
Connection conn = DBUtil.getConnection();
// 预处理
PreparedStatement st = null;
try {
st = conn.prepareStatement(sql);
// 绑定参数
if (args != null) {
// for-each循环
for (int i = 0; i < args.length; i++) {
st.setObject(i + 1, args[i]);
}
}
// 执行sql
int result = st.executeUpdate();
if (result > 0) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBUtil.close(null, st, conn);
}

return false;
}

public boolean add(User bean) {
String sql = "insert into" + TABLE_NAME + "(name,age) values(?,?);";

return doADU(sql, bean.getName(), bean.getAge());
}

public boolean update(User bean) {
return false;
}

public boolean delete(int id) {
return false;
}

public User queryOne(int id) {
String sql = "select * from user where id=?";
// 获取数据库连接
Connection conn = DBUtil.getConnection();
// 预处理
PreparedStatement st = null;
try {
st = conn.prepareStatement(sql);
// 绑定参数
st.setInt(1, id);
// 执行sql
ResultSet rs = st.executeQuery();
if (rs.next()) {
User bean = new User();
// bean.setId(rs.getInt("id"));
// bean.setName(rs.getString("name"));
// bean.setAge(rs.getInt("age"));
//获取数据表元数据
ResultSetMetaData md = rs.getMetaData();
int count = md.getColumnCount();//列总数
//md.getColumnLabel(index):获取列名称,如果有别名则获取别名
//md.getColumnName(index):只能获取列名称,不能获取别名
for(int i = 0; i < count; i++) {
String name = md.getColumnLabel(i + 1);
Object value = rs.getObject(name);
ReflectUtil.bindValue(bean, name, value);
}
// ReflectUtil.bindValue(bean, "id", rs.getObject("id"));
// ReflectUtil.bindValue(bean, "name", rs.getObject("name"));
// ReflectUtil.bindValue(bean, "age", rs.getObject("age"));
return bean;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBUtil.close(null, st, conn);
}

return null;
}

public static void main(String[] args) {
UserDao dao = new UserDao();
System.out.println(dao.queryOne(5));
}

public List<User> queryList() {
return null;
}
}

ReflectUtil.java

package com.neuedu.util;

import java.lang.reflect.Field;

public class ReflectUtil {
/**
* 将value绑定到obj对象的name属性
* @param obj
* @param name
* @param value
*/
public static void bindValue(Object obj, String name, Object value) {
//获取类模板信息
Class c = obj.getClass();
//Class类中包含类的基本信息,属性、方法、构造方法、接口等
/*通过名称获取属性对象
c.getDeclaredField(name):获取声明的属性,包括私有,不包括继承过来的
c.getField(name):获取所有属性,但不包括私有,包括继承过来的
*/
try {
Field f = c.getDeclaredField(name);//获取属性对象
//强制开启访问权限
f.setAccessible(true);
f.set(obj, value);//指定该属性是对象obj的,且赋值为value
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

版本二

BaseDao.java

package com.neuedu.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

import com.neuedu.db.DBUtil;
import com.neuedu.util.ReflectUtil;

public abstract class BaseDao<T> {

public abstract boolean add(T bean);
public abstract boolean update(T bean);
public abstract boolean delete(int id);

public abstract T queryOne(int id);
public abstract List<T> queryList();

/**
*
* @param sql
* @param args 可变参数,即参数的数量是不固定的,本质上是数组。 可变参数只能在形参最后一个
* @return
*/
public boolean doADU(String sql, Object... args) {
// 获取数据库连接
Connection conn = DBUtil.getConnection();
// 预处理
PreparedStatement st = null;
try {
st = conn.prepareStatement(sql);
// 绑定参数
if (args != null) {
// for-each循环
for (int i = 0; i < args.length; i++) {
st.setObject(i + 1, args[i]);
}
}
// 执行sql
int result = st.executeUpdate();
if (result > 0) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBUtil.close(null, st, conn);
}

return false;
}

public T query(String sql, Class c, List<T> list, Object... args) {
//String sql = "select * from user where id=?";
// 获取数据库连接
Connection conn = DBUtil.getConnection();
// 预处理
PreparedStatement st = null;
try {
st = conn.prepareStatement(sql);
// 绑定参数
if (args != null) {
// for-each循环
for (int i = 0; i < args.length; i++) {
st.setObject(i + 1, args[i]);
}
}
// 执行sql
ResultSet rs = st.executeQuery();
while (rs.next()) {
T bean = (T) ReflectUtil.createObject(c);
//获取数据表元数据
ResultSetMetaData md = rs.getMetaData();
int count = md.getColumnCount();//列总数
for(int i = 0; i < count; i++) {
String name = md.getColumnLabel(i + 1);
Object value = rs.getObject(name);
ReflectUtil.bindValue(bean, name, value);
}

if(list == null) {
return bean;
}

list.add(bean);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBUtil.close(null, st, conn);
}

return null;
}

}

UserDao.java

package com.neuedu.dao;

import java.util.ArrayList;
import java.util.List;

import com.neuedu.model.User;

public class UserDao extends BaseDao<User>{
private final String TABLE_NAME = "user";

public boolean add(User bean) {
String sql = "insert into" + TABLE_NAME + "(name,age) values(?,?);";

return doADU(sql, bean.getName(), bean.getAge());
}

public boolean update(User bean) {
return false;
}

public boolean delete(int id) {
return false;
}

public User queryOne(int id) {
String sql = "select * from user where id=?";
return query(sql, User.class, null, id);
}

public static void main(String[] args) {
UserDao dao = new UserDao();
System.out.println(dao.queryOne(5));
System.out.println(dao.queryList());
}

public List<User> queryList() {
String sql = "select * from user";
List<User> list = new ArrayList<User>();
query(sql, User.class, list);
return list;
}

}

ReflectUtil.java

package com.neuedu.util;

import java.lang.reflect.Field;

public class ReflectUtil {
/**
* 将value绑定到obj对象的name属性
* @param obj
* @param name
* @param value
*/
public static void bindValue(Object obj, String name, Object value) {
//获取类模板信息
Class c = obj.getClass();
//Class类中包含类的基本信息,属性、方法、构造方法、接口等
/*通过名称获取属性对象
c.getDeclaredField(name):获取声明的属性,包括私有,不包括继承过来的
c.getField(name):获取所有属性,但不包括私有,包括继承过来的
*/
try {
Field f = c.getDeclaredField(name);//获取属性对象
//强制开启访问权限
f.setAccessible(true);
f.set(obj, value);//指定该属性是对象obj的,且赋值为value
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static Object createObject(Class c) {
try {
return c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}

return null;
}
   
   /**
    * 根据set方法赋值
    * @param obj
    * @param name
    * @param value
    */
   public static void bindValueBySetMethod(Object obj, String name, Object value) {
  Class c = obj.getClass();
  //拼接set方法名称 set+第一个字母大写的属性名称
  String setMethod = "set" + upperFirstLetter(name);
  System.out.println(setMethod);
  //获取属性
  Field f;
try {
f = c.getDeclaredField(name);
  Method m = c.getDeclaredMethod(setMethod, f.getType());
  //执行方法
  m.invoke(obj, value);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
  }
}

作业

完成反射set方法

/**
    * 根据set方法赋值
    * @param obj
    * @param name
    * @param value
    */
public static void bindValueBySetMethod(Object obj, String name, Object value) {
  Class c = obj.getClass();
  //拼接set方法名称 set+第一个字母大写的属性名称
  String setMethod = "set" + upperFirstLetter(name);
  System.out.println(setMethod);
  //获取属性
  Field f;
try {
f = c.getDeclaredField(name);
  Method m = c.getDeclaredMethod(setMethod, f.getType());
  //执行方法
  m.invoke(obj, value);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
  }

Day1222

Spring介绍

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

◆目的:解决企业应用开发的复杂性

◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

◆范围:任何Java应用

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

官网

参考文档

下载地址

作者:Rod Johnson(罗德·约翰逊)

Spring前身是interface21,于2004年3月24日,发布了1.0正式版

模拟面试

1.Java类的基本组成

2.Java的重载怎么描述

方法名称相同,形参列表不同,与形参名和方法的返回值类型无关

3.说一下Java多态

1.必须是继承关系

2.就是子类转父类形态,再还可再转回子类形态

MVC开发模式

M:model,与数据库表对应JavaBean类以及Dao。相关包model和dao

V:视图

C:控制层,业务逻辑。controller和service

Spring特征

轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。

控制反转——Spring通过一种称作控制反转(IoC)的技术促进了低耦合。

面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如事务、日志管理)进行内聚性的开发。

容器——Spring包含并管理应用对象的配置和生命周期,可以配置每个bean如何被创建。

框架——Spring可以将简单的组件配置、组合成为复杂的应用。

Spring版本

Spring2.5增加注解的支持

Maven项目

Maven是用来做jar管理

参考文档 https://blog.csdn.net/huo920/article/details/82082403

1.eclipse配置maven

2.下载apache maven 3

3.创建maven项目

4.下载mysql5.0.4jar包

Spring-HelloWorld

项目结构

 

配置文件Beans.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
        				   https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="userDao" class="neusoft.dao.UserDaoImpl"></bean>
</beans>

UserDao.java

package neusoft.dao;

/**
 * Hello world!
 *
 */
public interface UserDao 
{
    void add();
    void update();
    void delete();
    void query();
}

UserDaoImpl.java

package neusoft.dao;

public class UserDaoImpl implements UserDao{
	public UserDaoImpl() {
		System.out.println("UserDaoImpl");
	}
	
	public void add() {
		System.out.println("add");
	}
	
	public void update() {
			
	}
	
	public void delete() {
		
	}
	
	public void query() {
		
	}
}

配置文件是放在源文件夹resources下,也可以直放在src下但不推荐。

UserService.java

package neuedu.service;

public interface UserService {
	
    void add();
    void update();
    void delete();
    void query();

}

UserServiceImpl.java

package neuedu.service.impl;

import neuedu.dao.UserDao;
import neuedu.service.UserService;

public class UserServiceImpl implements UserService{
	private UserDao userDao;
	
	/*	Ico控制反转
	 * 		反转:将对象的控制权交spring,创建、销毁等
	 * 	依赖注入
	 * 		构造器注入
	 * 		set注入
	 * 
	 */
	//spring构造器注入
	public UserServiceImpl(UserDao userDao) {
		this.userDao = userDao;
	}
	
	public void add() {
		userDao.add();
	}
	
	public void update() {
		userDao.update();
	}
	
	public void delete() {
		userDao.delete();
	}
	
	public void query() {
		userDao.query();
	}
}

App.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import neuedu.dao.UserDao;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    	//源码路径:在java中叫classpath
    	ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
    	//UserDao userDao = (UserDao) cxt.getBean("userDao");
    	UserDao userDao = cxt.getBean("userDao", UserDao.class);
    	userDao.add();
;    }
}

Ioc-控制反转

作业

结合BaseDao和Spring学过的知识实现登陆注册功能

eclipse创建webapp参考教程https://www.cnblogs.com/hongmoshui/p/7994759.html

UserController.java

package zuoye1222.controller;
import java.io.IOException;

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

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import zuoye1222.service.UserService;


public class UserController extends HttpServlet{
	private UserService userService;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//super.doGet(req, resp);
		System.out.println("doget");
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//super.doPost(req, resp);
		System.out.println("dopost");
		//获取spring上下文对象
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		//上下文对象可以直接操作bean容器
		userService = ctx.getBean("userService", UserService.class);
		System.out.println(userService.queryOne(1));
	}
}
package zuoye1222.controller;
import java.io.IOException;

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

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import zuoye1222.service.UserService;


public class UserController extends HttpServlet{
	private UserService userService;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//super.doGet(req, resp);
		System.out.println("doget");
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//super.doPost(req, resp);
		System.out.println("dopost");
		//获取spring上下文对象
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		//上下文对象可以直接操作bean容器
		userService = ctx.getBean("userService", UserService.class);
		System.out.println(userService.queryOne(1));
	}
}

beans.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
        				   https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 注册组件,注册的组件都必须是实现类,因为spring会帮我创建组件对象,所以不能接口 -->
	<bean id="userDao" class="zuoye1222.dao.impl.UserDaoImpl" ></bean>
	<bean id="userService" class="zuoye1222.service.impl.UserServiceImpl">
		<!-- ref:表示引用其它bean对象
			 字面值
			 	根据类型:type="" value=""
			 	根据索引:index="" value=""
			 	index是从0开始
		 -->
		<constructor-arg ref="userDao"></constructor-arg>
	</bean>
</beans>

UserDaoImpl.java

package zuoye1222.dao.impl;

import java.util.List;

import zuoye1222.dao.UserDao;
import zuoye1222.model.User;

public class UserDaoImpl extends BaseDao<User> implements UserDao{

	@Override
	public boolean add(User bean) {
		return false;
	}

	@Override
	public boolean update(User bean) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean delete(int id) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public User queryOne(int id) {
		String sql = "select * from user where id=?";
		return query(sql, User.class, null, id);
	}

	@Override
	public List<User> queryList() {
		// TODO Auto-generated method stub
		return null;
	}

}

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		 xmlns="http://java.sun.com/xml/ns/javaee" 
		 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
					http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
		 id="WebApp_ID" version="3.0">

  <display-name>Archetype Created Web Application</display-name>
  <!-- 注册 -->
  <servlet>
  	<servlet-name>user</servlet-name>
  	<servlet-class>zuoye1222.controller.UserController</servlet-class>
  </servlet>
  <!-- 配置访问url -->
  <servlet-mapping>
  	<servlet-name>user</servlet-name>
  	<url-pattern>/user</url-pattern>
  </servlet-mapping>
</web-app>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.neusoft.edu</groupId>
  <artifactId>zuoye1222</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>zuoye1222 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <version>5.2.2.RELEASE</version>
	</dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
	<dependency>
	    <groupId>mysql</groupId>
	    <artifactId>mysql-connector-java</artifactId>
	    <version>5.0.4</version>
	</dependency>
	    
  </dependencies>

</project>

Day1223

DI-依赖注入

  • 构造方法注入

    • Bean注入

    private UserDao userDao;
    	
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    
    <?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
            				   https://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!-- 注册组件,注册的组件都必须是实现类,因为spring会帮我创建组件对象,所以不能接口 -->
    	<bean id="userDao" class="zuoye1222.dao.impl.UserDaoImpl" ></bean>
    	<bean id="userService" class="zuoye1222.service.impl.UserServiceImpl">
    		<!-- ref:表示引用其它bean对象
    			 字面值
    			 	根据类型:type="" value=""
    			 	根据索引:index="" value=""
    			 	index是从0开始
    		 -->
    		<constructor-arg ref="userDao"></constructor-arg>
    	</bean>
    </beans>
    
    • 字面值

      • 类型:同类型的参数按照代码顺序进行注入

      public User(Integer id, String name, Integer age) {
      		super();
      		this.id = id;
      		this.name = name;
      		this.age = age;
      }
      

      注入的类一定要有对应的构造器

      <bean id="user" class="cn.neusoft.edu.spring_di.User">
      		<!-- ref:表示引用其它bean对象
      			 字面值
      			 	根据类型:type="" value=""
      			 	根据索引:index="" value=""
      			 	index是从0开始
      		 -->
      		<constructor-arg type="java.lang.Integer" value="2"></constructor-arg>
      		<constructor-arg type="java.lang.String" value="leo"></constructor-arg>
      		<constructor-arg type="java.lang.Integer" value="30"></constructor-arg>
      	</bean>
      
      • 索引

      <bean id="user" class="cn.neusoft.edu.spring_di.User">
      		<!-- ref:表示引用其它bean对象
      			 字面值
      			 	根据类型:type="" value=""
      			 	根据索引:index="" value=""
      			 	index是从0开始
      		 -->
      		<constructor-arg index="0" value="2"></constructor-arg>
      		<constructor-arg index="1" value="leo"></constructor-arg>
      		<constructor-arg index="2" value="30"></constructor-arg>
      	</bean>
      
  • set方法注入

    注意属性必须要有set方法

    public void setName(String name) {
        this.name = name;
    }
    public void setGames(List<String> games) {
        this.games = games;
    }
    public void setCard(Map<String, String> card) {
        this.card = card;
    }
    public void setPeiou(String peiou) {
        this.peiou = peiou;
    }
    public void setBooks(String[] books) {
        this.books = books;
    }
    
    <bean id="student" class="cn.neusoft.edu.spring_di.Student">
    		<property name="name"><value>hello</value></property>
    		<property name="books">
    			<array>
    				<value>三国</value>
    				<value>西游</value>
    			</array>
    		</property>
    		<property name="games">
    			<list>
    				<value>LOL</value>
    				<value>王者</value>
    				<value>Dota2</value>
    			</list>
    		</property>
    		<property name="card">
    			<map>
    				<entry key="shenfenzheng" value="111111111111111111"></entry>
    				<entry key="yinhangka" value="11178784039"></entry>
    			</map>
    		</property>
    		<property name="peiou">
    			<null/>
    		</property>
    	</bean>
    

    bean的name属性

    可以给注册的bean添加多个名称

    <bean id="user" name="a,b;c d" class="cn.neusoft.edu.spring_di.User">
    		<!-- ref:表示引用其它bean对象
    			 字面值
    			 	根据类型:type="" value=""
    			 	根据索引:index="" value=""
    			 	index是从0开始
    		 -->
    		<constructor-arg type="java.lang.Integer" value="2"></constructor-arg>
    		<constructor-arg type="java.lang.String" value="leo"></constructor-arg>
    		<constructor-arg type="java.lang.Integer" value="30"></constructor-arg>
    	</bean>
    
     User a = ctx.getBean("a", User.class);
    System.out.println(a);
    User b = ctx.getBean("b", User.class);
    System.out.println(b);
    User c = ctx.getBean("c", User.class);
    System.out.println(c);
    User d = ctx.getBean("d", User.class);
    System.out.println(d);
    

Bean的作用域

scope

<!-- 
  scope:
   signleton:单例模式,默认
   prototype:原型或多例模式
   web开发才会使用到
   request:当前次请求
   session:当前session对话
   下面了解,上面四个必须掌握
   application:整个浏览器
   websocket:websocket范围
  -->
<bean id="student" class="cn.neusoft.edu.spring_di.Student" scope="prototype">
    <property name="name"><value>hello</value></property>
    <property name="books">
        <array>
            <value>三国</value>
            <value>西游</value>
        </array>
    </property>
    <property name="games">
        <list>
            <value>LOL</value>
            <value>王者</value>
            <value>Dota2</value>
        </list>
    </property>
    <property name="card">
        <map>
            <entry key="shenfenzheng" value="111111111111111111"></entry>
            <entry key="yinhangka" value="11178784039"></entry>
        </map>
    </property>
    <property name="peiou">
        <null/>
    </property>
</bean>

Beans下的其它配置标签

  • alias:别名

    <?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
            				   https://www.springframework.org/schema/beans/spring-beans.xsd">
    	
    	<!-- 别名 -->
    	<alias name="user" alias="loginUser"/>
    </beans>
    
  • import:导入其它配置文件

    <import resource="department.xml"/>
    

c和p命名空间

一定要注意先在头部引入命名空间

  • c命名空间:构造器注入的简写方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
引入p命名空间       xmlns:p="http://www.springframework.org/schema/p"
     
引入c命名空间       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        				   https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="cn.neusoft.edu.spring_di.User" c:id="3" c:name="haha" c:age="20"></bean>
</beans>
  • p命名空间:set注入的简写方式

自动装配

大多用于配置set注入

  • 根据名称:ByName,推荐

private UserDao userDao;

public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}
<bean id="userDao" class="zuoye1222.dao.impl.UserDaoImpl" ></bean>
<bean id="userService" class="zuoye1222.service.impl.UserServiceImpl" autowire="byName">
</bean>
  • 根据类型:ByType,id无所谓,多个之间不方便使用

private UserDao userDao;

public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}
<bean id="userDao11" class="zuoye1222.dao.impl.UserDaoImpl" ></bean>
	<bean id="userService" class="zuoye1222.service.impl.UserServiceImpl" autowire="byType">
	</bean>

作业

1.根据今天的内容完成登录注册

2.数据库信息使用set注入完成。可以使用数据源

package zuoye1223.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/*	JDBC数据库编程
 * 		1.找到mysql数据库驱动jar包,并放到WebContent/WEB-INF/lib
 * 		2.编写数据库连接与关闭的类DBUtil
 * 			1.在静态代码块中加载驱动
 * 			2.实现数据库连接方法,并且返回java.sql.Connection对象
 * 			3.实现数据库关闭方法
 * 		注意,所有的类都是使用java.sql包下的
 */
public class DBUtil {
	private String username;
	private String password;
	private String url;
	private String driver;
	
	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	/**
	 * 数据库连接方法
	 * @return
	 */
	public Connection getConnection() {
		Connection conn = null;
		/*	jdbc:mysql://		协议
		 * 	localhost:3306		地址及端口
		 * 	qst_yiyuan			数据库名称
		 * 	?useUnicode=true&characterEncoding=utf8"	连接参数,设置为unicode编码并且是utf-8
		 * 
		 */
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//"jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8";
		try {
			conn = DriverManager.getConnection(url, username, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
	}
	
	public static void main(String[] args) {
		//Connection conn = getConnection();
		//System.out.println(conn);
		ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
		DBUtil bean = ctx.getBean("dbUtil", DBUtil.class);
		System.out.println(bean.getConnection());
	}
	
	/**
	 * 关闭数据库连接
	 * @param rs
	 * @param st
	 * @param conn
	 */
	public void close(ResultSet rs, Statement st, Connection conn) {
		if(rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(st != null) {
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

<bean id="dbUtil" class="zuoye1223.db.DBUtil" p:username="root" p:password="root">
		<property name="driver" value="com.mysql.jdbc.Driver"></property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8</value>
		</property>
	</bean>

要求,交的作业必须是md文档。所有代码都要有

Day1224

开发工具(IDE)

eclipse、intellij idea。是两个不同IDE

eclipse:老牌ide,内存占用小,编译慢,小问题多

idea:最近4年流行的,内存占用大,至少要求电脑4G。开发过程很快,编译快,提示效果非常好

创建maven项目

https://blog.csdn.net/weixin_39209728/article/details/85853516

自动装配注解实现

第一步

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        				   https://www.springframework.org/schema/beans/spring-beans.xsd
        				   http://www.springframework.org/schema/context
        				   https://www.springframework.org/schema/context/spring-context.xsd
        				   ">
	
	<!-- 支持注解 -->
	<context:annotation-config/>
	
</beans>
  • @Autowired:默认是byName,也可以byType

    • 加属性上

    • 加set方法上

    • required:true:不能为null,false允许为null

  • @Qualifier:同类型的Bean,指定名称匹配

@Qualifier("student111")
private Student student;
  • @Resource:是Java的注解

    • 效果与Autowired一样

    • 不能与@Qualifier一起用

    • 有多个同类型的Bean时,可以通过name属性指定匹配的Bean

    @Resource(name="student111")
    private Student student;
    

Java的方法

  • 构造方法

  • 一般方法

    • 实例方法(非静态方法)

      调用:类的对象.方法(实参)

    • 类方法(静态方法)

      调用:类名.方法(实参)或者类的对象.方法(实参)

  • 抽象方法

spring注解开发

  • @Component:组件,可以被扫描为Spring容器的Bean

    • @Repository:dao层

    • @Service:service层

    • @Controller:controller层

	<context:annotation-config/>
	<context:component-scan base-package="组件所在的包"></context:component-scan>
//默认以类称首字母小写为组件名称,也可指定如下
@Component("helo")
public class User {
  • @Value

  • @Scope

  • @Import

  • @Lazy:默认Spring容器是一启动的时候就会实例所有组件,通过@Lazy会改变成使用时即getBean()时才会实例化

注解开发和xml开发

xml开发可以完成所有功能实现

注解开发有些功能未必能使用,但随着版本更新可能会可以使用

使用注解开发会额外增加以下五个Bean

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

基于Java类配置

  • @Configuration

  • @Bean

package neu.java;

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

@Configuration
public class AppConfig {
	@Bean//默认以方法的名称做为id
	public Admin admin() {
		return new Admin();
	}
	
	@Bean("hello")//指定组件名称
	public Admin admin1() {
		return new Admin();
	}
	
	@Bean
	public Service service() {
		return new Service();
	}
}

package neu.java;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
	public static void main(String[] args) {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		Admin bean = ctx.getBean("admin", Admin.class);
		System.out.println(bean);
		Admin hello = ctx.getBean("hello", Admin.class);
		System.out.println(hello);
		Service service = ctx.getBean("service", Service.class);
		System.out.println(service);
	}
}

面向切面AOP

静态代理

好处是把事情交给最专业的来做

例子,租房

(不需要代理)需要租房的对象、直接找房东。省钱,概率小

(需要中介代理)需要租房的对象、找中介、房东、中介要收是介费。

需要租房的对象:Test.java

中介:代理Proxy.java

房东:FangDong.java

接口:ZuFang.java中有zuFang()这个行为

优点:只需要集中在最核心的需求,其它行为都有代理类帮忙去处理

缺点:一个代理类只能代理一种需求,工作成倍增加

package neu.proxy;

/**
 * 执行人
 * @author 12447
 *
 */
public class Test {
	public static void main(String[] args) {
		Test t = new Test();
		// 运气好直接找到房东
		//t.zhaofangzi();
		//运气不好找中介
		FangDong fd = new FangDong();
		Proxy zhongjie = new Proxy(fd);
		t.zhaofangzi(zhongjie);
	}
	
	/**
	 * 直接找房东租房子
	 */
	public void zhaofangzi() {
		FangDong fd = new FangDong();
		fd.zuFang();
	}
	
	/**
	 * 通过中介租房子
	 */
	public void zhaofangzi(Proxy zhongjie) {
		zhongjie.zuFang();
	}
}

package neu.proxy;

/**
 * 中介
 * @author 12447
 *
 */
public class Proxy implements ZuFang{
	private ZuFang fangDong;
	public Proxy(ZuFang fangDong) {
		this.fangDong = fangDong;
	}

	@Override
	public void zuFang() {
		System.out.println("中介租房");
		kanfangzi();
		fangDong.zuFang();
		shouqian();
	}
	
	public void kanfangzi() {
		System.out.println("看房子");
	}
	
	public void shouqian() {
		System.out.println("收钱");
	}

}

package neu.proxy;

public class FangDong implements ZuFang{

	@Override
	public void zuFang() {
		System.out.println("房东租房");
	}

}

package neu.proxy;

public interface ZuFang {
	void zuFang();
}

作业

1.使用xml实现登陆注册

思路

1.JSP页面

表单和表单提交,注意name属性

2.Servlet

1.LoginServlet

2.去web.xml注册配置LoginServlet

3.LoginServlet中的doPost或doGet方法去处理

1.接收表单参数

2.使用ApplicationContext加载beans.xml文件到spring容器中

3.beans.xml配置

1.注册dao

2.注册service

dao属性的注入

xml

构造器、set、c和p命名空间

3.注册model中的类,可选(慎用),作用域一定是多例

2.使用注解实现登陆注册

3.使用基于Java配置实现登陆注册

4.将静态代理的代码练习三遍

Day1225

静态代理加深理解

添加一个功能需求,比如日志打印,不希望去修改下面类的代码

UserDao

UserDaoImpl

UserService

package neusoft.dynamic.spring_proxy;

public interface UserService {
	boolean add();
	boolean update();
	boolean delete();
	void query();
}

UserServiceImpl

package neusoft.dynamic.spring_proxy;

public class UserServiceImpl implements UserService{

	@Override
	public boolean add() {
		System.out.println("add user");
		return false;
	}

	@Override
	public boolean update() {
		System.out.println("update user");
		return false;
	}

	@Override
	public boolean delete() {
		System.out.println("delete user");
		return false;
	}

	@Override
	public void query() {
		System.out.println("query user");
	}

}

UserServiceProxy

package neusoft.dynamic.spring_proxy;

public class UserServiceProxy implements UserService{
	public UserService userService;
	//set方法注入
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	@Override
	public boolean add() {
		log("add");
		return userService.add();
	}

	@Override
	public boolean update() {
		log("update");
		return userService.update();
	}

	@Override
	public boolean delete() {
		log("delete");
		return userService.delete();
	}

	@Override
	public void query() {
		log("query");
		userService.query();
	}
	
	public void log(String msg) {
		System.out.println("正在执行" + msg + "方法");
	}

}

App

package neusoft.dynamic.spring_proxy;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    	//被代理的对象
        UserService userService = new UserServiceImpl();
        //代理对象
        UserServiceProxy proxy = new UserServiceProxy();
        //注入被代理的对象
        proxy.setUserService(userService);
        //代理对象帮被代理的对象执行
        proxy.add();
    }
}

动态代理

  • 动态代理和静态代理需要的角色(类)是一样

  • 代理类的对象是动态生成的,不需要我们去写

  • 动态代理有三种实现方式

    • 基于接口:JDK的动态代理

    • 基于类:cglib

    • java字节码:javassist,目前比较流行的

学习动态代理主要学习JDK中java.lang.reflect的两个类Proxy和InvocationHandler

package neusoft.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyInvocationHandler implements InvocationHandler{
	private Object target;
	
	public void setTarget(Object target) {
		this.target = target;
	}

	//创建代理对象
	public Object createProxy() {
		/*	Proxy.newProxyInstance(loader, interfaces, h)
		 * 		loader:类加载器
		 * 		interfaces:被代理对象的接口
		 */
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	@Override//调用被代理的对象的方法
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//动态代理的本质就是使用反射来进行方法调用
		return method.invoke(target, args);
	}

}

App

package neusoft.dynamicproxy;


public class App {
	public static void main(String[] args) {
		UserServiceImpl userService = new UserServiceImpl();
		//动态代理处理类的对象 
		ProxyInvocationHandler pih = new ProxyInvocationHandler();
		//注入被代理的对象 
		pih.setTarget(userService);
		//创建代理对象
		UserService proxy = (UserService) pih.createProxy();
		//通过代理对象执行方法
		proxy.add();
	}
}

AOP

  • 是面向对象编程(OOP)的延伸

  • 面向切面编程是指一类业务

AOP实现方式

Pom.xml

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjweaver</artifactId>
		    <version>1.9.1</version>
		</dependency>
  • Spring AOP

    • 在配置文件中配置aop,需要导入aop相关的约束

    • 方式一使用Spring AOP接口

    package neusoft.aspectj;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class BeboreLog implements MethodBeforeAdvice{
    
    	/*	method:被执行的方法
    	 * 	args:方法的参数
    	 * 	target:被执行方法的对象
    	 */
    	@Override
    	public void before(Method method, Object[] args, Object target)
    			throws Throwable {
    		System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    	}
    	
    }
    
    
    package neusoft.aspectj;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class AfterLog implements AfterReturningAdvice{
    
    	@Override
    	public void afterReturning(Object returnValue, Method method,
    			Object[] args, Object target) throws Throwable {
    		System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    		System.out.println("且返回值为" + returnValue);
    	}
    }
    
    
    <?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:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            				   https://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/aop
            				   https://www.springframework.org/schema/aop/spring-aop.xsd
            				   ">
    	<bean id="userService" class="neusoft.aspectj.UserServiceImpl"></bean>
    	<bean id="beboreLog" class="neusoft.aspectj.BeboreLog"></bean>
    	<bean id="afterLog" class="neusoft.aspectj.AfterLog"></bean>
    	
    	<!-- 第一种 使用spring api接口 -->
    	<!-- 配置aop -->
    	<aop:config>
    		<!-- 切入点: expression:表达式,execution(* neusoft.aspecj.UserServiceImpl.*(..))-->
    		<aop:pointcut expression="execution(* neusoft.aspectj.UserServiceImpl.*(..))" id="log"/>
    		<!-- 执行环绕增加! -->
    		<aop:advisor advice-ref="beboreLog" pointcut-ref="log"/>
    		<aop:advisor advice-ref="afterLog" pointcut-ref="log"/>
    	</aop:config>
    </beans>
    
    package neusoft.aspectj;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App {
    	public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    		UserService bean = ctx.getBean("userService", UserService.class);
    		bean.add();
    		bean.query();
    	}
    }
    
    
  • 自定义类实现

<bean id="diy" class="neusoft.aspectj.diy.Diy"></bean>
	<aop:config>
		<aop:aspect ref="diy">
			<!-- 切入点 -->
                <aop:pointcut expression="execution(* neusoft.aspectj.UserServiceImpl.*(..))" id="log"/>
			<!-- 通知 -->
			<aop:before method="before" pointcut-ref="log"/>
			<aop:after method="afterReturn" pointcut-ref="log"/>
		</aop:aspect>
	</aop:config>
package neusoft.aspectj.diy;

public class Diy {
	public void before() {
		System.out.println("diy before");
	}
	
	public void afterReturn() {
		System.out.println("diy afterreturn");
	}
}

参考资料https://www.jianshu.com/p/5b9a0d77f95f

  • 注解实现

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        				   https://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/aop
        				   https://www.springframework.org/schema/aop/spring-aop.xsd
        				   ">
	<bean id="userService" class="neusoft.aspectj.UserServiceImpl"></bean>
	<bean id="annotationAspect" class="neusoft.aspectj.anno.AnnotationAspect"></bean>
	<!-- 开启注解支持 -->
	<aop:aspectj-autoproxy/>
</beans>
package neusoft.aspectj.anno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationAspect {
	@Before("execution(* neusoft.aspectj.UserServiceImpl.*(..))")
	public void before() {
		System.out.println("before");
	}
	
	@After("execution(* neusoft.aspectj.UserServiceImpl.*(..))")
	//被增强的方法代码后执行
	public void after() {
		System.out.println("after");
	}
	
	@AfterReturning("execution(* neusoft.aspectj.UserServiceImpl.*(..))")
	public void afterReturn() {
		System.out.println("afterReturn");
	}
	
	@Around("execution(* neusoft.aspectj.UserServiceImpl.*(..))")
	public void around(ProceedingJoinPoint pjp) {
		System.out.println("around1");
		//获得签名,有方法相关的信息
		Signature signature = pjp.getSignature();
		System.out.println("signature:::" + signature);
		try {
			Object obj = pjp.proceed();
			System.out.println("around2");
			System.out.println("obj:::" + obj);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	
	@AfterThrowing("execution(* neusoft.aspectj.UserServiceImpl.*(..))")
	public void afterThrowing() {
		System.out.println("afterThrowing");
	}
}

package neusoft.aspectj.anno;

import neusoft.aspectj.UserService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-anno.xml");
		UserService bean = ctx.getBean("userService", UserService.class);
		bean.query();
	}
}

Day1227

Spring复习

  • Maven项目:方便管理jar包

    • 下载maven软件,在apache官网

    • maven设置,maven安装目录下的conf/setting.xml

    • eclipse或idea配置maven

    • maven仓库搜索自己需要的jar包

    • pom.xml配置项目需要使用的jar包

  • Spring项目配置jar。直接配置spring-webmvc即可

  • Spring配置文件,推荐命名为application-context.xml

  • xml配置文件的约束,一般在写在xml文件头部

  • 关于bean的配置,id和class(类的完全限定名),写完之后使用ctrl+左键单击验证是否写对

  • 通过ApplicationContext接口下的ClasspathXmlApplicationContext("application-context.xml")。获取容器,再通过容器对象中的getBean(id,类名.class)获取注册Bean的对象

  • 有两个很装逼概念控制反转(Ioc)和依赖注入(DI)

    • 控制反转:由程序自己创建及管理对象的方式,转换为Spring容器来创建及管理,统称为Bean

    • 依赖注入:构造器注入和set方法注入。本质就是通过Spring容器来给注册的Bean的属性赋值

    • <bean>标签的属性name、id、class、autowire、scope

    • <import>标签,多配置文件整合

    • c和p命名空间

    • 注解开发,主要替换的就是application-context.xml文件中<beans>下的标签,比如bean、import等。在Spring容器初始化时比xml配置会多5个Bean

      • @Autowired:@Resource效果

        • @Qualifier:有多个同类型Bean情况下,通过名称指定

      • @Scope

      • @Import

      • @Value

      • @Lazy

      • @Componet,以下几个注解效果和Componet一样,只是针对MVC开发不同层进行注解

        • @Repository

        • @Service

        • @Controller

    • 基于Java配置

      • @Configuration:指定该类为配置文件

      • @Bean:注册组件,默认是以方法为id,也可以通过@Bean("名称")

  • AOP

    • 静态代理:四个角色,分别是接口,被代理的对象,代理类,执行类

    • 动态代理:角色一致。代理类不需要写,自动创建,使用的java.lang.reflect下的Proxy和IncocationHandler

    • AOP

      • 导入jar包

      • Spring AOP实现

        • 接口

          • MethodBeforeAdvice

          • MethodAfterAdvice

          • AfterReturningAdvice

          • AfterThrowingAdvice

          • 在xml文件中使用aop-config注册

            • 切入点:pointcut,id和expression,execution(* 类的全限定名.*(..))

            • 配置通知:advice,有before和after等属性

        • 自定义类

        • 注解实现

          • @Before

          • @After

          • @AfterReturning

          • @AfterThrowing

          • @Around

项目需求分析

  • 百度脑图:https://naotu.baidu.com/home,分析项目模块,每个模块有什么功能

  • 任务分工,按模块来分工。

  • 分工会带来的问题,不同人的代码如何整合。推荐代理管理工具。一定要会,没有哪个公司不同

    • SVN,自已搭建服务器和客户端,简单易用

    • GitHub:服务器在国外,比较慢,使用要复杂一点

    • 码云osChina:在国同,工具同github

  • 前端框架bootstrap、jquery,或自己找一些漂亮的界面模块

MyBatis

1.简介

官网:https://mybatis.org/mybatis-3/zh/getting-started.html

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis避免了几乎所有的 JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

DBUtil.java和BaseDao。这是工具类的解决方案

MyBatis是一个框架解决方案,功能更完整更强大

对POJO和JavaBean的知识:https://www.jianshu.com/p/d9cfd1a85068?utm_campaign=haruki&utm_content=note&utm_medium=reader_share&utm_source=weixin_timeline&from=timeline

Mybatis就是ibatis3。

2.与Hibernate对比

DBUtil.java和BaseDao,大部分封装的工具都差不多

 

Hibernate是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。只需要关心表及JavaBean即可,其它的都黑盒操作

 

缺点:因为不编写sql,灵活性和性能,sql自动生成无法保存效率和性能。越复杂的项目sql要求越高。在面试中sql必问,sql优化。HQL解决方案来解决Hibernate的sql灵活性问题,只能服务Hibernate框架,变像的增加学习成本 。

3.第一个程序

Idea工具的基本设置 https://blog.csdn.net/wytocsdn/article/details/81913701

在实际开发中有以下三种环境

  • 开发环境:dep

  • 测试环境:test

  • 生产环境:prod

POM.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>mybatis-study</groupId>
  <artifactId>mybatis-01-hello</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>m-01-hello</module>
  </modules>

  <name>mybatis-01-hello</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.3</version>
    </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.47</version>
      </dependency>

  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
s
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/leo?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.study.UserMapper">
    <!--
        namespace:名称空间
            比如下面配置了一个select,要使用的话必须通过namespace.id
        select:
            id:该sql命令的获取标识
            resultType:类的全限定名,返回类型
    -->
    <select id="selectUser" resultType="mybatis.model.User">
        select * from user where id = #{id}
    </select>
</mapper>
package mybatis.model;

public class User {
    private Integer id;
    private String name;
    private Integer age;

    public User(){}

    public User(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public java.lang.String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package mybatis.study;


import mybatis.model.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
 * Hello world!
 *
 */
public class App 
{
//    @Test
    public void t1() {
        //读配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        User user =  session.selectOne("mybatis.study.UserMapper.selectUser", 1);
        System.out.println(user);
    }
}

4.传统的Dao与DaoImpl实现

需要我们自己去实现DaoImpl类,且再调用MyBatis相关方法

5.Mybatis面向接口编程

1.修改Mapper文件中的命名空间

2.将mapper.xml放到与接口同在的包下

3.接口中的方法名称必须与mapper.xml中的id一致

4.所有得到的Mapper对象是org.apache.ibatis.binding.MapperProxy的实例

package mybatis.dao.new1;

import mybatis.model.User;

public interface UserMapper {
    /*
     * 1.修改Mapper文件中的命名空间
     * 2.将mapper.xml放到与接口同在的包下
     */
    User getById(int id);
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mybatis/dao/new1/UserMapper.xml"/>
    </mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.dao.new1.UserMapper">
    <!--
        namespace:名称空间
            比如下面配置了一个select,要使用的话必须通过namespace.id
        select:
            id:该sql命令的获取标识
            resultType:类的全限定名,返回类型
		#{id}:属于spEL语言
			参数名为id,直接获取值
			参数是一个对象有id属性,直接id属性的值
		${属性名},jstl,el
    -->
    <select id="getById" resultType="mybatis.model.User">
        select * from user where id = #{id}
    </select>
</mapper>
@Test
public void t3() throws Exception {
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    System.out.println(userMapper.getById(1));
}

作业

1.完成接口编程示例代码

2.通过查询官网和ppt教程。完成增删改查

Day1228

配置文件

  • configuration:配置文件的根节点,对应源码Configuration.java,里面的子节点建议按照顺序写

  • properties:加载jdbc属性文件

  • settings

  • typeAliases:别名,一是见名知意,二是方便使用

    • 一个个配置:typeAlias

    • 批量处理:package,默认使用类名作为别名,不能有类名相同,且不建package路径下有子包,如果存在同名类,使用注解@Alias("别名")处理即可

  • typeHandlers:了解即可.。从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。

  • environments:主要是配置数据源环境,可以配置多个environment,通过id区分。使用通过default指定当前使用的环境

    • JDBC:由JDBC处理事务,事务是一些动作行为,全部完成叫做事务。如果中间有任何动作没有完成,会回滚到原点或者保存点

    • MANAGED:啥都不做

    • POOLED:使用连接池

    • UNPOOLED:不使用

  • databaseIdProvider:配置多数据库环境,了解

  • mappers:映射器

    • resource:类路径,使用"/"分隔文件夹

    • url:网络或或外项目外的文件

    • class:包名+类名,要保存证对xml文件与java文件在同一目录下或完全使用注解

    • package:将包内的映射器接口实现全部注册为映射器

jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8
username=root
password=root

ms.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
ms.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test
ms.username=sa
ms.password=123456
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--resource:文件的路径,url:网络文件-->
    <properties resource="jdbc.properties"></properties>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
<!--        <typeAlias type="mybatis.model.User" alias="user"></typeAlias>-->
        <package name="mybatis.model"/>
    </typeAliases>

    <environments default="env_mysql">
        <environment id="env_mysql">
            <!--JDBC:由JDBC处理事务,事务是一些动作行为,全部完成叫做事务。如果中间有任何动作没有完成,会回滚到原点或者保存点
                MANAGED:啥都不做
            -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
<!--        <environment id="evn_ms">-->
            <!--JDBC:由JDBC处理事务,事务是一些动作行为,全部完成叫做事务。如果中间有任何动作没有完成,会回滚到原点或者保存点
                MANAGED:啥都不做
            -->
<!--            <transactionManager type="JDBC"/>-->
<!--            <dataSource type="POOLED">-->
<!--                <property name="driver" value="${ms.driver}"/>-->
<!--                <property name="url" value="${ms.url}"/>-->
<!--                <property name="username" value="${ms.username}"/>-->
<!--                <property name="password" value="${ms.password}"/>-->
<!--            </dataSource>-->
<!--        </environment>-->
    </environments>
    <databaseIdProvider type="DB_VENDOR">
        <property name="SQL Server" value="sqlserver"/>
        <property name="MYSQL" value="mysql"/>
        <property name="Oracle" value="oracle" />
    </databaseIdProvider>
    <mappers>
        <mapper resource="mybatis/dao/new1/UserMapper.xml"/>
    </mappers>
</configuration>

Mapper文件

  • insert:id自动增长处理

    • 不处理,mysql数据库会自动增长。

    • oracle,SEQ_CUST_INCOME_REPORT.NEXTVAL

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.dao.new1.UserMapper">
    <!--
        namespace:名称空间
            比如下面配置了一个select,要使用的话必须通过namespace.id
        select:
            id:该sql命令的获取标识
            resultType:类的全限定名,返回类型
    -->
    <select id="getById" resultType="User">
        select * from user where id = #{a}
    </select>
<!--    <select id="getById" resultType="User" databaseId="sqlserver">-->
<!--        select sname user_name, age, depart as id from user where depart = ${id}-->
<!--    </select>-->
    <insert id="insert">
        insert into user(user_name, password, age)  values(#{userName}, #{password}, #{age})
    </insert>

    <insert id="add">
        insert into user(user_name, password, age)  values(#{userName}, #{password}, #{age})
--         insert into user(user_name, password, age)  values('${userName}', '${password}', '${age}')
    </insert>

    <update id="update">
        update user set password=#{password}, age = #{age} where id=#{id}
    </update>

    <delete id="delete">
        delete from user where id=#{id}
    </delete>

</mapper>
package mybatis.dao.new1;

import mybatis.model.User;
import org.apache.ibatis.annotations.Param;

public interface UserMapper {
    /*
     * 1.修改Mapper文件中的命名空间
     * 2.将mapper.xml放到与接口同在的包下
     */
    User getById(int id);
    int insert(User bean);
    /*
        以下形参名称与mapper文件中${参数名}或#{参数名}无关,但是与@Param("名称")有关
        #{}:spEl表达式,推荐使用,功能强大很多。会做类型处理
        ${}:el表达式,只是取值不会做类型处理
     */
    int add(@Param("userName") String a, @Param("password") String b, @Param("age") int c);
    int update(User bean);
    int delete(Integer id);
}

  • update

  • delete

UserMapper.java与mapper.xml映射关系

 

Configuration解析过程

 

获取SqlSession对象的过程

 

Day1229

Java内存解析

 

ResultMap(结果集)

将多表查询的结果映射为Map

package mybatis.model;

public class User {
    private Integer id;
    private String userName;
    private Integer age;
    private String password;

    public User(){}

    public User(Integer id, String userName, Integer age) {
        this.id = id;
        this.userName = userName;
        this.age = age;
    }

    public User(Integer id, String userName, Integer age, String password) {
        this.id = id;
        this.userName = userName;
        this.age = age;
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override//方便打印对象的时候不再类名+地址,而return下的内容
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                '}';
    }
}
package mybatis.model;

import java.util.Date;

public class Record {
    private Integer id;
    private Date date;
    private String ip;
    private Integer userId;

    public Record() {

    }

    public Record(Integer id, Date date, String ip, Integer userId) {
        this.id = id;
        this.date = date;
        this.ip = ip;
        this.userId = userId;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    @Override
    public String toString() {
        return "Record{" +
                "id=" + id +
                ", date=" + date +
                ", ip='" + ip + '\'' +
                ", userId=" + userId +
                '}';
    }
}

package mybatis.dao.new1;

import java.util.Map;

public interface RecordMapper {
    Map<String, Object> getUserRecordByUserId(int id);
}

<resultMap id="userRecord" type="map">
        <id column="id" property="id"></id>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="age" property="age"/>
        <result column="date" property="date"/>
        <result column="ip" property="ip"/>
    </resultMap>

    <select id="getUserRecordByUserId" resultMap="userRecord">
        select a.id, a.username, a.password, a.age, b.date, b.ip
        from user a, record b
        where a.id = b.user_id;
    </select>

多关联查询映射JavaBean

package mybatis.model;

import java.util.Date;

public class Record {
    private Integer id;
    private Date date;
    private String ip;
//    private Integer userId;
    private User user;

    public Record() {

    }

    public Record(Integer id, Date date, String ip, User user) {
        this.id = id;
        this.date = date;
        this.ip = ip;
        this.user = user;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Record{" +
                "id=" + id +
                ", date=" + date +
                ", ip='" + ip + '\'' +
                ", user=" + user +
                '}';
    }
}

package mybatis.dao.new1;

import mybatis.model.Record;

import java.util.Map;

public interface RecordMapper {
    Map<String, Object> getUserRecordByUserId(int id);
    Record getById(Integer id);
}

<resultMap id="detailRecord" type="record">
    <id property="id" column="id" />
    <result property="date" column="date" />
    <result property="ip" column="ip" />
    <association property="user" javaType="user">
        <id property="id" column="user_id" />
        <result property="userName" column="username" />
        <result property="password" column="password" />
        <result property="age" column="age" />
    </association>
</resultMap>

<select id="getById" resultMap="detailRecord">
    select * from record a, user b
    <where>
        a.user_id = b.id and a.id=#{id};
    </where>
</select>

多表关联查询多次查询

<resultMap id="detailRecord" type="record">
    <id property="id" column="id" />
    <result property="date" column="date" />
    <result property="ip" column="ip" />
    <!--发起另一个查询-->
    <association property="user" column="user_id" javaType="user" select="mybatis.dao.new1.UserMapper.getById">
    </association>
</resultMap>
<select id="getById" resultMap="detailRecord">
    select * from record 
    <where>
        id=#{id};
    </where>
</select>

关联查询一对多

package mybatis.model;

import java.util.List;

public class User {
    private Integer id;
    private String userName;
    private Integer age;
    private String password;
    private List<Record> recordList;

    public User(){}

    public User(Integer id, String userName, Integer age) {
        this.id = id;
        this.userName = userName;
        this.age = age;
    }

    public User(Integer id, String userName, Integer age, String password) {
        this.id = id;
        this.userName = userName;
        this.age = age;
        this.password = password;
    }

    public User(Integer id, String userName, Integer age, String password, List<Record> recordList) {
        this.id = id;
        this.userName = userName;
        this.age = age;
        this.password = password;
        this.recordList = recordList;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Record> getRecordList() {
        return recordList;
    }

    public void setRecordList(List<Record> recordList) {
        this.recordList = recordList;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                ", recordList=" + recordList +
                '}';
    }
}
<resultMap id="detailUser" type="User">
    <id column="id" property="id" />
    <result column="username" property="userName"/>
    <result column="password" property="password"/>
    <result column="age" property="age"/>
    <collection property="recordList" column="id" select="mybatis.dao.new1.RecordMapper.getByUserId"></collection>
</resultMap>
<select id="getById" resultMap="detailUser">
    select * from user where id = #{a}
</select>
package mybatis.dao.new1;

import mybatis.model.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper {
    User getById(int id);

    User getByBean(User bean);

    List<User> getAll();

    int insert(User bean);
    int add(@Param("userName") String a, @Param("password") String b, @Param("age") int c);
    int update(User bean);
    int delete(Integer id);
    int deleteByIds(List<Integer> ids);
}

自动映射

自动映射autoMapping,会将列名与属性名称相同的进行自动绑定,无视大小写
<resultMap id="detailUser" type="User" autoMapping="true">
        <id column="id" property="id" />
        <collection property="recordList" column="id" select="mybatis.dao.new1.RecordMapper.getByUserId"></collection>
    </resultMap>

动态SQL

<select id="getByBean" resultType="User">
    select * from user
    <where>
        <if test="id != null">
            and id = #{id}
        </if>
        <if test="userName != null">
            and username like  concat('%', #{userName}, '%')
        </if>
    </where>
</select>
<delete id="deleteByIds">
    delete from user
    <where>
        id 
        <!--id in (id1, id2, id3)-->
        <!--先确定好自己的目标sql,再确定由foreach帮你拼接的部分-->
        <foreach collection="list" item="item" open="in (" close=")" separator=",">
            #{item}
        </foreach>
    </where>
</delete>

choose、when、otherwise:相当于switch和if-elseif-else

分页查询

原理

currIndex:从哪条记录开始,pageSize:查多少条
select * from student limit #{currIndex} , #{pageSize}

插件

PageHelper

注解开发

UserMapper.java

package neusoft.mapper;

import neusoft.model.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface UserMapper {
    //相当于xml<resultMap></resultMap>
    @Results(
            id = "detailUser",
            value = {
                    @Result(
                            property = "id", column = "id"
                    ),
                    @Result(
                            property = "recordList", column = "id", many = @Many(select = "neusoft.mapper.RecordMapper.getByUserId")
                    )
            }
    )
    @Select("select * from user where id=#{id}")
    User getById(Integer id);

    @Select("select * from user")
    @ResultMap("detailUser")
    List<User> getAll();
}

RecordMapper.java

package neusoft.mapper;

import neusoft.model.Record;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

public interface RecordMapper {
    Map<String, Object> getUserRecordByUserId(int id);
    Record getById(Integer id);
    @Select("select * from record where user_id=#{userId}")
    List<Record> getByUserId(Integer userId);
}

作业

1.上周的作业,只需要将数据库有关的使用Mybatis完成dao(mapper)和service即可。直接使用Junit测试通过即可

2.作业1,使用注解完成

Day1230

MyBatis逆向工程

官网

http://mybatis.org/generator/quickstart.html

maven依赖POM.xml

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

    <groupId>mybatis-gen</groupId>
    <artifactId>nx</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring.version>5.2.2.RELEASE</spring.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>3.5.3</mybatis.version>
        <junit.version>4.12</junit.version>
        <mybatis.gen.version>1.4.0</mybatis.gen.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>${mybatis.gen.version}</version>
        </dependency>

    </dependencies>

</project>

mybatis-generator.xml

<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--
        id:随便写,见名知意即可
        targetRuntime: MyBatis3DynamicSql(动态sql),全注解开发,不推荐使用
                        MyBatis3Kotlin(kotlin语言,谷歌用来替代java)
                            SUN公司,创建者
                            Oracle公司,收购了Sun,JDK,他的产品基本都会收费
                            Google,openJDK,出Kotlin意欲替代Java
                        MyBatis3
                            豪华版,基本支持mybatis所有功能
                        MyBatis3Simple
                            简单生成CRUD(增删改查),增加(Create)、读取(Retrieve)、更新(Update)和删除(Delete)
        context下的内容按顺序写
    -->
    <context id="dsql" targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"
                        userId="root"
                        password="root"
        />

        <!--targetProject:文件保存的路径,注意如果是项目是module,建议使用绝对路径       -->
        <javaModelGenerator targetPackage="neusoft.pojo" targetProject="src/main/java"/>
        <sqlMapGenerator targetPackage="neusoft.mapper" targetProject="src/main/resources" />
        <!--type="XMLMAPPER",如果该属性没有或者写错会出现Cannot instantiate object of type null        -->
        <javaClientGenerator targetPackage="neusoft.mapper" targetProject="src/main/java" type="XMLMAPPER"/>
        <table tableName="user" />
        <table tableName="record" />
    </context>
</generatorConfiguration>

GeneratorTest.java

package neusoft.test;

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class GeneratorTest {
    @Test
    public void t1() throws Exception{
        //每次运行前,最好把之前生成的文件都删除
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("src\\main\\resources\\mybatis-generator.xml");
        System.out.println(configFile.getAbsolutePath());
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

MyBatis和Spring整合

官网

http://mybatis.org/spring/

添加依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.3</version>
</dependency>

POM.xml

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

    <groupId>mybatis-gen</groupId>
    <artifactId>nx</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring.version>5.2.2.RELEASE</spring.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>3.5.3</mybatis.version>
        <junit.version>4.12</junit.version>
        <mybatis.gen.version>1.4.0</mybatis.gen.version>
        <mybatis.spring.version>2.0.3</mybatis.spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>${mybatis.gen.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>
    </dependencies>

</project>

application-context.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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        				   https://www.springframework.org/schema/beans/spring-beans.xsd
        				   http://www.springframework.org/schema/context
        				   https://www.springframework.org/schema/context/spring-context.xsd
        				   http://mybatis.org/schema/mybatis-spring
        				   http://mybatis.org/schema/mybatis-spring.xsd
						   ">

	<!--引入jdbc.properties-->
	<context:property-placeholder location="classpath:jdbc.properties" />
	<!--添加注解支持-->
	<context:annotation-config />
	<context:component-scan base-package="neusoft.service" />
	<!--配置数据源
		1.spring自带
		2.c3p0
		3.DBCP
		4.JNDI:如果应用配置在高性能的应用服务器(如WebLogic或Websphere等)上,
			我们可能更希望使用应用服务器本身提供的数据源。应用服务器的数据源 使用JNDI开放调用者使用,
			Spring为此专门提供引用JNDI资源的JndiObjectFactoryBean类
		5.druid
	-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driver}" />
		<property name="url" value="${url}" />
		<property name="username" value="${user}" />
		<property name="password" value="${password}" />
	</bean>
	<!--整合mybatis
			1.使用spring管理mybatis所有组件,比如mapper接口
			记住SqlSessionFactoryBean这个类
			2.使用spring事务处理
	-->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:mybatis-config.xml"></property>
	</bean>
	<!--扫描mapper接口,注意引入命名空间-->
	<mybatis:scan base-package="neusoft.mapper"/>
</beans>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <typeAliases>
        <package name="neusoft.pojo"/>
    </typeAliases>

    <mappers>
        <package name="neusoft.mapper"/>
    </mappers>
</configuration>

UserService.java

package neusoft.service;

import neusoft.pojo.User;

public interface UserService {
    User getById(Integer id);
}

UserServiceImpl.java

package neusoft.service.impl;

import neusoft.mapper.UserMapper;
import neusoft.pojo.User;
import neusoft.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    public User getById(Integer id) {
        return userMapper.selectByPrimaryKey(id);
    }
}

AppTest.java

package neusoft.test;

import neusoft.mapper.UserMapper;
import neusoft.pojo.User;
import neusoft.pojo.UserExample;
import neusoft.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class AppTest {
    @Test
    //只能测试逆向工程,不能测试整合
    public void t1() throws Exception{
        String resource = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = sqlSessionFactory.openSession();

        UserExample example = new UserExample();
        UserExample.Criteria c = example.createCriteria();
        List<Integer> list = new ArrayList<Integer>();
        list.add(30);
        list.add(20);
        list.add(10);
        //age in (30, 20, 10)
        c.andAgeIn(list);
        //and username like '%s%'
        c.andUsernameLike("%s%");
        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.selectByExample(example);
    }

    @Test
    public void t2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
        UserService userService = ctx.getBean("userService", UserService.class);
        User bean = userService.getById(1);
        System.out.println(bean);
    }
}

Spring事务

官网

https://mybatis.org/spring/zh/transactions.html

Maven依赖

<properties>
    <spring.version>5.2.2.RELEASE</spring.version>
    <mysql.version>5.1.47</mysql.version>
    <mybatis.version>3.5.3</mybatis.version>
    <junit.version>4.12</junit.version>
    <mybatis.gen.version>1.4.0</mybatis.gen.version>
    <mybatis.spring.version>2.0.3</mybatis.spring.version>
    <aspectjweaver.version>1.9.1</aspectjweaver.version>
</properties>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${aspectjweaver.version}</version>
</dependency>

application-context.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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        				   https://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/tx
        				   https://www.springframework.org/schema/tx/spring-tx.xsd
        				   http://www.springframework.org/schema/aop
        				   https://www.springframework.org/schema/aop/spring-aop.xsd
        				   http://mybatis.org/schema/mybatis-spring
        				   http://mybatis.org/schema/mybatis-spring.xsd
						   ">

	<!--引入jdbc.properties-->
	<context:property-placeholder location="classpath:jdbc.properties" />
	<!--添加注解支持-->
	<context:annotation-config />
	<context:component-scan base-package="neusoft.service" />
	<!--配置数据源
		1.spring自带
		2.c3p0
		3.DBCP
		4.JNDI:如果应用配置在高性能的应用服务器(如WebLogic或Websphere等)上,
			我们可能更希望使用应用服务器本身提供的数据源。应用服务器的数据源 使用JNDI开放调用者使用,
			Spring为此专门提供引用JNDI资源的JndiObjectFactoryBean类
		5.druid
	-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driver}" />
		<property name="url" value="${url}" />
		<property name="username" value="${user}" />
		<property name="password" value="${pass}" />
	</bean>
    <!--事务配置开始,不要忘记引入约束tx和aop-->
	<!--配置事务-->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<!--开启事务注解-->
	<tx:annotation-driven transaction-manager="txManager"/>
	<!--配置事务通知-->
	<tx:advice id="txAdvice" transaction-manager="txManager" >
		<tx:attributes>
			<!--propagation="REQUIRED"是默认值,可以不写-->
			<!--*:处理所有方法-->
			<tx:method name="*" propagation="REQUIRED"/>
			<!--处理insert开头的方法-->
			<tx:method name="insert*" />
		</tx:attributes>
	</tx:advice>
	<!--事务aop处理-->
	<aop:config>
		<!--切入点-->
		<aop:pointcut id="pcUuser" expression="execution(* neusoft.service.*.*(..))"/>
		<!--通知-->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pcUuser"></aop:advisor>
	</aop:config>
    <!--事务配置结束-->
	<!--整合mybatis
			1.使用spring管理mybatis所有组件,比如mapper接口
			记住SqlSessionFactoryBean这个类
			2.使用spring事务处理
	-->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:mybatis-config.xml"></property>
	</bean>
	<!--扫描mapper接口,注意引入命名空间-->
	<mybatis:scan base-package="neusoft.mapper"/>
</beans>

UserServiceImpl.java

package neusoft.service.impl;

import neusoft.mapper.UserMapper;
import neusoft.pojo.User;
import neusoft.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    public User getById(Integer id) {
        return userMapper.selectByPrimaryKey(id);
    }

    /**
     * 模拟事务
     * @param bean
     * @return
     */
    public boolean update(User bean) {
        userMapper.updateByPrimaryKey(bean);
        int i = 1/0;//抛出异常,中断
        bean.setAge(100);
        userMapper.updateByPrimaryKey(bean);
        return false;
    }
}

AppTest.java

@Test
    public void t3() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
        UserService userService = ctx.getBean("userService", UserService.class);
        User bean = userService.getById(1);
        bean.setAge(60);
        userService.update(bean);
        System.out.println(bean);
    }

mysql表引擎

必须是InnoDB,不然不支持事务

声明式事务

  • 事务是把一组业务或一连串动作当成一个业务或动作完成

 

  • 事务在开发中,非要重要

事务的原则ACID

  • 原子性:要么都成功,要么都失败

  • 一致性: 倘若事务操作失败,则回滚事务时,与原始状态一致。即是一致性

  • 隔离性: 当你在进行事务操作时,其他事务的操作不能影响到你的事务操作也就是事务与事务之间是隔离的,各干各的,互不干扰,干完再整合。

  • 持久性: 事务操作的结果是具有持久性的,也就是事务结果一旦写入数据库,那再不改动的情况下,数据库一直都是这个数据

Day1231

MyBatis缓存

一级缓存

只是存在当前sqlSession会话中,如果sqlSession对象销毁,那么该缓存将失效。一级缓存基本不用,原因是当mybatis和spring框架整合后,一级缓存就失效了。一级缓存也在数据库中的数据发生变化时失效。查询条件不同也会失效

二级缓存

1.自带的

2.Ehcache:第三方的

3.只要能实现mybatis中的Cache接口,就可以自定义缓存

4.如何ehcache时,如果需要将缓存写在磁盘上必须保pojo类实现了序列化

依赖
<!-- ehcache核心jar包 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.6.11</version>
        </dependency>
        <!-- MyBatis与ehcache整合jar包 -->
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.1.0</version>
        </dependency>

配置文件ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <!-- 磁盘缓存位置 -->
    <diskStore path="D:/ehcache/"/>

    <!-- 默认缓存 -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>

    <!-- userCache缓存 -->
<!--    <cache name="userCache"-->
<!--           maxElementsInMemory="1000"-->
<!--           eternal="false"-->
<!--           timeToIdleSeconds="0"-->
<!--           timeToLiveSeconds="1000"-->
<!--           overflowToDisk="false"-->
<!--           memoryStoreEvictionPolicy="LRU"/>-->
</ehcache>

UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.dao.new1.UserMapper">
    <!--开启第三方二级缓存-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache">
    </cache>
    <!--
        namespace:名称空间
            比如下面配置了一个select,要使用的话必须通过namespace.id
        select:
            id:该sql命令的获取标识
            resultType:类的全限定名,返回类型
    -->
    <resultMap id="detailUser" type="User" autoMapping="true">
        <id column="id" property="id" />
        <collection property="recordList" column="id" select="mybatis.dao.new1.RecordMapper.getByUserId"></collection>
    </resultMap>
    <select id="getById" resultMap="detailUser" >
        select * from user where id = #{a}
    </select>
<!--    <select id="getById" resultType="User">-->
<!--        select * from user where id = #{a}-->
<!--    </select>-->

    <select id="getAll" resultType="User">
        select * from user
    </select>

    <select id="getByBean" resultType="User">
        select * from user
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if test="userName != null">
                and username like  concat('%', #{userName}, '%')
            </if>
        </where>
    </select>
<!--    <select id="getById" resultType="User" databaseId="sqlserver">-->
<!--        select sname user_name, age, depart as id from user where depart = ${id}-->
<!--    </select>-->
    <insert id="insert">
        insert into user(user_name, password, age)  values(#{userName}, #{password}, #{age})
    </insert>

    <insert id="add">
        insert into user(user_name, password, age)  values(#{userName}, #{password}, #{age})
--         insert into user(user_name, password, age)  values('${userName}', '${password}', '${age}')
    </insert>

    <update id="update">
        update user set password=#{password}, age = #{age}
        where id=#{id}
    </update>

    <delete id="delete">
        delete from user where id=#{id}
    </delete>

    <delete id="deleteByIds">
        delete from user
        <where>
            id
        <!--id in (id1, id2, id3)-->
            <foreach collection="list" item="item" open="in (" close=")" separator=",">
                #{item}
            </foreach>
        </where>
    </delete>

</mapper>
App.java
@Test
    public void t13() throws Exception {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.getById(1));
        sqlSession.close();

        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        System.out.println(mapper1.getById(1));
        sqlSession1.close();
    }

Day0102

Idea新建webapp

参考资料:https://blog.csdn.net/czc9309/article/details/80304074

对于以下问题的快速解决办法。直接点击fix,二选一

 

 

war包

war包:将web项目中的src下的源码及webapp下的静态资源和jsp等页面资源压缩打的格式,可以直接放到tomcat下的webapps下运行,tomcat会自行解压

tomcat下的server.xml文件

修改项目访问路径

http://localhost:8080/项目名称/页面

http://localhost:8080:默认是进到tomcat目录下的webapps。除你在tomcat目录conf下的server.xml配置修改项目访问路径

path:项目访问路径,docBase:项目实际路径
<Context path="/upload" docBase="D:\upload" reloadable="true"></Context>

修改访问端口号及get请求乱码

port:设置的访问端口,URLEncoding:get请求时的编码设置。
<Connector URLEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

乱码问题

数据库编码,jsp或html编码,请求编码,响应编码。不一致就会造成乱码问题。具体解决后面再讲

tomcat下的web.xml

1.定义了一个DefaultServlet。拦截所有请求不拦截*.jsp

<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <init-param>
        <param-name>listings</param-name>
        <param-value>false</param-value>
    </init-param>
    1:启动顺序,多个servlet之间值越小越先启动
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    /:拦截所有除*.jsp的请求
    /*:拦截所有请求,包括*.jsp
    <url-pattern>/</url-pattern>
</servlet-mapping>

2.定义了一个JspServlet,处理*.jsp请求

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

3.mime-mapping:支持处理的文件

重新部署内容到tomcat中

不管是java代码变化还是jsp或者其它静态资源的变化,都可以

 

原生Servlet+JSP开发

1.创建Servlet,重写doGet和doPost方法

2.在web.xml文件中注册。多个servlet,多次注册

坏处,web.xml中注册的servlet会有几十或上百个,难以管理

解决办法

1.按业务来分,不同的业务以传参来解决。一个Servlet代码太多,难以管理

http://locahost:8080/test/login?type=1:表示注册

http://locahost:8080/test/login?type=2:表示登录

LoginServlet中

String type = request.getParameter("type");

if(type.equals("1")) {

注册

}else if(type.equals("2")){

登录

}

3.使用struts2,定义Action来解决

4.使用springmvc,来解决。springmvc是在3.0之后才超过了struts2

SpringMVC

1.导包-Maven依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
里面包含了spring核心相关的jar

2.web.xml注册

1.设置欢迎页面
<!--配置默认请求的页面,比如http://localhost:8080/ssm01
    以上请求默认会有一个处理页面,一般默认值index.jsp或index.html
    如下代码,即默认打开login.jsp。
    优先级按代码顺序
  -->
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
2.注册springmvc前端控制器
<!--注册springmvc的serlvet,即前端控制器,处理请求-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <!--servlet-class中的值是spring-webmvc包提供的类,即前端控制器,用于控制所有请求 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!---加载配置-->
      <param-value>classpath:application-context.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--url-pattern(重点)中有3个值,分别为/、 /*、 *.action  -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--spring前端控制器注册结束-->
3.完整的web.xml
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>没啥用</display-name>
  <!--注册springmvc的serlvet,即前端控制器,处理请求-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <!--servlet-class中的值是spring-webmvc包提供的类,即前端控制器,用于控制所有请求 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!---加载配置-->
      <param-value>classpath:application-context.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--url-pattern(重点)中有3个值,分别为/、 /*、 *.action  -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--spring前端控制器注册结束-->
  <!--配置默认请求的页面,比如http://localhost:8080/ssm01
    以上请求默认会有一个处理页面,一般默认值index.jsp或index.html
    如下代码,即默认打开login.jsp。
    优先级按代码顺序
  -->
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

3.编写Controller

package neusoft.controller;

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

@Controller//注意名称不要写错,以及包名
public class HelloController {
    //@RequestMapping("hello01"),效果同下,推荐下面写法
    @RequestMapping("/hello01")
    public String hello01() {
        /*
            对应web-inf下的页面
                web-inf下的内容,只能够通过servlet访问
                不能够通过浏览器地址直接访问
         */
        return "WEB-INF/pages/success.jsp";
    }
}

4.在application-context.xml开启扫描

 

5.配置视图解析器

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--注意最后的/-->
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>
@RequestMapping("/hello01")
public String hello01() {
    return "success";
}

6.将项目部署到tomcat下运行

https://www.jianshu.com/p/1c3a39f3c057

7.@Controller

用于标记是一个控制器类,本质上是一个@Component

8.tomcat端口被占用

Address localhost:1099 is already in use。一个端口号只能对应一个程序

9.@RequestMapping

配置Controller类和其中的方法访问路径

  • value:效果同path,指定访问路径,重点

eg:@RequestMapping("/hello"),访问路径上多一个hello父路径。http://localhost:8080/ssm01/hello/hello01

  • method:指定请求方式,重点

GET, POST, PUT, DELETE:常用

OPTIONS, TRACE, HEAD, PATCH:基本不用

@RequestMapping(value = "/hello02", method = RequestMethod.GET)
public String hello02() {
    return "success";
}

如上限制方法只能使用get方式访问

HTTP Status 405 - Request method 'POST' not supported。此错误就是因为发起访问的method不对

  • params:设置请求的参数来限制方法的访问,了解一下

1.params={"username"}:要求请求该方法必须带有username参数,否则出现HTTP Status 400 - Parameter conditions "username" not met for actual request parameters:

@RequestMapping(value = "/hello03", params = {"username"})
public String hello03() {
    return "success";
}
<a href="hello/hello03">错误的请求hello03</a>
<a href="hello/hello03?username">正确的请求hello03</a>
<a href="hello/hello03?username=">正确的请求hello03</a>
<a href="hello/hello03?username=123">正确的请求hello03</a>

2.params={"!username"}:不能带username

3.params={"username=123"}:必须且=123才行

4.params={"username!=123", "!pwd", "age"}

  • headers:http协议的头部信息,了解一下

参考教程:https://blog.csdn.net/private66/article/details/82288857

比如限制浏览的访问

@RequestMapping(value = "/hello04", headers = "User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0")
public String hello04(HttpServletRequest request) {
    System.out.println(request.getHeader("User-Agent"));
    return "success";
}
  • consumes:只接受内容类型是哪种请求,规定请求头中的Content-Type,了解一下

  • produces:告诉浏览器返回的内容类型是什么,给响应头加上Content-Type,了解一下

10.html页面元素的路径

以路径,比如href、src、url等
/:表示的意思是tomcat的根路径即,webapps
/hello/hello01:http://localhost:8080/hello/hello01
hello/hello01:表示相对路径,在当前路径的后面附加,即http://localhost:8080/ssm01/hello/hello01
去到上级目录:../
当前目录:./,一般不需要
<a href="/hello/hello01">请求/hello/hello01</a><br>
<a href="hello/hello01">请求hello/hello01</a><br>
<a href="hello/hello02">get方式请求hello02</a>

不管是jsp还是servlet或freemarker和thymeleaf等动态页面开发语言,从服务解析之后传回客户端浏览的时候都是html

11.ANT风格api

其实是url的风格。还有一个叫restful风格(推荐)

优先做精确匹配

模糊匹配的两种方式

?:匹配一个字符

*:匹配多个字符,可以放在父路径中, **,表示多层父路径

@RequestMapping(value = "/hello0?")
public String hello05() {
    System.out.println("我是05");
    return "success";
}

@RequestMapping(value = "/hello0*")
public String hello06() {
    System.out.println("我是06");
    return "success";
}

@RequestMapping(value = "/*/hello0*")
public String hello07() {
    System.out.println("我是06");
    return "success";
}

@RequestMapping(value = "/**/hello0*")
public String hello08() {
    System.out.println("我是06");
    return "success";
}
<a href="hello/hello05">请求hello05</a>
<a href="hello/hello06666">请求hello06</a>
<a href="hello/aaaa/hello04">请求hello07</a>
<a href="hello/a/b/c/hello04">请求hello08</a>

12.@PathVariable

获取url中的值,不是参数

  • value:效果同name,指定参数的名称。默认是参数名称与变量名称相同

  • name

  • required:false,允许变量为null,如果为true,但又没有传HTTP Status 500 - Missing URI template variable 'age' for method parameter of type Integer

@RequestMapping(value = "/hello09/{name}")
public String hello09(@PathVariable String name) {
    System.out.println("你的参数内容是:" + name);
    return "success";
}

@RequestMapping(value = "/hello10/{name}/{age}")
public String hello10(@PathVariable String name, @PathVariable Integer age) {
    System.out.println("你的参数内容是:" + name + "," + age);
    return "success";
}

@RequestMapping(value = {"/hello11/{abc}/{age}","/hello11/{abc}"})
public String hello11(@PathVariable("abc") String name, @PathVariable(required = false) Integer age) {
    System.out.println("你的参数内容是:" + name + "," + age);
    return "success";
}

@RequestMapping(value = {"/hello12/{abc}/{age}","/hello12/{abc}"})
public String hello12(@PathVariable("abc") String name, @PathVariable Integer age) {
    System.out.println("你的参数内容是:" + name + "," + age);
    return "success";
}
<a href="hello/hello09/haha">请求hello09</a>
<a href="hello/hello10/haha/20">请求hello10</a>
<a href="hello/hello11/haha/20">请求hello11</a>
<a href="hello/hello12/haha">请求hello12,测试没有age值</a>

13.注解类型

/** Class, interface (including annotation type), or enum declaration 加在类上*/
TYPE,
/** Field declaration (includes enum constants) 加在属性上*/
FIELD,02
/** Formal parameter declaration 加在形参上*/
PARAMETER,

/** Constructor declaration 加在构造器*/
CONSTRUCTOR,

/** Local variable declaration 加在局部变量*/
LOCAL_VARIABLE,

/** Annotation type declaration 加在注解类型*/
ANNOTATION_TYPE,

/** Package declaration 加在包上*/
PACKAGE,

/**
 * Type parameter declaration 加在参数类型
 *
 * @since 1.8
 */
TYPE_PARAMETER,

/**
 * Use of a type 当成类型使用
 *
 * @since 1.8
 */
TYPE_USE

14.Restful风格api

一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

备注 ANT风格(旧api) Restful风格
查询一个 selectXXX?id=1 user/1--Get
去到修改页面 updateXXX?id=1 user/1--PUT
删除一个 deleteXXX?id=1 user/1--DELETE
去到添加页面 addXXX user--GET
保存 save user--POST
RestfulController.java
package neusoft.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * 为了测试restful风格api,不是测试RestController注解
 */
@RequestMapping("/rest")
@Controller
public class RestfulController {
    /**
     * 去到添加页面
     * @return
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String add() {
        System.out.println("add");
        return "success";
    }

    @PostMapping("/")
    public String save(String name) {
        System.out.println("save"+name);
        return "success";
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String getById(@PathVariable Integer id) {
        System.out.println("getById" + id);
        return "success";
    }

    /**
     * 根据id删除
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public String deleteById(@PathVariable Integer id) {
        System.out.println("deleteById" + id);
        return "success";
    }

    /**
     * 去到修改页面
     * @param id
     * @return
     */
    @PutMapping("/{id}")
    public String updateById(@PathVariable Integer id) {
        System.out.println("updateById" + id);
        return "success";
    }
}

restful.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="rest/">去到添加页面</a><br>
    <form action="rest/" method="post">
        <input type="text" name="name" >
        <button>测试save</button>
    </form>
    <br>

    <a href="rest/1">测试查询</a><br>
    <a href="#" onclick="doRest('rest/1', 'delete')">测试删除(失效)</a><br>
    <form id="form" method="post">
        <input type="hidden" name="_method" value="delete">
        <button>测试删除</button>
    </form><br>
    <a href="#" onclick="doRest('rest/1', 'put')">测试修改</a><br>
    <script>
        function doRest(href, method) {
            var form = document.getElementById("form");
            //var href = this.href;
            console.log(href);
            console.log(method);
            form.action = href;
            var input_method = document.getElementsByName("_method")[0];
            input_method.value = method;
            form.submit();//提交表单
            return false;
        }
    </script>
</body>
</html>

15.HiddenHttpMethodFilter.java

是一个过滤器也就是filter

web.xml
<!--restful过滤器-->
  <filter>
    <filter-name>restful</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>restful</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
源码
@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		HttpServletRequest requestToUse = request;
		//判断如果是post请求且没有异常
		if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
            //获取_method的参数
			String paramValue = request.getParameter(this.methodParam);
            //判断参数是否有值 
			if (StringUtils.hasLength(paramValue)) {
                //将参数值转为大写
				String method = paramValue.toUpperCase(Locale.ENGLISH);
                //判断是否是put或delete
				if (ALLOWED_METHODS.contains(method)) {
					requestToUse = new HttpMethodRequestWrapper(request, method);
				}
			}
		}

        //如果不是post请求,直接放行
		filterChain.doFilter(requestToUse, response);
	}

16.关于高版本的tomcat对支持restful风格的问题

 

解决方法

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
将isErrorPage设置为true,原因是tomcat8,默认将其设置为false,导致变成8大对象

17.SpringMVC如何获取参数

获取参数指的,url中?后面的部分

1.servlet获取参数

request.getParameter("参数名称");

2.@RequestParam:获取请求参数,参数默认必须带值。
  • value:指定要获取的参数名称

  • required:是否必须带上参数,是否null

如果为true,但是不传这个参数,则报错

 

  • defaultValue:默认值

ParamController.java
package neusoft.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(String name, String password) {
        System.out.println("name:::" + name + ",password:::" + password);
        return "success";
    }

    @RequestMapping(value = "/t01")
    public String t01(@RequestParam("abc") String name, @RequestParam(required = false, defaultValue = "haha") String password) {
        System.out.println("name:::" + name + ",password:::" + password);
        return "success";
    }
}

param.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="param/login" method="post">
    <input type="text" name="name">
    <input type="password" name="password">
    <button>login</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="abc">
    <input type="password" name="password">
    <button>t01</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="abc">
    <button>t01,没有password参数</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="name">
    <button>t01,没有abc这个参数</button>
</form>
</body>
</html>

3.@RequestHeader:获取请求头中某个值,相当于request.getHeader()
  • value:指定参数的key

  • required:

  • defaultValue:

4.@CookieValue:获取cookie值

原生jsp

Cookie[] cs = request.getCookies();
    for (Cookie item : cs) {
        String name = item.getName();
        if(name.equals("JSESSIONID")) {
        String value = item.getValue();
        System.out.println("JSESSIONID:::" + value);
    }
}
  • value:获取名称key

  • required

  • defaultValue

注意,以上三个注解默认都是以变量名称做value的值

5.使用POJO,使用最多的
User.java
package neusoft.pojo;

public class User {
    private Integer id;
    private String username;
    private Integer age;
    //如下,定义了一个有参构造方法,必须再定义一个无参的构造方法。因为框架基本都会使用到无参构造方法
    public User() {
    }

    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

ParamController.java
package neusoft.controller;

import neusoft.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(String name, String password) {
        System.out.println("name:::" + name + ",password:::" + password);
        return "success";
    }

    @RequestMapping(value = "/t01")
    public String t01(@RequestParam("abc") String name, @RequestParam(required = false, defaultValue = "haha") String password) {
        System.out.println("name:::" + name + ",password:::" + password);
        return "success";
    }

    @RequestMapping(value = "/t02")
    public String t02(@RequestParam("abc") String name,
                      @RequestParam(required = false, defaultValue = "haha") String password,
                      @RequestHeader("User-Agent") String userAgent) {
        System.out.println("name:::" + name + ",password:::" + password);
        System.out.println(userAgent);
        return "success";
    }

    @RequestMapping(value = "/t03")
    public String t03(@CookieValue("JSESSIONID") String value) {
        System.out.println("t03");
        System.out.println(value);
        return "success";
    }

    @RequestMapping(value = "/t04")
    public String t04(User bean) {
        System.out.println("t04");
        System.out.println(bean);
        return "success";
    }
}

param.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="param/login" method="post">
    <input type="text" name="name">
    <input type="password" name="password">
    <button>login</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="abc">
    <input type="password" name="password">
    <button>t01</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="abc">
    <button>t01,没有password参数</button>
</form>
<form action="param/t01" method="get">
    <input type="text" name="name">
    <button>t01,没有abc这个参数</button>
</form>
<a href="param/t02?abc=123">测试t02</a>
<a href="param/t03">测试t03</a>
<%
    Cookie[] cs = request.getCookies();
    for (Cookie item : cs) {
        String name = item.getName();
        if(name.equals("JSESSIONID")) {
            String value = item.getValue();
            System.out.println("原生代码JSESSIONID:::" + value);
        }
    }

    //Cookie: JSESSIONID=ED98DB61BF8CA230540FCC5E90F8C8AD
%>
<form action="param/t04" method="post">
    <input type="text" name="id">
    <input type="text" name="username">
    <input type="number" name="age">
    <button>测试t04,使用pojo</button>
</form>
<form action="param/t04" method="post">
    <input type="text" name="id">
    <input type="text" name="username">
    <button>测试t04,使用pojo,少一个age属性</button>
</form>
</body>
</html>

6.SpringMVC参数支持的使用原生api
  • HttpServletRequest

  • HttpServletResponse

  • HttpSession

@RequestMapping(value = "/t05")
    public String t05(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        System.out.println(request.getParameter("abc"));
        System.out.println(response);
        System.out.println(session.getAttribute("ses"));
        return "success";
    }
7.中文乱码
  • 请求乱码

    • get:在tomcat中conf下的server.xml文件修改

    <Connector URLEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
     URLEncoding="UTF-8",这里关键
    
    • post:相当于Servlet中的request.setCharacterEncoding("UTF-8");在Springmvc中使用拦截器

    CharacterEncodingFilter.java源码

     

    <!--请注意是在web.xml文件中-->
    <!--编码拦截器或过滤器,必须是第一个拦截器-->
      <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>
    

     

    如果出现以上错误,参考教程https://bbs.csdn.net/topics/290007965。解决方法如下,注意空格

     

  • 响应乱码:response.setContentType("text/html;charset=UTF-8");

8.数据回显

就是将Controller中的数据显示在jsp或其它view页面上。通过request域

1.Servlet原生api处理
			request.getRequestDispatcher("/success.jsp").forward(request, response);
2.map处理

ParamController.java

    @RequestMapping(value = "/t06")
    public String t06(Map<String, Object> map) {
        map.put("msg", "haha你好");
        return "success";
    }

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" isELIgnored = "false" %>
<!--isELIgnored = "false"开启el表达式的支持-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>恭喜你</title>
</head>
<body>
page:${pageScope.msg}<br>
request:${requestScope.msg}<br>
session:${sessionScope.msg}<br>
application:${applicationScope.msg}
<br>
    哈哈,终于成功了
</body>
</html>

3.Model处理
4.ModelMap处理
@RequestMapping(value = "/t06")
public String t06(Map<String, Object> map) {
    map.put("msg", "haha你好");
    return "success";
}

@RequestMapping(value = "/t07")
public String t07(Model model) {
    model.addAttribute("msg", "Model中的haha你好");
    return "success";
}

@RequestMapping(value = "/t08")
public String t08(ModelMap model) {
    model.addAttribute("msg", "ModelMap中的haha你好");
    return "success";
}

底层干活的就是BindingAwareModelMap

5.ModelAndView

在SpringMVC中,不管传的就是String视图,还是Model或Map或ModelMap+String视图,底层都帮我们处理为一个ModelAndView对象

@RequestMapping(value = "/t09")
    public ModelAndView t09(HttpSession session) {
        ModelAndView mav = new ModelAndView();
        //设置视图
        mav.setViewName("success");
        //添加数据
        mav.addObject("msg", "这是ModelAndView数据");
        session.setAttribute("loginUser", new User(1, "leo", 30));

        return mav;
    }
9.session域

1.直接使用HttpSession

2.@SessionAttributes:不推荐使用。将request域中的信息,同时给session域添加一份。参考https://blog.csdn.net/csyy140225/article/details/82454611

10.页面跳转
1.servlet页面跳转

转发:request.getRequestDispatcher("转发的页面").forward(request, response);

重定向:response.sendRedirect("重定向的页面");

2.转发

转发是不会经过视图解析器处理,也可以获取request域中的数据

注意,1。转发的路径怎么;2。是否能传数据

在return "forward:页面名称.jsp"

    @RequestMapping(value = "/t10")
    public String t10() {
        return "forward:success";
    }

    @RequestMapping(value = "/t11")
    public String t11() {
        //不能去到web-inf里面
        return "forward:success.jsp";
    }

    @RequestMapping(value = "/t12")
    public String t12(ModelMap model) {
        model.addAttribute("msg", "ModelMap中的haha你好");
        //当前路径是http://localhost:8080/ssm01/param/t12
        http://localhost:8080/ssm01/
        return "forward:../forward.jsp";
    }
3.重定向

return "redirect:页面名称.jsp"

1.会将数据显示在url中,地址栏会变化

2.无法获取request域,因为是重新创建了一个request对象

    @RequestMapping(value = "/t13")
    public String t13(ModelMap model) {
        model.addAttribute("msg", "ModelMap中的haha你好");
        //当前路径是http://localhost:8080/ssm01/param/t12
        //http://localhost:8080/ssm01/
        return "redirect:../forward.jsp";
    }

测试代码

<a href="param/t10">测试t10</a><br>
<a href="param/t11">测试t11</a><br>
<a href="param/t12">测试t12</a><br>
<a href="param/t13">测试t13</a><br>
4.springmvc配置文件配置视图

原来都在Controller中,写上方法再加@RequestMapping注解,配置url。当只是去到某一个页面,不想写方法。可能直接在springmvc配置文件中写

<!--会引起一个严重的后果,controller中的所有url全部是404-->
    <mvc:view-controller path="/test" view-name="success"></mvc:view-controller>
    <!--将springmvc,功能全开-->
    <mvc:annotation-driven />
5.静态资源处理

静态资源:js,css,images。这些是不需要被springmvc拦截的

<!--告诉springmvc,自己映射的请求就自己处理,不能处理的请求就交给tomcat-->
    <mvc:default-servlet-handler />
6.数据格式化

主要针对日期类型还有数字类型(货币)

reg.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="user/save" method="post">
    <input type="text" name="username" >
    <input type="number" name="age" >
    <input type="date" name="regDate" >
    <button>提交</button>
</form>
</body>
</html>

UserController.java
package neusoft.controller;

import neusoft.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

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

    @RequestMapping("/save")
    public String save(User bean) {
        System.out.println(bean);
        System.out.println(new Date());

        return "success";
    }
}

application-context.xml
    <mvc:annotation-driven conversion-service="convertService"/>
    <bean id="convertService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
User.java
package neusoft.pojo;

import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

public class User {
    private Integer id;
    private String username;
    private Integer age;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date regDate;
    //如下,定义了一个有参构造方法,必须再定义一个无参的构造方法。因为框架基本都会使用到无参构造方法
    public User() {
    }

    public User(Integer id, String username, Integer age, Date regDate) {
        this.id = id;
        this.username = username;
        this.age = age;
        this.regDate = regDate;
    }

    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getRegDate() {
        return regDate;
    }

    public void setRegDate(Date regDate) {
        this.regDate = regDate;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", age=" + age +
                ", regDate=" + regDate +
                '}';
    }
}

7.数据校验

参考:https://blog.csdn.net/iwts_24/article/details/83792423

SSM整合

一、需求分析

功能模块思维导图

二、数据库结构

1.ER图

2.表结构

user表

名称 类型 是否为空 主键 备注
id int 自动增长
name varchar(45)     用户名
password varchar(45)     密码
email varchar(45)     邮箱
phone varchar(11)     手机
reg_date datetime     注册日期
last_login_date datetime     最后一次登录日期

3.数据sql

user.sql

create table user
(
	id int auto_increment,
	name varchar(45) null,
	password varchar(45) null,
	email varchar(45) null,
	phone varchar(11) null,
	reg_date datetime null,
	last_login_date datetime null,
	constraint user_pk
		primary key (id)
);

三、组员工作划分

以表格形式,每个组员都必须经历jsp->servlet->service-mapper->-mapper.xml

四、代码整合工具

svn还是码云还是github

五、POM.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>neusoft</groupId>
  <artifactId>ssm-02</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>ssm-02 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.2.2.RELEASE</spring.version>
    <mysql.version>5.1.47</mysql.version>
    <mybatis.version>3.5.3</mybatis.version>
    <junit.version>4.12</junit.version>
    <mybatis.gen.version>1.4.0</mybatis.gen.version>
    <slf4j.version>1.7.6</slf4j.version>
    <mybatis.spring.version>2.0.3</mybatis.spring.version>
    <aspectjweaver.version>1.9.1</aspectjweaver.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>${mybatis.gen.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis.spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${aspectjweaver.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>


  </dependencies>

  <build>
    <finalName>ssm-02</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

六、配置文件

1.spring相关

application-context.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
        				   https://www.springframework.org/schema/context/spring-context.xsd
                           ">

    <!--引入jdbc.properties-->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!--添加注解支持-->
    <context:annotation-config />
    <context:component-scan base-package="neusoft" />
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${driver}" />
        <property name="url" value="${url}" />
        <property name="username" value="${user}" />
        <property name="password" value="${pass}" />
    </bean>

    <import resource="spring-mabatis.xml"/>
    <import resource="spring-mvc.xml"/>
    <import resource="spring-tx.xml"/>

</beans>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
        				   http://www.springframework.org/schema/mvc
        				   https://www.springframework.org/schema/mvc/spring-mvc.xsd
                           ">
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--会引起一个严重的后果,controller中的所有url全部是404-->
<!--    <mvc:view-controller path="/test" view-name="success"></mvc:view-controller>-->
    <!--告诉springmvc,自己映射的请求就自己处理,不能处理的请求就交给tomcat-->
    <mvc:default-servlet-handler />

    <!--将springmvc,功能全开-->
    <mvc:annotation-driven conversion-service="convertService" />
    <bean id="convertService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
</beans>

spring-tx.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
        				   http://www.springframework.org/schema/tx
        				   https://www.springframework.org/schema/tx/spring-tx.xsd
        				   http://www.springframework.org/schema/aop
        				   https://www.springframework.org/schema/aop/spring-aop.xsd
                           ">
    <!--配置事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--事务AOP处理-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pcuser" expression="execution(* neusoft.service.*.*(..))"/>
        <!--通知-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pcuser"></aop:advisor>
    </aop:config>
</beans>

spring-mybatis.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:mybatis="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
        				   http://mybatis.org/schema/mybatis-spring
        				   http://mybatis.org/schema/mybatis-spring.xsd
                           ">
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>
    <mybatis:scan base-package="neusoft.mapper"/>
</beans>

2.mybatis

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <typeAliases>
        <package name="neusoft.pojo"/>
    </typeAliases>

    <mappers>
        <package name="neusoft.mapper"/>
    </mappers>
</configuration>

3.日志

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[CateringLog] %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c - %m%n" />
        </layout>
    </appender>
    <appender class="org.apache.log4j.RollingFileAppender" name="file">
        <param name="File" value="d:/companyProject/logs/catering.log" />
        <param name="Append" value="true" />
        <param name="MaxFileSize" value="1024KB" />
        <param name="MaxBackupIndex" value="5" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[CateringLog] %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c - %m%n" />
        </layout>
    </appender>
    <root>
        <priority value="debug" />
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>
    <!--通过<logger></logger>的定义可以将各个包中的类日志输出到不同的日志文件中-->
    <logger name="org.springframework">
        <level value="ERROR" />
    </logger>
    <logger name="org.mybatis.spring">
        <level value="ERROR" />
    </logger>
    <logger name="net.sf.ehcache">
        <level value="ERROR" />
    </logger>
    <logger name="com.mchange.v2">
        <level value="ERROR" />
    </logger>
    <logger name="java.sql">
        <level value="debug" />
    </logger>
</log4j:configuration>

七、代码

1.pojo

User.java
package neusoft.pojo;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private String password;
    private String email;
    private String phone;
    private Date regDate;
    private Date lastLoginDate;

    public User(){

    }

    public User(Integer id, String name, String password, String email, String phone, Date regDate, Date lastLoginDate) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.email = email;
        this.phone = phone;
        this.regDate = regDate;
        this.lastLoginDate = lastLoginDate;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Date getRegDate() {
        return regDate;
    }

    public void setRegDate(Date regDate) {
        this.regDate = regDate;
    }

    public Date getLastLoginDate() {
        return lastLoginDate;
    }

    public void setLastLoginDate(Date lastLoginDate) {
        this.lastLoginDate = lastLoginDate;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", regDate=" + regDate +
                ", lastLoginDate=" + lastLoginDate +
                '}';
    }
}

2.mapper

UserMappler.java
package neusoft.mapper;

import neusoft.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface UserMapper {
    User getById(Integer id);
    User login(@Param("name") String name, @Param("password") String password);
    User getByName(String name);
    boolean insert(User bean);
    boolean update(User bean);
    List<User> getList();
}

UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="neusoft.mapper.UserMapper">

    <select id="getById" resultType="User">
        select * from user where id = #{id}
    </select>
    <select id="login" resultType="User">
        select * from user where name = #{name} and password = #{password}
    </select>
    <select id="getList" resultType="User">
        select * from user
    </select>
    <select id="getByName" resultType="User">
        select * from user where name = #{name}
    </select>

    <insert id="insert">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">
                id,
            </if>
            <if test="name != null">
                name,
            </if>
            <if test="password != null">
                password,
            </if>
            <if test="email != null">
                email,
            </if>
            <if test="phone != null">
                phone,
            </if>
            <if test="regDate != null">
                reg_date,
            </if>
            <if test="lastLoginDate != null">
                last_login_date,
            </if>
        </trim>
         values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">
                #{id},
            </if>
            <if test="name != null">
                #{name},
            </if>
            <if test="password != null">
                #{password},
            </if>
            <if test="email != null">
                #{email},
            </if>
            <if test="phone != null">
                #{phone},
            </if>
            <if test="regDate != null">
                #{reg_date},
            </if>
            <if test="lastLoginDate != null">
                #{last_login_date},
            </if>
        </trim>
    </insert>

    <update id="update">
        update user set
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name != null">
                name = #{name},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="phone != null">
                phone = #{phone},
            </if>
            <if test="regDate != null">
                reg_date = #{reg_date},
            </if>
            <if test="lastLoginDate != null">
                last_login_date = #{last_login_date},
            </if>
        </trim>
        where id = #{id}
    </update>


</mapper>

3.service

UserService.java
package neusoft.service;

import neusoft.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserService {
    User getById(Integer id);
    User login(String name, String password);
    User getByName(String name);
    boolean insert(User bean);
    boolean update(User bean);
    List<User> getList();
}

UserServiceImpl.java
package neusoft.service.impl;

import neusoft.mapper.UserMapper;
import neusoft.pojo.User;
import neusoft.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public User getById(Integer id) {
        return userMapper.getById(id);
    }

    @Override
    public User login(String name, String password) {
        return userMapper.login(name, password);
    }

    @Override
    public User getByName(String name) {
        return userMapper.getByName(name);
    }

    @Override
    public boolean insert(User bean) {
        return userMapper.insert(bean);
    }

    @Override
    public boolean update(User bean) {
        return userMapper.update(bean);
    }

    @Override
    public List<User> getList() {
        return userMapper.getList();
    }
}

4.controller

UserController.java
package neusoft.controller;

import neusoft.pojo.User;
import neusoft.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpSession;

import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    //@PostMapping("/login")http://localhost:8080/ssm-02/user/login
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(String name, String password, Model model, HttpSession session) {
        System.out.println("login:::name:::" + name + ", password" + password);
        User bean = userService.login(name, password);
        if (bean != null) {
            //登录成功
            //session保存
            session.setAttribute("loginUser", bean);
            //记住密码,使用Cookie

        }else {
            //登录失败
            model.addAttribute("msg", "用户名或密码错误");
            //return "forward:login.jsp";//http://localhost:8080/ssm-02/user/login.jsp
            return "forward:../login.jsp";
        }
        return "index";
    }

    @PostMapping("/reg")
    public String reg(User bean, String cfmpassword, Model model) {
        System.out.println("reg:::" + bean);
        System.out.println("reg:::" + cfmpassword);
        //判断用户名重复
        if (userService.getByName(bean.getName()) != null) {
            model.addAttribute("msg", "该用户名已经被使用");
            return "forward:../reg.jsp";
        }
        //判断两次密码是否一致
        if(!bean.getPassword().equals(cfmpassword)) {
            model.addAttribute("msg", "两次输入密码不一致");
            return "forward:../reg.jsp";
        }

        boolean result = userService.insert(bean);
        if (result) {
            System.out.println("注册成功");
            return "forward:../login.jsp";
        }
        System.out.println("注册失败");
        model.addAttribute("msg", "注册失败");
        return "forward:../reg.jsp";
    }

}

5.jsp

reg.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" isErrorPage="true" %>
<% pageContext.setAttribute("ctx", request.getContextPath()); %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    ${requestScope.msg}<br>
    <form action="${ctx}/user/reg" method="post">
        <input type="text" name="name" placeholder="请输入用户名">
        <input type="password" name="password" placeholder="请输入密码">
        <input type="password" name="cfmpassword" placeholder="请输入确认密码">
        <button>注册</button>
    </form>
</body>
</html>

login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" isErrorPage="true" %>
<% pageContext.setAttribute("ctx", request.getContextPath()); %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link href="${ctx}/layui/css/layui.css" rel="stylesheet">
    <link href="${ctx}/css/common.css" rel="stylesheet">
    <link href="${ctx}/css/login.css" rel="stylesheet">
</head>
<body>
<div class="layui-container">
    <div class="layui-row">
        <div class="layui-col-md-offset4 layui-col-md4">
            <form class="layui-form" action="${ctx}/user/login" method="post">
                <h1 class="layui-input-block">欢迎注册</h1>
                <div class="layui-form-item">
                    <input type="text" class="layui-input" name="name" placeholder="请输入用户名">
                </div>
                <div class="layui-form-item">
                    <input type="text" class="layui-input" name="password" placeholder="请输入密码">
                </div>
                <div class="layui-form-item">
                    <button class="layui-btn layui-btn-fluid" lay-submit lay-filter="formDemo">登录</button>
                </div>
                <div class="layui-form-item">
                    <div class="layui-input-block">
                        <div class="layui-btn-group">
                            <a href="reg.jsp" class="layui-btn layui-btn-primary">注册</a>
                            <button type="reset" class="layui-btn layui-btn-warm">重置</button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

</body>
</html>

6.css

common.css
.layui-container {
    margin-top: 20px;
}
login.css
form h1 {
    margin-bottom: 20px;
}

7.layui

下载地址:https://www.layui.com/

8.数据较验

分为两类

1.前端较验:使用js或jq完成,但浏览器可以关闭对js的支持,不安全

2.后台较验:有一个规范JSR303,还有一些是Hibernate validator的

img

1.maven依赖

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.0.9.Final</version>
</dependency>

2.相关注解说明

@AssertFalse 验证注解的元素值是 false
@AssertTrue 验证注解的元素值是 true
@DecimalMax(value=x) 验证注解的元素值小于等于指定的十进制value 值
@DecimalMin(value=x) 验证注解的元素值大于等于指定的十进制value 值
@Digits(integer=整数位数, fraction=小数位数)验证注解的元素值的整数位数和小数位数上限
@Future 验证注解的元素值(日期类型)比当前时间晚,预约未来
@Past 验证注解的元素值(日期类型)比当前时间早,过去时
@Max(value=x) 验证注解的元素值小于等于指定的 value值
@Min(value=x) 验证注解的元素值大于等于指定的 value值
@NotNull 验证注解的元素值不是 null
@Null 验证注解的元素值是 null
@Pattern(regex=正则表达式) 验证注解的元素值不指定的正则表达式匹配,比如手机号
@Size(min=最小值, max=最大值) 验证注解的元素值的在 min 和 max (包含)指定区间之内,如字符长度、集合大小
@Valid 该注解主要用于字段为一个包含其他对象的集合或map或数组的字段,或该字段直接为一个其他对象的引用,这样在检查当前对象的同时也会检查该字段所引用的对象。
@NotEmpty 验证注解的元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0)
@Range(min=最小值, max=最大值)验证注解的元素值在最小值和最大值之间
@NotBlank 验证注解的元素值不为空(不为 null、去
除首位空格后长度为 0),不同于@NotEmpty, @NotBlank 只应用于字符串且在比较时会去除字符串的空格
@Length(min=下限, max=上限) 验证注解的元素值长度在 min 和 max 区间内
@Email 验证注解的元素值是 Email,也可以通过正则表达式和 flag 指定自定义的 email 格式

3.编写javabean,在需要校验的属性上面添加相应的注解

package neusoft.pojo;

import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.*;
import java.util.Date;

public class User {
    private Integer id;
    @NotNull(message = "用户名不能为空")
    @Length(message = "用户名长度必须{min}-{max}在之间", max = 20, min = 4)
    private String name;
    @NotNull(message = "密码不能为空")
    @Size(min = 6, message = "密码长度不能小于{min}")
    private String password;
    @Email(message = "邮箱格式不对")
    private String email;
    @Pattern(regexp = "^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$", message = "手机号码不正确")
    private String phone;
    @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")//记得去springmvc注解consersionService
    @Past(message = "注册日期不对")
    private Date regDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")//记得去springmvc注解consersionService
    @Past(message = "最后一次登录日期不对")
    private Date lastLoginDate;

    public User(){

    }

    public User(Integer id, String name, String password, String email, String phone, Date regDate, Date lastLoginDate) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.email = email;
        this.phone = phone;
        this.regDate = regDate;
        this.lastLoginDate = lastLoginDate;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Date getRegDate() {
        return regDate;
    }

    public void setRegDate(Date regDate) {
        this.regDate = regDate;
    }

    public Date getLastLoginDate() {
        return lastLoginDate;
    }

    public void setLastLoginDate(Date lastLoginDate) {
        this.lastLoginDate = lastLoginDate;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", regDate=" + regDate +
                ", lastLoginDate=" + lastLoginDate +
                '}';
    }
}

4.在spring-mvc.xml配置

<!--将springmvc,功能全开-->
    <mvc:annotation-driven conversion-service="convertService" validator="validator" />
    <bean id="convertService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
    <!--注册数据较验器-->
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
    </bean>

5.Controller方法编写

@PostMapping("/reg")
    public String reg(@Valid User bean, BindingResult br, String cfmpassword, Model model) {
        System.out.println("reg:::" + bean);
        System.out.println("reg:::" + cfmpassword);
        //判断两次密码是否一致
        if(!bean.getPassword().equals(cfmpassword)) {
            model.addAttribute("msg", "两次输入密码不一致");
            return "forward:../reg.jsp";
        }
        //数据较验
        if(br.hasErrors()) {
            Map<String, String> errors = new HashMap<String, String>();
            System.out.println("==============================表单数据出错=================================");
            List<FieldError> fieldErrors = br.getFieldErrors();
            for (FieldError item : fieldErrors) {
                System.out.println(item.getField());
                System.out.println(item.getDefaultMessage());
                errors.put(item.getField(), item.getDefaultMessage());
            }
            model.addAttribute("errors", errors);
            return "forward:../reg.jsp";
        }

        //判断用户名重复
        if (userService.getByName(bean.getName()) != null) {
            model.addAttribute("msg", "该用户名已经被使用");
            return "forward:../reg.jsp";
        }

        boolean result = userService.insert(bean);
        if (result) {
            System.out.println("注册成功");
            return "forward:../login.jsp";
        }
        System.out.println("注册失败");
        model.addAttribute("msg", "注册失败");
        return "forward:../reg.jsp";
    }

5.JSP页面编写

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" isErrorPage="true" %>
<% pageContext.setAttribute("ctx", request.getContextPath()); %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    ${requestScope.msg}<br>
    <form action="${ctx}/user/reg" method="post">
        <input type="text" name="name" placeholder="请输入用户名"><span >${requestScope.errors.name}</span><br>
        <input type="password" name="password" placeholder="请输入密码"><span >${requestScope.errors.password}</span><br>
        <input type="password" name="cfmpassword" placeholder="请输入确认密码"><br>
        <input type="text" name="email" placeholder="请输入邮箱"><span >${requestScope.errors.email}</span><br>
        <input type="text" name="phone" placeholder="请输入手机号"><span >${requestScope.errors.phone}</span><br>
        <button>注册</button>
    </form>
</body>
</html>

八、重大问题

在tomcat/webapps/项目名/WEB-INF/classes会有一个所有源码编译生成的文件夹。该文件夹应该包含所有java文件编译产生的.class文件,且mapper接口XXXMapper.class对应的XXXMapper.xml必须在同一个目录下

九、SpringMVC使用JSON数据交互

json是一种数据格式,为了方便在不同开发端进行数据交互。跟平台无关。还有一个叫xml数据交互,xml太繁琐,标签比内容还多

开发端:

后端(后台):java、php、python、c++

前端:html、css、javascript

移动端:android、ios

数据交互:

后台:输出json格式的数据,能接收json格式数据

前端:ajax技术,jquery比较多,因为如果用javascript直接写太麻烦

移动端:有相应的json解析技术

1.@RequestBody

接收json格式的参数。测试发现可以直接提交json数据并转化为Java对象。所以@RequestBody不需要使用

2.@ResponseBody

将数据以json的格式输出到页面

/**
     * 以json数据格式返回数据
     * @return
     */
    @GetMapping("/getListJson")
    @ResponseBody
    public List<User> getListJson() {
        System.out.println("getListJson");
        return userService.getList();
    }
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" isErrorPage="true" %>
<%@include file="../../include.jsp"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主界面</title>
</head>
<body>
    <div>
        <table>
            <thead>
            <tr><th>编号</th><th>姓名</th><th>密码</th></tr>
            </thead>
            <tbody>

            </tbody>
        </table>
    </div>

    <script src="${ctx}/js/jquery-3.4.1.min.js"></script>
    <script>
        //jquery代码都必须写在ready方法中
        $(document).ready(function () {
            $.get("${ctx}/user/getListJson",function(data,status){
                console.log(data);
                console.log("数据: " + data + "\n状态: " + status);
                $.each(data, function (index, item) {
                    console.log(index);
                    console.log(item);
                    var table = $("table");
                    var tr = document.createElement("tr");
                    var td1 = document.createElement("td");
                    td1.innerText = item.id;
                    tr.append(td1);
                    var td2 = document.createElement("td");
                    td2.innerText = item.name;
                    tr.append(td2);
                    var td3 = document.createElement("td");
                    td3.innerText = item.password;
                    tr.append(td3);
                    table.append(tr);
                })
            });
        });

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

3.Maven依赖

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.5</version>
    </dependency>

十、拦截器

拦截执行某方法之后的操作,最主要的体现就是登录拦截器

拦截器只是针对springmvc来说的作用相当于servlet中过滤器

1.实现HandlerInterceptor

LoginInterceptor.java

package neusoft.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    //请求之前,在请求方法之前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //System.out.println("preHandle:::" + request.getRequestURI());
        System.out.println("preHandle:::" + request.getRequestURL());
        StringBuffer url = request.getRequestURL();

        if (url.toString().endsWith("user/login") || url.toString().endsWith("user/reg")) {
            return true;
        }else {
            //获取session对象
            Object o = request.getSession().getAttribute("loginUser");
            if (o == null) {
                //传个参数
                request.setAttribute("msg", "请先登录");
                //没有登录过
                //response.sendRedirect("../login.jsp");
                //如果页面都在pages下
                request.getRequestDispatcher("../login.jsp").forward(request, response);
            }else {
                return true;
            }
        }
        return false;
    }

    @Override
    //请求通过,是方法里面的代码执行之后
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    //请求完成,页面渲染完毕
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

2.在spring-mvc.xml配置

<!--静态资源不拦截-->
    <mvc:resources location="/" mapping="/*"/>
    <!--注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/**/*.css"/>
            <mvc:exclude-mapping path="/**/*.js"/>
            <bean class="neusoft.interceptor.LoginInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

十一、文件上传

十二、异常处理

十三、SpringMVC运行流程

猜你喜欢

转载自www.cnblogs.com/fafafa123/p/12187909.html