1、创建一个Spring starter project
web mybatis mysql devtools(热加载)
2、SpringBoot中默认使用的视图技术是Thymeleaf,如果需要使用jsp,则需要
pom.xml添加一个依赖
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
如果需要将应用部署到tomcat之类的服务器中,则需要修改主应用文件并配置打包方式为war
@SpringBootApplication
public class App extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(App.class);
}
}
3、引入SpringMVC的配置类进行相关的配置定义
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
}
4、使用应用的核心配置文件定义相关的配置
目前常见的方法有2种: application.properties和application.yml
properties属于比较古老的写法,定义语法为
a.b=ccc其中a.b是key,ccc是值
yml是一种新的标记语言yaml,YAML是“YAML不是一种标记语言”的外语缩写;但为了强调这种语言以数据做为中心,而不是以置标语言为重点,而用返璞词重新命名。它是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言。官方网站为yaml.org
语法:
a:
b: ccc
4.1、定义数据源
SpringBoot中默认使用的连接池是HikariCP,也可以使用阿里的Druid
引入druid的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql:///test
username: root
password: 123456
单元测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {
@Autowired
private DataSource ds;
@Test
public void contextLoads() throws Exception {
System.out.println(ds.getConnection());
}
}
4.2、定义实体和对应的表结构
//提示: 一般正式开发中定义表结构时不添加对应的约束,直到产品部署
create table t_users(
id bigint primary key auto_increment,
username varchar(20)not null unique,
password varchar(20) not null,
birth timestamp default current_timestamp,
sex boolean default 1
) engine=innodb default charset utf8;
添加依赖
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.4</version>
</dependency>
引入通用 Mapper的写法:
1、没有映射元文件,相关的映射信息使用注解定义在实体类
@Entity //声明当前类是一个实体类
@Table(name="t_users")//声明当前类对应的表名称
public class User implements Serializable{
private static final long serialVersionUID = 4003610184190858149L;
@Id //声明id属性对应的是主键
@GeneratedValue(strategy=GenerationType.IDENTITY)用于声明主键生成策略
针对mysql的auto_increment,生成策略为GenerationType.IDENTITY
private Long id;
@Column(name="username")声明username属性对应的列名称为username,如果名称
一致可以不用定义name属性
private String username;
@Column
private String password;
@Column
private Date birth;
@Column
private Boolean sex;
生成对应的getter,setter 方法 toString()
}
2、定义对应的mapper接口,这个接口只需要继承于Mapper接口即可,这里已经包含了常见的增删改查的方法,除非有特殊方法需要声明,否则不需要定义什么方法
public interface UserMapper extends Mapper<User> {}
3、在主类上使用新的注解声明对应的mapper接口所在的包名称,使系统自动识别mapper接口
@SpringBootApplication
@tk.mybatis.spring.annotation.MapperScan("com.yan.dao")
public class App extends SpringBootServletInitializer
4、单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {
@Autowired
private UserMapper userMapper;
@Test
public void testCreate() {
User user = new User();
user.setUsername("yanjun");
user.setPassword("123456");
int len=userMapper.insertSelective(user);
System.out.println(len);
assertEquals(1, len);
}
5、打开日志输出所执行的SQL语句
logging:
level:
com.ren: debug
5、引入事务
5.1、在主类上声明使用事务
@EnableTransactionManagement//声明打开注解事务支持
public class App extends SpringBootServletInitializer
5.2、在业务上使用@Transactional声明事务的特性
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class UserServImpl implements IUserServ {
@Autowired
private UserMapper userMapper;
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public boolean create(User user) {
int len = userMapper.insertSelective(user);
return len > 0;
}
}
5.3、一般建议针对业务方法需要进行对应的单元测试,进行对应功能的确认
6、定义页面和控制器等相关的表现层操作
0、定义视图解析器的相关参数
spring:
mvc:
view:
prefix: /WEB-INF/conent/
suffix: .jsp
1、按照WebConfig中的配置registry.addViewController("/").setViewName(“index”);先定义首页面/WEB-INF/content/index.jsp
1.1、在定义jsp页面时经常需要使用JSTL,所以需要添加依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
1.2、定义首页
<a href="/users/add">新增用户</a>
1.3、定义控制器
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "add", method = RequestMethod.GET)
public String add(Model model) throws Exception {
User user = new User();
user.setSex(true);
model.addAttribute("user", user); //需要使用<form:form>定义输入表单
return "user/add";
}
}
1.4、定义输入页 add.jsp
<form:form modelAttribute="user">
用户名称:<form:input path="username" />
<form:errors path="username" />
<br />
用户口令:<form:password path="password" />
<form:errors path="password" />
<br />
确认口令:<form:input path="repassword" />
<form:errors path="repassword" />
<br />
出生日期:<form:input path="birth" />
<form:errors path="birth" />
<br />
性别:<form:radiobuttons items="${sexOptions}" path="sex" />
<form:errors path="sex" />
<br />
<input type="submit" value="新增用户" />
</form:form>
为了实现性别选项,所以在Controller中添加了一个方法
@ModelAttribute("sexOptions")
public Map<Boolean, String> sexOptions() {
Map<Boolean, String> res = new LinkedHashMap<>();
res.put(true, "男");
res.put(false, "女");
return res;
}
2、启动应用进行页面的测试
启动应用可以使用maven
run as–>Spring boot App
默认访问路径为http://localhost:8080/,如果需要修改端口号,可以添加一个配置
server:
port: 9000
7、服务器端数据校验 hibernate-validator
public String add(@Validated @ModelAttribute("user") User user, Errors errors) throws Exception {
if(errors.hasErrors())
return "user/add"; 如果有报错信息则自动跳转到输入页
在值bean中添加注解,定义对应的校验
@NotBlank(message="用户名称不能为空")
@Length(min=6,max=20,message="用户名称应该在6到20个字符之间!")
private String username;
定义执行验证的顺序:
要求只有非空的情况下才需要执行长度验证
@GroupSequence({ LoginFirstGroup.class, LoginSecondGroup.class })
interface LoginGroup { }
给对应的校验设置不同的分组
@NotBlank(message = "用户名称不能为空", groups = LoginFirstGroup.class)
@Length(min = 6, max = 20, message = "用户名称应该在6到20个字符之间!", groups = LoginSecondGroup.class)
private String username;
给验证设置执行哪个分组的验证
public String add(@Validated(LoginGroup.class) @ModelAttribute("user") User user, Errors errors,
Model model) throws Exception {
8、数据类型转换
针对日期格式的定义
spring.mvc.date-format=yyyy-MM-dd
9、中文乱码问题:
使用系统默认的UTF-8编码【页面的编码字符集为UTF-8,数据的提交方式必须为post】
数据入库问题:
spring:
datasource:
url: jdbc:mysql:///test?useUnicode=true&characterEncoding=utf8
10、客户端验证
jquery jquery.validate
静态资源的存放位置 src/main/resources/static
例如存放图片: 新建文件夹 images/ 存放图片
在页面中的访问路径为 /images/mv01.jpg
在src/main/resources/static文件夹下新建文件夹jslib,将js文件拷贝到jslib文件夹
<script type="text/javascript" src="${pageContext.request.contextPath}/jslib/jquery.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/jslib/jquery.validate.js"></script>
使用jquery.validate执行客户端数据校验
$(function() {
$('#user').validate({
rules : {
username:{required:true,rangelength:[6,20],remote:'${pageContext.request.contextPath}/users/check'},
password:{required:true},
repassword:{required:true,equalTo:'#password'}
},
messages : {
username:{required:'必须填写!',rangelength:'长度应在6到20个字符之间!',remote:'用户名称已占用'},
password:{required:'必须填写!'},
repassword:{required:'必须填写!',equalTo:'两次输入口令必须一致'}
}
});
});
在控制器中返回一个只包含true或者false的响应信息
@RequestMapping(value = "check")
@ResponseBody
public String check(String username) throws Exception {
boolean exists=userService.existsName(username);
return !exists+""; //注意false表示验证失败,true表示验证通过
}
11、Mapper框架中提供的查询
SELECT id,username,password,birth,sex FROM t_users
User temp = new User();
List<User> list = userMapper.select(temp);
SELECT id,username,password,birth,sex FROM t_users WHERE username = ?
User temp = new User();
temp.setUsername("yanjun");
List<User> list = userMapper.select(temp);
SELECT id,username,password,birth,sex FROM t_users WHERE username = ? AND password = ?
User temp = new User();
temp.setUsername("yanjun");
temp.setPassword("123456");
List<User> list = userMapper.select(temp);
12、使用maven管理的jquery
选用webjar来管理前台资源文件,因为通过手工进行管理,容易导致文件混乱、版本不一致等问题。而WebJars是将这些通用的Web前端资源打包成Java的Jar包,然后借助Maven工具对其管理,保证这些web资源版本唯一性,升级也比较容易
删除了src/main/resources/static/jslib下的jquery.js
添加依赖
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-1</version>
</dependency>
引入jquery.js的方法:
<script type="text/javascript"
src="${pageContext.request.contextPath}/webjars/jquery/3.3.1-1/jquery.js"></script>
13、登录处理流程:
1、首页面添加超连接打开登录页面
<a href="${pageContext.request.contextPath}/users/login">登录系统</a>
2、定义控制器处理login的get请求
@RequestMapping(value = "login", method = RequestMethod.GET)
public String login(Model model) throws Exception {
User user = new User();
model.addAttribute("user", user); // 需要使用<form:form>定义输入表单
return "user/login";
}
3、定义login页面
<form:form modelAttribute="user">
用户名称:<form:input path="username" />
<form:errors path="username" />
<br />
用户口令:<form:password path="password" />
<form:errors path="password" />
<br />
<input type="submit" value="登录系统" />
</form:form>
4、定义控制器处理login的post请求
@SessionAttributes("loginUser")
public class UserController {
@Autowired
private IUserServ userService;
@RequestMapping(value = "login", method = RequestMethod.POST)
public String login(@Validated(UserGroup.LoginGroup.class) @ModelAttribute("user") User user, Errors errors,
Model model) throws Exception {
if (errors.hasErrors())
return "user/login";
boolean bb = userService.login(user);
if (bb) {
model.addAttribute("loginUser", user);
return "redirect:/users/";
} else {
model.addAttribute("msg", "登录失败!请重新登录");
return "user/login";
}
}
5、定义业务实现
public boolean login(User user) {
Assert.notNull(user,"参数错误!");
Assert.hasText(user.getUsername(), "参数错误!");
Assert.hasText(user.getPassword(), "参数错误!");
List<User> ulist=userMapper.select(user);
if(ulist!=null && ulist.size()>0) {
User temp=ulist.get(0);
BeanUtils.copyProperties(temp, user);
return true;
}
return false;
}
6、登录成功后跳转到显示用户信息的页面
@RequestMapping(value = "/", method = RequestMethod.GET)
public String list(Model model) throws Exception {
List<User> list = userService.getAllUsers();
model.addAttribute("userList", list);
return "user/list";
}
@Override
public List<User> getAllUsers() {
return userMapper.selectAll();
}
<table border="1" align="center">
<thead>
<tr><th>用户编号</th><th>用户名称</th><th>用户口令</th>
<th>出生日期</th><th>性别</th><th>操作</th></tr>
</thead>
<tbody>
<c:if test="${not empty userList}">
<c:forEach items="${userList}" var="u1">
<tr>
<td>${u1.id}</td><td>${u1.username}</td>
<td>${u1.password}</td>
<td><fmt:formatDate value="${u1.birth}" pattern="yyyy年M月d日E"/></td>
<td>${true==u1.sex?'男':'女'}</td>
<td>删除修改</td>
</tr>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>