1、使用IDEA中提供的项目初始化器完成项目的创建
这里的视图采用JSP,SpringBoot已经不建议使用JSP
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.0.1version>
<relativePath/>
parent>
<groupId>com.yangroupId>
<artifactId>demo0111artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demo0111name>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>17java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.4.6version>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.mysqlgroupId>
<artifactId>mysql-connector-jartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
2、使用yaml格式的配置文件,所以需要修改application.properties为application.yml
# 数据源的配置,这里没有引入druid,所以使用的是HikariCP连接池
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///test?serverTimezone=UTC
username: root
password: 123456
编写创建表所使用的sql语句和初始化表的数据
在resources目录下创建文件夹database,其中添加文件schema.sql其中包含创建表的sql语句,添加文件data.sql其中包含初始化表数据的sql语句
create table if not exists tb_users(
id bigint primary key auto_increment,
username varchar(32) not null unique,
password varchar(32) not null,
birth date,
sex boolean default 1
)engine=innodb default charset utf8;
初始化表中的数据
delete from tb_users;
insert into tb_users values(1,'zhangsan','123456','1989-2-3',0);
insert into tb_users values(2,'lisi','123456','2017-4-5',0);
insert into tb_users values(3,'yanjun','123456','2018-4-8',1);
添加配置使SpringBoot启动时自动执行sql文件完成表的初始化操作
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///test?serverTimezone=UTC
username: root
password: 123456
sql:
init:
mode: always
schema-locations: classpath:database/schema.sql
data-locations: classpath:database/data.sql
添加web应用相关的配置,例如视图解析器所使用的参数
spring:
mvc:
view:
prefix: /WEB-INF/content/ # 视图解析器的前缀
suffix: .jsp # 视图解析器的后缀
在src/main目录下创建文件夹webapp用于存储jsp页面,静态资源遵循管理存储在resources/static目录下
添加控制器
@Controller
public class IndexController {
@RequestMapping({"","/","index"})
public String index(){
return "index";
}
}
如果页面显示正常,则表示开发环境已经搭建完毕
3、使用MyBatis的反向引擎生成对应的实体类、映射源文件和接口
需要引入反向映射的插件mybatis-generator-maven-plugin。需要注意一般在具体开发中为了避免在开发工程中引入额外的内容,所以一般是创建一个独立项目执行反向映射
针对反向映射生成的文件进行调整。
映射元文件
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yan.dao.UserMapper">
<resultMap id="BaseResultMap" type="com.yan.entity.User">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="username" jdbcType="VARCHAR" property="username"/>
<result column="password" jdbcType="VARCHAR" property="password"/>
<result column="birth" jdbcType="DATE" property="birth"/>
<result column="sex" jdbcType="BOOLEAN" property="sex"/>
resultMap>
<sql id="Base_Column_List">
id, username, password, birth, sex
sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from tb_users
where id = #{id,jdbcType=BIGINT}
select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete
from tb_users
where id = #{id,jdbcType=BIGINT}
delete>
<insert id="insertSelective" parameterType="com.yan.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into tb_users
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
username,
if>
<if test="password != null">
password,
if>
<if test="birth != null">
birth,
if>
<if test="sex != null">
sex,
if>
trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">
#{username,jdbcType=VARCHAR},
if>
<if test="password != null">
#{password,jdbcType=VARCHAR},
if>
<if test="birth != null">
#{birth,jdbcType=DATE},
if>
<if test="sex != null">
#{sex,jdbcType=BOOLEAN},
if>
trim>
insert>
<update id="updateByPrimaryKeySelective" parameterType="com.yan.entity.User">
update tb_users
<set>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
if>
<if test="password != null">
password = #{password,jdbcType=VARCHAR},
if>
<if test="birth != null">
birth = #{birth,jdbcType=DATE},
if>
<if test="sex != null">
sex = #{sex,jdbcType=BOOLEAN},
if>
set>
where id = #{id,jdbcType=BIGINT}
update>
<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.yan.entity.User">
select
<include refid="Base_Column_List"/>
from tb_users where 1=1
<if test="username != null">
and username like #{username,jdbcType=VARCHAR}
if>
<if test="password != null">
and password = #{password,jdbcType=VARCHAR}
if>
<if test="birth != null">
and birth = #{birth,jdbcType=DATE}
if>
<if test="sex != null">
and sex = #{sex,jdbcType=BOOLEAN}
if>
<if test="id!=null">
and id = #{id,jdbcType=BIGINT}
if>
select>
mapper>
实体类
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private Date birth;
private Boolean sex;
}
新增一个mapper接口的通用接口
public interface SqlMapper<T extends Serializable,ID extends Serializable> {
int deleteByPrimaryKey(ID id);
int insertSelective(T record);
T selectByPrimaryKey(ID id);
int updateByPrimaryKeySelective(T record);
List<T> selectByExample(T record);
}
修改生成的映射接口
@Repository //添加这个注解的目的主要在于使IDEA不报错,实际上没有必要
public interface UserMapper extends SqlMapper<User,Long>{
}
添加MyBatis相关的配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 用于开发阶段在控制台上输出所指定的SQL语句
mapper-locations: classpath:mapper/*.xml # 用于注册映射元文件
修改主类,在主类上添加一个注解用于自动扫描mapper接口
@SpringBootApplication
@MapperScan(value = "com.yan.dao",markerInterface = SqlMapper.class)
public class Demo0111Application {
public static void main(String[] args) {
SpringApplication.run(Demo0111Application.class, args);
}
}
使用SpringBoot提供的单元测试检测配置是否有错误。在具体开发中一般不会针对dao进行测试,因为dao的具体实现实际上是依赖于MyBatis框架来实现的
Spring Boot的项目初始化器自动提供了一个测试主类,可以使用这个测试主类进行简单验证
@SpringBootTest
class Demo0111ApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
System.out.println(userMapper);
User user=new User();
user.setUsername("zhaoliu");
user.setPassword("666666");
user.setBirth(new Date());
user.setSex(false);
int rows = userMapper.insertSelective(user);
Assertions.assertEquals(1,rows);
}
}
4、添加业务层,不要忘记在业务代码中引入声明式事务管理。从理论上来说,不应该使用实体类进行层与层之间的数据传递,但是为了简化开发,提高开发效率,可以使用实体类用于数据传递
首先定义接口,推荐使用的是JDK动态代理
public interface IUserServ {
boolean create(User user);
boolean exists(String username);
}
添加实现类
@Service
public class UserServImpl implements IUserServ{
@Autowired
private UserMapper userMapper;
@Override
public boolean create(User user) {
Assert.notNull(user,"参数不允许为空!");
Assert.hasText(user.getUsername(),"用户名称不允许为空!");
Assert.hasLength(user.getPassword(),"用户口令不允许为空!");
boolean bb=exists(user.getUsername());
if(bb)
throw new IllegalArgumentException("用户名称已经被占用!");
int res=userMapper.insertSelective(user);
return res>0;
}
@Override
public boolean exists(String username) {
Assert.hasText(username,"用户名称不能为空!");
User tmp=new User();
tmp.setUsername(username.trim());
List<User> userList=userMapper.selectByExample(tmp);
return userList!=null && userList.size()>0;
}
}
进行单元测试,甚至有地方还使用TDD测试驱动开发方式
在具体开发中如果时间允许,实际上针对所有的可能都应该覆盖测试到
@SpringBootTest
class Demo0111ApplicationTests {
@Autowired
private IUserServ userService;
@Test
void contextLoads() {
}
@Test
void testCreate(){
User user=new User();
user.setUsername("yan111");
user.setPassword("111111");
user.setSex(false);
boolean res= userService.create(user);
Assertions.assertTrue(res);
}
}
从控制台上查看输出日志信息
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16b7e04a] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@2042950203 wrapping com.mysql.cj.jdbc.ConnectionImpl@5a566922] will not be managed by Spring
==> Preparing: select id, username, password, birth, sex from tb_users where 1=1 and username like ?
==> Parameters: yan111(String)
<== Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16b7e04a]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b788dc2] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@172290043 wrapping com.mysql.cj.jdbc.ConnectionImpl@5a566922] will not be managed by Spring
==> Preparing: insert into tb_users ( username, password, sex ) values ( ?, ?, ? )
==> Parameters: yan111(String), 111111(String), false(Boolean)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b788dc2]
这里开发发现使用的是non transactional SqlSession,没有使用事务
修改主类添加注解@EnableTransactionManagement使声明式事务生效
@SpringBootApplication
@MapperScan(value = "com.yan.dao",markerInterface = SqlMapper.class)
@EnableTransactionManagement
public class Demo0111Application {
public static void main(String[] args) {
SpringApplication.run(Demo0111Application.class, args);
}
}
修改业务实现类,添加事务相关特性的声明注解
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
@Service
public class UserServImpl implements IUserServ{
@Autowired
private UserMapper userMapper;
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public boolean create(User user) {
Assert.notNull(user,"参数不允许为空!");
Assert.hasText(user.getUsername(),"用户名称不允许为空!");
Assert.hasLength(user.getPassword(),"用户口令不允许为空!");
boolean bb=exists(user.getUsername());
if(bb)
throw new IllegalArgumentException("用户名称已经被占用!");
int res=userMapper.insertSelective(user);
return res>0;
}
@Override
public boolean exists(String username) {
Assert.hasText(username,"用户名称不能为空!");
User tmp=new User();
tmp.setUsername(username.trim());
List<User> userList=userMapper.selectByExample(tmp);
return userList!=null && userList.size()>0;
}
}
删除刚刚插入的数据,重新执行单元测试,查看控制器输出
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
JDBC Connection [HikariProxyConnection@1133655596 wrapping com.mysql.cj.jdbc.ConnectionImpl@668cc9a2] will be managed by Spring
==> Preparing: select id, username, password, birth, sex from tb_users where 1=1 and username like ?
==> Parameters: yan111(String)
<== Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1] from current transaction
==> Preparing: insert into tb_users ( username, password, sex ) values ( ?, ?, ? )
==> Parameters: yan111(String), 111111(String), false(Boolean)
<== Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ceb68a1]
从这里可以看到事务生效transactional SqlSession
5、编写表现层相关代码,从而总结出业务层需要提供的方法
修改控制器,如果用户已经登录则直接进入显示所有用户信息【分页】,如果用户没有登录则字节打开登录输入页面
@Controller
public class IndexController {
@RequestMapping({"","/","index"})
public String index(HttpServletRequest request){
HttpSession session= request.getSession();
Object obj=session.getAttribute("userInfo");
if(obj!=null && obj instanceof User)
return "redirect:/admin/user/show";
else
return "redirect:/user/login";
}
}
注意这里的request类型为jakarta.servlet.http.HttpServletRequest,不是原来的包名称。这是因为这里使用的是Tomcat10,支持的是JavaEE9,包名称统一进行了调整
定义用户相关的控制器,因为有登录后和没有登录之分,所以建议使用两个不同的控制器进行处理。非使用一个控制器实际上也可以,但是判断是否需要登录不够方便。
@Controller
@RequestMapping("/user")
public class UserController {
}
需要登录后才能访问的控制器
@Controller
@RequestMapping("/admin/user")
public class AdminUserController {
}
继续修改UserController处理登录流程
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/login")
public String login(Model model){
User user=new User();
model.addAttribute("user",user);
return "user/login";
}
}
在content目录下创建登录输入页面,记住由于包名称的变化,所以前面添加的jstl依赖是有问题的,因为它支持的原始的包名称java…
用户名称:
用户口令:
页面正常显示表示显示登录页面的流程正确
定义控制器接收用户提交数据,使用模型驱动的方式接收数据。由于在业务中已经添加了创建方法,所以先调用业务中的创建进行流程的验证
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserServ userService;
@GetMapping("/login")
public String login(Model model){
User user=new User();
model.addAttribute("user",user);
return "user/login";
}
@PostMapping("/login")
public String login(User user, Errors errors)throws Exception{
try {
boolean res = userService.create(user);
return "redirect:/admin/user/show";
} catch (Exception e){
errors.rejectValue("msg",null,e.getMessage());
return "user/login";
}
}
}
修改jsp页面进行报错信息显示
用户名称:
用户口令:
在控制器中添加服务器端数据校验
@PostMapping("/login")
public String login(@Validated User user, Errors errors)throws Exception{
try {
boolean res = userService.create(user);
return "redirect:/admin/user/show";
} catch (Exception e){
errors.rejectValue("msg",null,e.getMessage());
return "user/login";
}
}
修改实体类添加验证规则
@Data
public class User implements Serializable {
private Long id;
@NotBlank(message = "用户名称不能为空!",groups = UserGroup.LoginFirstGroup.class)
@Size(min = 6,max = 20,message = "用户名称应该是{min}到{max}个字符",groups = UserGroup.LoginSecondGroup.class)
private String username;
@NotBlank(message = "用户口令不能为空!",groups = UserGroup.LoginFirstGroup.class)
@Size(min = 6,max = 20,message = "用户口令应该是{min}到{max}个字符",groups = UserGroup.LoginSecondGroup.class)
private String password;
使用校验分组实现第一个校验通过才执行第二个校验,不会所有校验都要执行
public interface UserGroup {
@GroupSequence({LoginFirstGroup.class,LoginSecondGroup.class})
public interface LoginGroup{}
public interface LoginFirstGroup{}
public interface LoginSecondGroup{}
}
修改控制器的方法添加配置指定执行的验证分组
@PostMapping("/login")
public String login(@Validated(UserGroup.LoginGroup.class) User user, Errors errors)throws Exception{
if(errors.hasErrors())
return "user/login";
try {
boolean res = userService.create(user);
return "redirect:/admin/user/show";
} catch (Exception e){
errors.rejectValue("msg",null,e.getMessage());
return "user/login";
}
}
5、web显示相关配置
默认情况下当SpringBoot应用启动时会在控制台显示一个logo
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.1)
这个logo可以关闭显示
方法1:在配置文件中进行设置 spring.main.show-banner: off,这种方式已经不再推荐使用
方法2:在主类中使用编程的方式关闭logo的显示
SpringApplication application = new SpringApplication(Demo0111Application.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
setBannerMode参数为Mode,其中可以配置的的值为Mode的枚举类型值,OFF关闭banner显示,CONSOLE默认值表示在控制台上显示logo,LOG表示在日志记录中显示logo
允许用户自定义修改所显示的logo
仅需要创建一个banner.txt文件,放到项目resources目录就行了,banner.txt里的内容,就会显示到logo位置
自定义时需要注意banner.txt的编码字符集问题,可以将txt文件的编码字符集设置为UTF-8即可
允许修改txt文件读取时所识别的编码字符集
spring.banner.charset: UTF-8
日志系统
日志对于应用程序的重要性不言而喻,不管是记录运行情况还是追踪线上问题,都离不开对日志的分析,
在Java领域里存在着多种日志框架,如JUL、Log4j、Log4j2、Commons Loggin、Slf4j和Logback
等
在开发的时候不应该直接使用日志实现类,应该使用日志的抽象层
Logger logger = LoggerFactory.getLogger(getClass());
控制器编程使用日志系统输出调试信息
private static Logger logger= LoggerFactory.getLogger(UserController.class);
@PostMapping("/login")
public String login(@Validated(UserGroup.LoginGroup.class) User user, Errors errors, Model model) throws Exception {
logger.info("登录系统,提交数据为:"+user);
if (errors.hasErrors())
return "user/login";
try {
boolean res = userService.login(user);
if (res) {
model.addAttribute("userInfo", user);
logger.debug("登录成功");
return "redirect:/admin/user/show";
}else{
logger.debug("登录失败,重新登录");
errors.rejectValue("msg",null,"登录失败!请重新登录");
return "user/login";
}
} catch (Exception e) {
errors.rejectValue("msg", null, e.getMessage());
return "user/login";
}
}
日志级别从小到大为 trace < debug < info < warn < error ,Spring Boot 默认日志级别为 INFO
如果使用log4j输出日志信息,可以在resources目录下添加log4j.properties
log4j.rootLogger = debug,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
如果需要log4j日志框架无效,只要把resources目录下的log4j.properties移动到其它位置即可。
SpringBoot默认采用logback日志框架,可以配置采用其他框架。可以直接在application.yml配置,例如日志级别、输出文件等
配置信息
logging.level.root=info
logging.file=./logs/log.log #输出位置
logging.config=classpath:logback-spring.xml配置中指定了配置文件,在项目resources文件夹下。也可以不指定,只要配置文件名按默认风格命名即可
6、登录成功后显示用户信息
分页相关参数的传递
@Data
public class PageBean implements Serializable {
private int pageNum;//当前页码值
private int rowsNum;//总行数
private int maxPage;//最大页码值
private int rowsPerPage;//每页行数
}
首先控制台结束分页相关数据,如果没有对应的数据,则会使用RequestParam中定义的默认值
实际上分页处理是依靠pagehelper插件实现的,并不是使用MyBatis的rowbound进行分页的
使用pagehelper是物理分页,需要添加依赖pagehelper-spring-boot-starter
配置相关的参数
pagehelper:
helper-dialect: mysql # 告知插件所使用的数据库方言,因为不同的数据库平台使用的不同的关键字实现分页处理。例如mysql使用limit,oracle使用rownum
reasonable: true # 设置分页插件针对分页参数进行合理化处理,例如没有-1页
业务类中查询操作
public List<User> getByPage(PageBean pages) {
Page<Object> pageInfo = PageHelper.startPage(pages.getPageNum(), pages.getRowsPerPage());
List<User> res=userMapper.selectByExample(null);
pages.setPageNum(pageInfo.getPageNum());
pages.setRowsNum(pageInfo.getTotal());
pages.setMaxPage(pageInfo.getPages());
return res;
}
控制器调用业务方法执行查询,并将查询结果存储到model中,转向显示页面进行数据显示
@Controller
@RequestMapping("/admin/user")
public class AdminUserController {
@Autowired
private IUserServ userService;
/**
* 用于分页显示所有的用户信息
*
* @param page 需要显示的页码值
* @param size 每行行数
* @return 逻辑地址名,需要在页面上显示的数据会通过方法参数model进行数据传递
*/
@RequestMapping("/show")
public String show(@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "15") int size, Model model) {
PageBean pages=new PageBean();
pages.setPageNum(page);
pages.setRowsPerPage(size);
List<User> userList=userService.getByPage(pages);
model.addAttribute("userList",userList);
model.addAttribute("pages",pages);
return "user/show";
}
}
页面显示报错,原因是jstl 1.2中的包名称和当前的包名称不一致,应该修改对应的依赖
<dependency>
<groupId>jakarta.servlet.jsp.jstlgroupId>
<artifactId>jakarta.servlet.jsp.jstl-apiartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>org.glassfish.webgroupId>
<artifactId>jakarta.servlet.jsp.jstlartifactId>
<version>3.0.1version>
dependency>
显示数据的jsp页面
用户编号
用户名称
用户口令
出生日期
性别
操作
${user.id}
${user.username}
${user.password}
${user.sex?"男":"女"}
删除
修改
第一页
上一页
下一页
末尾页
添加新用户
存放静态资源的位置
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
自定义静态资源目录
优先级顺序/META-INF/resources>resources>static>public,一般使用static目录存放静态资源
不想使用默认静态资源文件夹,允许创建静态资源文件夹进行放置静态资源
spring.web.resources.static-locations= classpath:/test11/
配置了自定义文件夹以后,原有的静态资源文件夹就失效了,想要继续使用,可以把原文件夹也写入该配置中
注意测试中缓存问题,需要进行一下缓存清除。最简单的办法就是使用另一个浏览器进行访问就可以了
代码配置
少量的简单配置可以完全依赖于application.properties或者application.yaml进行配置。如果比较复杂的配置可以考虑使用JavaConfig配置类来实现
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/test11/"
);
}
}
addResourceHandler针对静态资源的路径,表示访问当前应用根目录下的所有静态资源
addResourceLocations设置对应的存放位置
例如访问/images/29.jpg则对应的存放位置为/test11/images/29.jpg
应用的logo图标
只需要将ico图标放置在静态文件夹根路径下即可,不是images目录下,默认图标的命名favicon.ico
可以在阿里巴巴矢量图标库寻找合适的图标地址https://www.iconfont.cn/
自定义的js可以直接存储在静态文件夹的默认路径下即可使用相对路径引用
<script src="jslib/test1.js"></script>
WebJars是将web前端资源打成jar包文件。借助版本管理工具(Maven、gradle等)进行版本管理,保证这些Web资源版本唯一性。
避免了文件混乱、版本不一致等问题。实际上一般的方法是从官方下载对应的js文件,拷贝到statis/jslib/目录下即可,不是由maven管理
在pom.xml添加依赖
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>jqueryartifactId>
<version>3.5.1version>
dependency>
在页面中引入对应的js文件
页面中使用webjars
<script src="/webjars/jquery/3.5.1/jquery.min.js"></script>
<script>
$(function(){
alert('DOM加载完毕!');
});
</script>
为了隐藏版本号可以使用依赖webjars-locator-core
对应的pom.xml
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>webjars-locator-coreartifactId>
<version>0.52version>
dependency>
webjars对前端依赖进行统一管理
1、静态资源版本化:传统的静态资源需要自行维护,资源种类繁多,使得项目后期越来越臃肿,维护版
本升级也变得困难,
而使用webjars方式进行管理后,版本升级问题迎刃而解
2、提升编译速度:使用webjars的方式管理依赖可以给项目的编译速度带来2-5倍的速度提升专门写的js文件或者下载好的静态资源也可以使用webjar的方式发布到公司私服仓库
新建一个springboot项目,创建目录META-INF/resources/ ,将静态资源完整复制进去,然后发布公司maven私服即可